Чтение числа из файла и преобразование его в целое число в C - PullRequest
0 голосов
/ 17 октября 2011

У меня есть переменная FILE, объявленная как FILE *fin. fin = fopen( "points.dat", "r" ); инициализируется после объявления. Я пытался перебрать fin пока fgetc( fin ) != '\n'. Вот где я в тупике.

Я хочу сохранить каждый символ в строке 1 points.dat в char *, который позже я могу вызвать atoi для хранения в виде целого числа. Как мне это сделать? Я пробовал это, но я продолжаю получать ошибки сегментации и другие странные ошибки. Вот моя последняя попытка:

FILE *fin;
char c;
int counter = 0;
int countPoints;
char *readFirst;

fin = fopen( "points.dat", "r" );

while( ( c = fgetc( fin ) ) != '\n' ) {

    readFirst[counter] = c;
    counter++;
}

countPoints = atoi( readFirst );

printf("%d\n", countPoints);

Примечание: это не является домашним заданием. Это очень маленькая вещь, которую мне нужно получить, прежде чем я действительно смогу выполнить домашнее задание.

Ответы [ 5 ]

2 голосов
/ 17 октября 2011

Вы не выделили никакой памяти для readFirst, а также она не заканчивается символом NULL, как ожидает C.

Лучше использовать fgets для чтения строки и fputs для записи строки. Таким образом, вам не нужно искать новую строку. Также будет полезно, если вы отправите код записи в файл.

Вы также можете использовать стандартную обработку файлов c ++ (используя std :: iostream), чтобы сделать работу еще проще.

1 голос
/ 17 октября 2011

Вы получаете ошибку сегментации, потому что char *readFirst; только объявляет указатель, но не оставляет места для хранения данных.

Либо объявляйте readFirst непосредственно как массив (char readFirst[size];) или используйте функцию malloc() для выделения места.

0 голосов
/ 17 октября 2011

Когда я вижу это правильно, вы просто используете указатель char, не инициализируя его чем-либо.Это означает, что ваш указатель указывает на некоторую неизвестную область памяти.Если вам повезет, вы получите ошибку сегментации (вот почему инициализация указателя на NULL - хорошая идея), если нет: добро пожаловать в царство неопределенности.

Если вы хотите сохранить что-то, вам следует сначаласоздать немного памяти для этого.Вы можете сделать это либо в стеке (char readFirst[size]), либо в куче (malloc()).В любом случае вам нужно заранее знать, сколько памяти вам понадобится.Вы должны знать это во время компиляции для варианта стека и во время выполнения для варианта кучи.Это, конечно, означает, что вам нужен метод, чтобы узнать, сколько памяти вам понадобится.

0 голосов
/ 17 октября 2011

Что ж, непосредственная проблема заключается в том, что вы не выделили памяти для readFirst, чтобы указать на . Когда вы пишете readFirst[counter] = c, вы пытаетесь присвоить значение c некоторой случайной ячейке памяти, которая может вам принадлежать или не принадлежать (отсюда и segfaults).

Если вы знаете, насколько большим массив должен быть раньше времени, вы должны объявить readFirst как

char readFirst[SIZE];

Для представления десятичной цифры в среднем требуется примерно 3,3 бита; округлите его до 3, и вы можете измерить размер вашего массива как битовую ширину int, деленную на 3 плюс 2 для знака и 0 в качестве разделителя. Таким образом, 32-битному int потребуется массив из 9 + 2 = 11 символов. 64-битное целочисленное значение потребует 22 + 2 = 24.

Но это все вызывает другой вопрос; Вам нужно , чтобы прочитать ввод по одному символу за раз, а затем преобразовать в целочисленное значение? Если входной файл представляет собой просто текстовые представления целых чисел, вы можете обойти весь этот беспорядок и просто использовать fscanf со спецификатором преобразования %d (хотя это имеет свой собственный набор проблем).

В качестве альтернативы, вы можете использовать fgets для одновременного чтения всей текстовой строки и преобразования текста с использованием strtol (atoi не дает такой же возможности обработки ошибок, как strtol).

0 голосов
/ 17 октября 2011

readFirst - неинициализированный указатель на символ. Вам нужно либо выделить новый блок памяти для хранения символов, либо назначить его статически распределенному массиву символов. Кроме того, если вы собираетесь читать данные по одному байту за раз, вам нужно будет завершить строку нулем, прежде чем передать ее в atoi, иначе будет прочитано и конец буфера, и segfault.

Посмотри, сможешь ли ты понять это оттуда. Если вам нужна дополнительная помощь, напишите мне.

...