C fscanf читает одну и ту же строку дважды? - PullRequest
0 голосов
/ 19 ноября 2018

Итак, мое задание - создать ассемблер на C. Так что большая часть работы у меня работает, но первая часть заключается в сканировании файла сборки, поиске меток и назначении правильного местоположения «счетчика программы» для каждой метки. Все прекрасно работает, если внизу нет метки с пустой строкой и директивой .end после нее. Я попытался напечатать каждую строку, чтобы увидеть, что она читает, и кажется, что она читает последнюю метку дважды, и, таким образом, она увеличивает счетчик моей программы в два раза для одной и той же метки, и это неверно только для этой метки, и я не могу выяснить, в чем проблема. Любая помощь приветствуется. На данный момент я не добавил никакой логики к каждой команде, кроме как для увеличения 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 голосов
/ 19 ноября 2018

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.
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...