fgets максимален размер за четене

Използвайки fgets за въвеждане на низ, имам съмнения, свързани с дължината на прочетения низ.

Например, разгледайте следната програма.

char str[50];
int i;
int len;
printf("Enter name:\n");
fgets(str,11,stdin);
len = strlen(str);
printf("len :  %d\n",len);
  1. Ако въведа 123456789, strlen дава 10.

  2. Ако въведа 1234567890, даденото strlen отново е 10 ??

Мисля, че strlen обмисля нов ред и за дължина на низа. Прав ли съм? (Разбирам fgets използването на нов ред като част от низ)

Какво не е наред с (2), където въвеждам точно 10 знака, тук дължината на низа трябва да е 11, нали? 10 + 1 (за нов ред) = 11


person kumar    schedule 24.06.2012    source източник
comment
printf(len : %d,len); printf(str: %s,str); printf(hi);връщане 0; } Добавянето на няколко разпечатки помага да се изяснят отговорите, дадени по-долу. Забележете как се отпечатва hi.   -  person kumar    schedule 20.11.2012


Отговори (3)


fgets чете най-много 1 знак по-малко от дадения аргумент за дължина и запазва новия ред като част от входа - стига новият ред да е част от първите (дължина - 1) символи.

Така че във вашия първи случай, ако приемем, че 123456789 е последвано от нов ред, fgets е прочел 9 знака, включително новия ред, давайки низ с дължина 10; във втория ви случай fgets ще спре, след като прочете 10-те знака 1234567890, което ще доведе до низ с дължина 10.

person pb2q    schedule 24.06.2012
comment
Малка корекция: няма да запази новия ред, ако #/знаци ›= максимална дължина. Както е показано в примера по-долу. - person paulsm4; 25.06.2012
comment
@paulsm4 Вярвам, че това вече е ясно от първия ми ред: чете най-много 1 знак по-малко от дадения аргумент за дължина. - person pb2q; 25.06.2012

Ето един пример:

#include <stdio.h>
#include <string.h>

#define MAX_DIGITS 5

int
main ()
{
  char buf[80];
  char *s = NULL;
  printf ("\n>>Enter string, %d digits or less: ", MAX_DIGITS);
  s = fgets (buf, MAX_DIGITS+1, stdin);
  printf ("strlen(buf)=%d, buf=%s, strlen(s)=%d, s=%s\n",
    strlen(buf), buf, strlen(s), s);
  return 0;
}

Примерен резултат с „MAX_DIGITS“ и „MAX_DIGITS + 1“:

>>Enter string, 5 digits or less: 1
strlen(buf)=2, buf=1
, strlen(s)=2, s=1
.

>>Enter string, 5 digits or less: 12
strlen(buf)=3, buf=12
, strlen(s)=3, s=12
.

>>Enter string, 5 digits or less: 123
strlen(buf)=4, buf=123
, strlen(s)=4, s=123
.

>>Enter string, 5 digits or less: 1234
strlen(buf)=5, buf=1234
, strlen(s)=5, s=1234
.

>>Enter string, 5 digits or less: 12345
strlen(buf)=5, buf=12345, strlen(s)=5, s=12345.

>>Enter string, 5 digits or less: 123456
strlen(buf)=5, buf=12345, strlen(s)=5, s=12345.

Ще забележите:

  1. Буферът за връщане запазва "\n", докато #/цифрите са ‹ MAX_DIGITS.

  2. „\n“ се ПРЕМАХВА, когато #/цифри >= MAX_DIGITS.

  3. Вашият буфер трябва да побира MAX_DIGITS+1

person paulsm4    schedule 24.06.2012
comment
‹‹Вашият буфер трябва да побира MAX_DIGITS+1. Така че буферът трябва да има достатъчно място за съхранение на нов ред, което е +1. Благодаря за вашата помощ. - person kumar; 25.06.2012
comment
@kumar За съхраняване на нов ред трябва да бъде + 2, тъй като fgets вече отнема един за съхраняване на нулева стойност за край -› '\0'; Тоест, ако му подадете 6, той ще прочете най-много 5 неща (4 цифри + CR или 5 цифри). Ако го подадете 7, той ще прочете 5 цифри плюс връщане на каретката. - person Scooter; 22.08.2012

Всъщност fgets изисква size спецификация (във вашия случай 11) акаунт за \0 в края на низ. От страницата на fgets man:

fgets() чете най-много един знак по-малък от размера от потока и ги съхранява в буфера, към който сочи s. Четенето спира след EOF или нов ред. Ако бъде прочетен нов ред, той се съхранява в буфера. Краен нулев байт ('\0') се съхранява след последния знак в буфера.

Знаем, че четенето спира на \n, когато въведете 123456789\n. Когато обаче въведете 1234567890\n, fgets() обработва входа, но отнема само 10 знака и игнорира всичко останало след това.

Всеки допълнителен вход на вашия низ и вашия низ ще бъдат size-1 от fget() с последния знак като \0, така че изходът остава същият.

person Siddharth    schedule 12.09.2017