2017-01-10 2 views
0

У меня проблема. Я попытался увидеть длину некоторой строки после использования функции fgets. Если я ввешу строку под номером буквы, которая может быть в строке (например: максимальные буквы в строке равны 9, и я ввожу 4 буквы), я получаю длину строки + 1. Зачем?длина строки с функцией fgets в C

Вот мой код:

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

int main(void) 
{ 
    char name[10]={0}; 
    printf("enter your name\n"); 
    fgets(name, 10, stdin); 
    printf("your name is %s and it is %d letters\n", name, strlen(name)); // length problem 

    return 0; 
} 
+1

А как насчет man-страницы 'fgets' неясно? Вы проверили массив после функции в вашем отладчике? Что вы нашли в конце строки? – Olaf

+2

'fgets()' включает в себя новую строку на входе - если она читает новую строку. –

+0

... и после имени ваш вывод перемещается в ** следующую строку ** ... – LPs

ответ

1

Поскольку символ конца строки '\n' включена в строку скопированный в name по fgets(). страница

3

С fgets ручной (https://linux.die.net/man/3/fgets):

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

Так оно добавляет '\n' после ваших 4 букв, возвращая string_length+1.

От Removing trailing newline character from fgets() input Вы можете добавить решение @Tim Čas к вашему коду.

Линия по-прежнему считывается с помощью функции fgets() и после удаления символа новой строки.

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


int main(void) 
{ 
    char name[10] = { 0 }; 
    printf("enter your name\n"); 
    fgets(name, 10, stdin); 
    printf("your name is %s and it is %d letters\n", name, strlen(name)); // length problem 
    name[strcspn(name, "\n")] = 0; 
    printf("NEW - your name is %s and it is %d letters\n", name, strlen(name)); 
    return 0; 
} 

, который выводит:

enter your name 
Andy 
your name is Andy 
and it is 5 letters 
NEW - your name is Andy and it is 4 letters 
Press any key to continue . . . 
+0

, так как я могу получить строку без новой строки, которую она добавляет (удалите '' \ n ', если функция добавит его?) –

+0

Я обновил ответ. – jgorosdev

+0

См. [@LPs% zu] (http://stackoverflow.com/questions/41572713/string-length-with-fgets-function-in-c#comment70350205_41572713) – chux

1

Если массив символов имеет достаточно места, то стандартная функция fgets также включает в себя символ новой строки в массиве, как правило, соответствует введенный ключ Enter.

Вы можете удалить этот Избыточный символ новой строки следующего образом

name[strcspn(name, "\n")] = '\0'; 

после этого вы получите ожидаемый результат применения функции strlen. Функция

1

Как написано в man fgets,

В fgets() считывает максимум на один меньше, чем количество символов, указанных по размеру от данного потока и сохраняет их в строке ул. Чтение останавливается при обнаружении символа новой строки, в конце файла или ошибке . Новая строка, если таковая имеется, сохраняется. Если какие-либо символы читаются и нет ошибки, для завершения строки добавляется символ `\ 0 '.

Поскольку вы читаете из stdin, fgets(name, 10, stdin) читает не более 9 символов из стандартного ввода буфера и присоединяет \0 до конца. Просто случается, что новый символ строки \n, созданный, когда пользователь попадает в enter, также находится в буфере.

В качестве побочного элемента обычно используется (и хорошая практика) использовать sizeof() при указании размера массива, переданного в fgets.

fgets(name, (int) sizeof(name), stdin); 
+1

«* Это никогда не может пойти не так!» «Конечно, как его машина, но она по-прежнему может быть использована неправильно. Обработка изображений с использованием указателя вместо массива: 'char * readstr (char * p) {return fgets (p, sizeof p, stdin); } 'будет (в большинстве систем) попытаться прочитать 4 или 8' char'. – alk

+0

«Это никогда не может пойти не так!» -> обратите внимание, что 'sizeof' возвращает тип' size_t', но 'fgets (char * s, int n, FILE * stream)' использует 'int' для размера. С огромными массивами это может непредсказуемо конвертировать. Конечно, редко, но не всегда. – chux

+0

Как вы знаете, что он никогда не пойдет не так, если вы не проверите его возвращаемое значение? 'fgets' может возвращать' NULL' из 'stdin', если встречается' EOF'. – RoadRunner

Смежные вопросы