EOF не обнаружен C на Raspberry Pi

#c #gcc #raspberry-pi

#c #gcc #raspberry-pi

Вопрос:

Итак, я писал программу на моем Raspberry Pi Zero для подсчета частот разных длин слов во входных данных, но программа не остановилась на EOF.

Итак, я попробовал это для отладки:

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

void main() {
    char c;
    while ( (c = getchar()) != EOF) {
        putchar(c);
    }
}
  

И скомпилирован с этим:

 gcc test.c amp;amp; ./a.out <input.txt
  

Он распечатал входной текст, но затем просто продолжал печатать вопросительные знаки, пока я не нажму Ctrl C. Когда я скопировал программу на свой ноутбук и запустил ее там, все работало нормально.

Я мог бы просто закончить на ноутбуке, но мне любопытно. Почему Pi не может определить, когда файл попадает в EOF?

Ответ №1:

Первая пара фактов:

  • Символ EOF является макросом, который расширяется до целочисленной константы -1 . Эта целочисленная константа будет иметь тип int .
  • Это определяется реализацией, если char подписано или беззнаково. Один и тот же компилятор на разных платформах может иметь разные char реализации.

Теперь для длинного объяснения вашей проблемы:

Когда в арифметических выражениях используются целочисленные типы разных размеров (и сравнение считается арифметическим оператором), тогда оба операнда выражения подвергаются обычному арифметическому преобразованию для получения общего типа (обычно int ).

Для целых типов меньшего размера, таких как, например, char , это включает в себя целочисленное продвижение для преобразования его в int . Для этой акции значение char должно быть сохранено нетронутым, поэтому, например, -1 как a char по-прежнему будет -1 как int .

Из-за того, как в большинстве систем представлены отрицательные числа, char значение -1 равно (в шестнадцатеричном формате) 0xff . Для знака char , когда -1 преобразуется в int , он сохраняет значение -1 (которое будет представлено как 0xffffffff для 32-разрядного int типа).

Проблема возникает, когда char является беззнаковым, потому что тогда, когда getchar возвращается EOF (значение -1 ), беззнаковое char значение будет равно 255 (беззнаковое десятичное представление 0xff ). И при повышении до int значения все равно будет 255 . И 255 != -1 !

Вот почему getchar возвращаемый тип является int , а не char . И одна из причин, по которой все функции обработки символов используют int вместо char .

Итак, чтобы решить вашу проблему, вам нужно изменить тип переменной c на int :

 int c;
  

Тогда это сработает

Ответ №2:

getchar возвращает int значение, а не char значение. Поскольку вам нужен какой-то способ распознать в одной getchar функции, читаете ли вы обычный символ или функция сообщает вам, что больше читать нечего — кто-то давным-давно решил использовать int , чтобы можно было возвращать некоторое значение, большее char , для указания конца файла. Измените char на int .

Ответ №3:

getchar's return value предполагается, что он может возвращать любой символ ASCII (и расширенный ASCII) в диапазоне от 0 до 255.

Чтобы провести различие между ascii и EOF, EOF не может быть значением в этом интервале, поэтому возвращаемый тип getchar должен содержать более 8 бит.

    int getchar(void);
  

Итак, вы должны написать

 int c;
while ( (c = getchar()) != EOF) ...