C fscanf读取同一行两次吗?

时间:2018-11-19 05:01:45

标签: c file

因此,我的任务是在C中创建一个汇编器。因此,我的大部分工作都在进行,但是第一部分是扫描汇编文件并查找标签,并为每个标签分配正确的“程序计数器”位置。一切工作都很好,除非在底部有一个标签,在其下面有一个空白行,并在其后有一个.end指令。我尝试打印每一行以查看其正在读取的内容,似乎它正在读取最后一个标签两次,因此对于同一标签它两次将程序计数器加1,而对于该标签来说这是不正确的,而且我似乎无法找出问题所在。任何帮助表示赞赏。此时,除了增加lc之外,我没有为每个命令添加任何逻辑,因为这是完成这部分atm所需要做的全部工作。

int firstPass(FILE *infile, int labels[], int lc)
{
    char line[LINE_SIZE] = {};
    int lineCount = 0;
    int done = 0;
    int endFound = -1;
    char c;
    rewind(infile);
    while (fscanf(infile, "%[^\n]", line) != EOF && lineCount < LIMIT && !done)
    {
        lineCount++;
        fscanf(infile, "%c", &c);
        removeSpaces(line);
        toUpperCase(line);
        if (line[0] != 0 && line[0] != ';')
        {
            if (!strncmp(line, ".END", 4))
            {
                done = 1;
                endFound = 0;
            }
            else if(!strncmp(line, "LDR", 3))
            {   
                lc++;
            }
            else if(!strncmp(line, "LD", 2))
            {
                lc++;
            }
            else if(!strncmp(line, "ADD", 3))
            {
                lc++;
            }
            else if(!strncmp(line, "AND", 3))
            {
                lc++;
            }
            else if(!strncmp(line, "NOT", 3))
            {
                lc++;
            }
            else if(!strncmp(line, "STR", 3))
            {
                lc++;
            }
            else if(!strncmp(line, "ST", 2))
            {
                lc++;
            }
            else if(!strncmp(line, "BR", 2))
            {
                lc++;
            }
            else if(!strncmp(line, "TRAP", 4))
            {
                lc++;
            }
            else if (line[0] == 'L' && line[1] >= '0' && line[1] <= '9')
            {
                if (line[2] == '.')
                {
                    labels[line[1] - '0'] = lc;
                    lc++;
                }
                else
                {
                    labels[line[1] - '0'] = lc;
                }
            }
        }
    }
    if (endFound == -1)
    {
        printf("ERROR 4: Missing end directive.\n");
    }
    return endFound;
}

这是我正在使用的测试文件。

;Test file for assembly

;This is a comment

.orig x3000
    ADD R1, R2, R3
    add R0, R3, #10

    and R1, R1, R2
    AND R0, R3, #-10
L0          
    BR L1
    BRN L0
    BRZ L1
    BRP L0
    BRNZ L1
    BRNP L0
    BRZP L1
    BRNZP L0
    LD R1, L2
    LDR R1, R2, #-5
    L1          
    NOT R3, R4      
    ST R5, L2
    STR R6, R1, #-5 
    TRAP x20
    TRAP x21
    TRAP x22
    TRAP x23
    TRAP x24
    TRAP x25
    L2  .FILL   0   
L3  .FILL   0   
L4  .FILL   0

.END

每当我将标签打印到控制台时,它都会打印

L0

L1

L2 .FILL 0
L3 .FILL 0
L4 .FILL 0
L4 .FILL 0

我似乎无法弄清为什么它似乎两次读取L4。

1 个答案:

答案 0 :(得分:4)

fscanf主要返回成功读入的项目数。如果您有一个空行(即只有一个新行),那么fscanf(infile, "%[^\n]", line)将不会读入任何内容到line中,并且line保持不变(即文件中前一行的值)。

要解决此问题,请更准确地检查fscanf的返回值:

int fscanfResult;
while ((fscanfResult=fscanf(infile, "%[^\n]", line) != EOF && ...) {
   if (fscanfResult == 0) {
      fgets(line,infile);  // take the new line out of the buffer.
      continue;
   }
   ...

通常,我倾向于使用fgets阅读完整的行,然后进行解析。 fscanf在使用它来扫描基于行的输入时有很多陷阱。

如果必须保持while部分不变,那么检测空行的另一种方法是在下一个fscanf之前重置缓冲区:

while (fscanf(infile, "%[^\n]", line) != EOF && lineCount < LIMIT && !done) {
  if (!line[0]) { // nothing read in?
      fgets(line,infile);  // take the new line out of the buffer.
      continue;
  }

  ....
  // all your logic goes here
  ....
  line[0] = '\0'; // clear the buffer; if fscanf then does not read in anything, line remains empty.
}