Почему при сравнении результата scanf () с NULL выдается предупреждение компилятора? - PullRequest
0 голосов
/ 08 сентября 2018

Я пишу на C, и мне нужно прочитать все, что поступает на вход, но я не знаю, сколько символов я получу. Я написал

while (scanf("%c", &read) != NULL)

но компилятор говорит мне: [Warning] comparison between pointer and integer, так что мне вместо этого писать?

Ответы [ 2 ]

0 голосов
/ 08 сентября 2018

Ваш

scanf("%c", &read) != NULL

является опечаткой: типы левого и правого операнда для != не совпадают. Читайте о системах типа .

Прочитайте документацию scanf. Он говорит, что scanf возвращает некоторое значение int.

Но NULL - это значение указателя (это (void*)0).

Как может указатель по смыслу сравниваться с int? На моем Debian / x86-64 они даже не имеют одинаковый размер (как возвращается sizeof): указатель занимает 8 байтов, а int занимает 4 байта.

Так что компилятор предупреждает вас правильно.

Вы, вероятно, хотите вместо этого кодировать что-то вроде while (scanf("%c", &read) >0) или даже while (scanf("%c", &read) == 1), поскольку для успешного сканирования "%c" задокументирована функция scanf, которая дает 1.

Конечно, в этом конкретном случае лучше использовать fgetc (более читабельно и, возможно, немного быстрее). Прочитайте документацию fgetc и следуйте советам, данным ответом Шеффа .

В следующий раз:

  • обязательно прочитайте документацию из каждой функции, которую вы используете. Никогда не используйте функцию, документацию которой вы не прочитали и не поняли.

  • попросить компилятор выдать все предупреждения и отладочную информацию, поэтому с GCC compile с gcc -Wall -Wextra -g. Доверьтесь своему компилятору и улучшите свой код, чтобы вообще не получать предупреждений .

  • read Как отлаживать небольшие программы .

  • Прочтите документацию gdb (и, возможно, valgrind ).

  • Изучите, для вдохновения, исходный код небольшого бесплатного программного обеспечения , аналогичного вашему (возможно, на github ).

PS. Имя вашей переменной read - плохой вкус. Для большинства людей это конфликтует с функцией POSIX read.

0 голосов
/ 08 сентября 2018

Вместо scanf("%c", &read) вы можете рассмотреть read = getc(stdin).

Обратите внимание, что getc() / fgetc() возврат int.

Это позволяет сохранить любой символ в виде числа в диапазоне [0, 255], а также вернуть EOF (обычно -1) в случае сбоя.

Итак, с getc() это будет выглядеть так:

int read;
while ((read = getc(stdin)) != EOF)

Примечание:

Вы можете присвоить read переменной типа char & ndash; это будет неявно преобразовано. В случае успешного выполнения getc() при неявном преобразовании не должно быть потери данных.


Небольшой пример, чтобы показать это на работе:

#include <stdio.h>

int main(void)
{
  enum { N = 10 };
  char buffer[N];
  /* read characters and print if buffer ful */
  int read, n = 0;
  while ((read = getc(stdin)) != EOF) {
    if (n == N) {
      printf("%.*s", N, buffer); n = 0;
    }
    buffer[n++] = read;
  }
  /* print rest if buffer not empty */
  if (n > 0) printf("%.*s", n, buffer);
  /* done */
  return 0;
}

Примечание:

Считанные символы хранятся в buffer без окончания '\0'. Это обрабатывается в printf() соответственно форматером %.*s, означающим строку с макс. ширина * где ширина и строка считаются последовательными аргументами.

Демонстрация в реальном времени на ideone

...