将一行的前三个字符串读入单独的数组,然后将该行的其余部分读入 C 中的第四个字符串?

Read the first three strings of a line into individual arrays, then read the rest of the line into a fourth string in C?

我正在用 C 编写汇编程序的第一遍以进行赋值,需要读取包含汇编代码的文本文件行,并将标签、操作码和操作数以及任何注释存储在前三个字符串之后的行。我最初使用

fscanf(fileptr1,"%s\t%s\t%s",label,opcode,operand);

对于没有注释的文件,但 sscanf 无法将行的其余部分放入单个字符数组中。似乎我会使用 fgets,但我如何将它分成前三个字符串,用空格分隔,然后是该行的其余部分,直到换行符?

作为参考,各行遵循以下格式:

LABEL   OPCODE  OPERAND     COMMENTS IN MULTIPLE STRINGS

我想要单独字符串中的标签、操作码和操作数,就像我现在所做的那样,然后是一个单独的字符串用于整个行的其余部分。汇编代码中的几行供参考:

COPY    START   1000        COPY FILE FROM INPUT TO OUTPUT
FIRST   STL     RETADR      SAVE RETURN ADDRESS
CLOOP   JSUB    RDREC       READ INPUT RECORD
        LDA     LENGTH      TEST FOR EOF (LENGTH = 0)
        COMP    ZERO
        JEQ     ENDFIL      EXIT IF EOF FOUND
        JSUB    WRREC       WRITE OUTPUT RECORD
J       CLOOP   LOOP

为每个字段定义特定的分隔符

fscanf( fileptr1, "%[^\t] %[^\t] %[^\t] %[^\n]", label, opcode, operand, comment ) ;

您或许应该添加字段宽度说明符并检查 return 值,以检查错误和超限,但这是一个不同的问题。

但还有其他方法。例如,您可以 fgets() 将整行放入一个数组,然后使用 strtok() 将其拆分,使用 \t 作为分隔符。

char line[1024] = {0} ;

fgets( line, sizeof(line), fileptr1 ) ;

char* label = strtok( line, "\t" ) ;
char* opcode = label != 0 ? strtok( 0, "\t" ) : 0 ;
char* operand = opcode != 0 ? strtok( 0, "\t" ) : 0 ;
char* comment = operand != 0 ? strtok( 0, "\n" ) : 0 ;

第 1 步:阅读带有 fgets()

的行
char buffer[256];
while (fgets(buffer, sizeof buffer,fileptr1) {

how would I separate that into the first three strings separated by whitespace, ...

这是对问题的错误评估。在第一个 "string" 或 label 为空的 " LDA LENGTH TEST FOR EOF (LENGTH = 0)" 的情况下,3 "strings" 没有被空格分隔。

相反,代码需要查找缺失的字段。

第 2 步:有多种方法:下面是 try-it-1-of-2 方法,具体取决于前导字符是否为 white-space。通过测试 n

测试扫描是否成功
    char label[8];
    char opcode[8];
    char operand[12];
    char comment[sizeof buffer];  // big enough to handle the rest of the line
    label[0] = '[=11=]';
    opcode[0] = '[=11=]';
    operand[0] = '[=11=]';
    comment[0] = '[=11=]';

    int n = 0;  
    if (isspace((unsigned char) buffer[0])) {
      //                      vv--------- Save offset of scan if we got that far
      sscanf(buffer, "%7s%11s %n" , opcode, operand, &n); 
    } else {
      sscanf(buffer, "%7s%7s%11s %n" , label, opcode, operand, &n); 
    }
    if (n == 0) {
      // Handle bad input with TBD code
      continue;
    }
    // look for comment starting at `n`
    if (buffer[n]) {
      // scan in comment  
      sscanf(buffer + n, "%[^\n]" , comment); 
    }

    // do something with input
    printf("<%s> <%s> <%s> <%s>\n", label,opcode,operand,comment);
}

代码可以测试 "too long" 和 label,opcode,operand。示例:

    // Assume max length of opcode == 7
    char opcode[7 + 1 + 1];  // +1 for extra, +1 for null character
    ...
    sscanf(..., "...%8s...", .... opcode ...);
    if (opcode[7 + 1]) Handle_TooLoong();