Использование fscanf с циклом while для хранения char и int - PullRequest
0 голосов
/ 12 ноября 2018

Я пытаюсь использовать fscanf для чтения файла шестнадцатеричных чисел, в которых либо есть символ, за которым следуют цифры, либо только цифры, но без символа. Fscanf работает с первой строкой файла, но это все.

FILE

E10
20
22
18
E10
210
12

код

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char** argv) {
FILE * iFile;
char instr;
unsigned long long int address;

iFile = fopen("addresses.txt", "r");
if(iFile != NULL){

    while (fscanf(iFile, "%c%x", &instr, &address) > 0){

      printf("%c", instr);   //This just works for the first line

    }

}
fclose(iFile);
return 0;
}

1 Ответ

0 голосов
/ 12 ноября 2018

В таких случаях, когда вы будете пытаться анализировать одну и ту же строку много раз, лучше прочитать строку в память, а затем обработать данные в памяти, а не на диске.

char line[MAXLINE];
fgets(line, MAXLINE, iFile);

Тогда у вас есть то, что я называю "лестница sscanf", которая представляет собой серию предложений if - else if, каждая из которых пытается проанализировать line по-разному.Условие будет проверять возвращаемое значение sscanf, поскольку число успешно прочитанных объектов является возвращаемым значением.Поэтому мы используем это число для различения нескольких различных форматов:

if (sscanf(line, "%c%x", &instr, &address) == 2)
    /* you have an instruction and an address */
else if (sscanf(line, "%x", &address) == 1)
    /* you have an address only */

Поскольку в вашем случае это условие цикла, вам придется преобразовать его в собственную функцию:

int readAtLeastAddress(const char *const line, char *instr, unsigned long long *address)
{
    return sscanf(line, "%c%x", instr, address) == 2 || sscanf(line, "%x", &address) == 1;
}

Тогда вы бы переписали цикл как таковой

while (readAtLeastAddress(line, &instr, &address)) {
    printf("%c", instr);
}
...