Прочитайте фиксированное количество символов, используя fgets в C

Я пытаюсь использовать функцию fgets() в C для чтения 8 символов и должно быть 8 символов из стандартного ввода.

Пока что у меня есть это

    char HEX[9];
    while (fgets(HEX, 8, stdin) != NULL)
    {
      if (HEX[8] == '\0')
      {
        printf("GOOD\n");
        break;
      }
      else
      {
        printf("Not 8 characters");
      }
    }

Но это не работает. Любые идеи? Также пробовал использовать if (strlen(HEX) > 8), но ни то, ни другое.

Заранее спасибо.


person Skynight    schedule 30.07.2013    source источник
comment
Что происходит и почему вы говорите, что это не работает?   -  person Magn3s1um    schedule 31.07.2013
comment
fread может быть вариант?   -  person Justin Meiners    schedule 31.07.2013
comment
Я считаю, что это HEX[9] должно быть '\0', а не HEX[8], верно?   -  person Natan Streppel    schedule 31.07.2013
comment
Массивы начинаются с индекса 0, но инициализируются фактическим размером, что означает, что в этом случае последнее значение равно size-1 = 8.   -  person Magn3s1um    schedule 31.07.2013
comment
О, мой плохой. Кажется, я сегодня выпил слишком много кофе.   -  person Natan Streppel    schedule 31.07.2013
comment
@Streppel Нет, [8] верно, [9] будет за пределами допустимого. Помните, что он имеет индекс 0 [0..8].   -  person Scotty Bauer    schedule 31.07.2013


Ответы (5)


Из справочных страниц:

fgets() считывает не более одного символа меньше size из потока и сохраняет их в буфер, на который указывает s. Чтение останавливается после EOF или новой строки. Если читается новая строка, она сохраняется в буфере. Завершающий нулевой байт (aq\0aq) сохраняется после последнего символа в буфере.

Вы читаете только семь символов.

person LostBoy    schedule 30.07.2013

Одна из причин, по которой это может не сработать, заключается в том, что вы можете читать меньше восьми символов. Скажем, пользователь вводит три символа и нажимает [Enter]. В этом случае char в позиции 8 останется неназначенной, поэтому ее чтение будет поведением undefined.

На самом деле вы хотите спросить, являются ли все восемь символов, предшествующих первому '\0' в строке, ненулевыми. Вы можете сделать это, позвонив по номеру strlen.

Обратите внимание, что вы не можете получить строку длины восемь, когда вы передаете 8 для длины, потому что fgets будет использовать последнюю позицию для '\0':

char HEX[9];
while (fgets(HEX, 9, stdin) != NULL)
{ //              ^--- Pass 9, not 8
  if (strlen(HEX) == 8)
  {
    printf("GOOD\n");
    break;
  }
  else
  {
    printf("Not 8 characters");
  }
}
person Sergey Kalinichenko    schedule 30.07.2013
comment
Проблема, с которой я столкнулся с strlen, заключается в том, что даже когда я ввожу более 8-20 символов, он возвращает только 7 вершин. - person Skynight; 31.07.2013
comment
@Skynight Это потому, что вы передаете длину от 8 до fgets, а не 9. Я отредактировал ответ, чтобы объяснить, почему. - person Sergey Kalinichenko; 31.07.2013
comment
@dasblinkenlight, пожалуйста, используйте sizeof HEX вместо жестко заданной длины. (Я знаю, что вы это знаете, просто позвольте нам показать пример кода OP с некоторой хорошей практикой. :) - person ; 31.07.2013

вот почему:

fgets() считывает не более одного символа меньше size из потока и сохраняет их в буфер, на который указывает s. Чтение останавливается после EOF или новой строки. Если читается новая строка, она сохраняется в буфере. Завершающий нулевой байт (aq\0aq) сохраняется после последнего символа в буфере.

Это означает, что если вы хотите прочитать 8, вы на самом деле прочитаете только 7. Вы хотите прочитать 9, иметь буфер размером 9 и проверить, не является ли какое-либо из значений нулевым, начиная с конца.

 char HEX[10];
 memset(hex, 1, 10); //Will stop false positives since memory might be null to begin with
while (fgets(HEX, 9, stdin) != NULL)
{
  if (HEX[9] == '\0')
  {
    printf("GOOD\n");
    break;
  }
  else
  {
    printf("Not 8 characters");
  }
}
person Magn3s1um    schedule 30.07.2013
comment
Да, но прочитайте определение: он сохраняет нулевой байт ПОСЛЕ чтения min(sizeofstr, 8). - person Magn3s1um; 31.07.2013
comment
а hex[8] — девятый элемент в массиве - person LostBoy; 31.07.2013
comment
char HEX[9] будет достаточно. а должно быть HEX[8] == '\0'. - person chux - Reinstate Monica; 31.07.2013

Если вы хотите прочитать только 8 символов из стандартного ввода, функция fgetc() может лучше подойти для ваших целей.

Рассмотрим следующий код:

#include <stdio.h>

int main(void)
{
    char str[8];
    int incre1=0;
    for (incre1=0;incre1<=7;incre1++) {
        str[incre1] = fgetc(stdin);
        if(str[incre1] == EOF) {
            printf("less than 8 characters\n");
            break; }
    }
printf("%s\n",str);
return(0);
}

Этот код будет считывать первые 8 символов из стандартного ввода (включая символы новой строки), либо из консоли, либо из конвейерного вывода другой программы, и помещать их в буфер str. Добавив проверку в середине цикла for для символа End-of-FILE, вы можете заставить свою программу реагировать соответствующим образом, если ввод содержит менее 8 символов.

Обратите внимание: если вы пытаетесь написать программу с интерактивным консольным вводом, вы также можете включить соответствующее условие break, если будет прочитан символ новой строки.

person J. Alfred Prufrock    schedule 31.07.2013

fgets() хранит \n на 8-й позиции в вашем случае.
Итак, у вас есть два варианта,

  1. Проверьте наличие \0 на 9-й позиции.
  2. Замените \n на 8-й позиции на \0, затем проверьте наличие \0 на 8-й позиции.
person Abhishek    schedule 27.05.2019