#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) ...