Лучший способ получить номера от ввода?

Я хотел бы сгенерировать символ по символу из входного файла с текстом и цифрами. Я думал, что могу просто петли...

   char count;

    while( c != ' ' && c != '\n' && c != '\t' ) {
        count += c;
        c = fgetc(fp);
    }

сказать "11" из текстового файла, а затем использовать atoi для преобразования в int, но я понял, что просто добавляю ASCII-номера. Я новичок в C, и из того, что я понимаю, это просто char массивы. Значит ли это, что я должен поставить "1" и "1" в массив char? Но тогда мне придется беспокоиться о размере массива и преобразовании его в число?

Ответ 1

Хотя это выглядит как естественное решение, я обычно советю использовать fscanf() для потенциально искаженного ввода.

В функции есть несколько проблем, среди которых:

  • Невозможность восстановления из-за ошибки из-за ошибки (меньше ftell()/fseek()), потому что вы не знаете, где именно он остановил синтаксический анализ.
  • Легкость, с которой она приводит к использованию неинициализированных значений (если формат не соответствует вводу, и вы не правильно проверяли код возврата).
  • Некоторые угловые случаи, когда fscanf() дросселируют на входе, где atoi()/strtol() не ( "0xz" ...).

Все это отбрасывает fscanf() для чтения только форматированного ввода, т.е. того, что ваша собственная программа написала ранее в известном формате.

Для любого типа ввода, который может отсутствовать в ожидаемом формате, Я рекомендую читать строку за раз (fgets()) и анализировать ее в памяти, например, с помощью strtol():

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#define LINE_BUFFER_SIZE 256;

// ...
char line[ LINE_BUFFER_SIZE ];
fgets( line, LINE_BUFFER_SIZE, fp );
char * scanptr;
errno = 0;
long number = strtol( line, &scanptr, 0 );
if ( scanptr == line )
{
    // not a number...
}
  • scanptr теперь указывает на то, где закончилось парсинг чисел.
  • number содержит число проанализированных, 0, если строка не начиналась с числа, а LONG_MAX соответственно. LONG_MIN, если найденное число вне диапазона long (и в этом случае errno == ERANGE).

Я не знаю ваших точных требований, поэтому я не могу дать хороший пример, что делать, если вы не найдете номер или что делать с текстом. Но так как вы получили строку (или, первые LINE_BUFFER_SIZE символы более длинной строки...) в памяти, у вас есть весь диапазон строки функции в вашем распоряжении. strpbrk( line, "0123456789" ) можно использовать для сканирования следующей цифры или strpbrk( line, "+-0123456789" ), если у вас может быть +- на вашем входе...

Ответ 2

Большинство людей будут использовать fscanf:

int number, items_scanned;
items_scanned = fscanf(fp, "%d", &number);
if (items_scanned == 0) {
     /* Scanning for a number failed */
     printf("Scan failed!\n");
}
printf("Found number: %d\n", number);

fscanf пропускает пробелы. Он будет успешным, если он найдет число и потерпит неудачу, если найдет что-то еще.