fgets () включает новую строку в конце

fgets(input,sizeof(input),stdin);
if (strcmp(input, "quit") == 0){
  exit(-1);
}

Если я наберу команду quit, программа не выйдет; Мне интересно, почему это так.

Кстати input объявлен как char *input;.


person Man Person    schedule 18.11.2012    source источник
comment
Если вы действительно объявили char *input;, не выделив ему место, чтобы указать на него, вам повезло (или я имею в виду неудачник?), Что вы не получили сбой. Вы должны убедиться, что там достаточно места: char input[64]; было бы лучше; Я обычно использую 4096 для длины строки, если нет веской причины использовать что-то более короткое. Кроме того, вы должны убедиться, что fgets() читают некоторые данные: if (fgets(input, sizeof(input), stdin) != 0) ...OK - read some data....   -  person Jonathan Leffler    schedule 31.08.2013
comment
Я сбит с толку, название этого поста подразумевает, что вы уже знаете, в чем проблема. Вы меняли название?   -  person flarn2006    schedule 21.12.2016
comment
@ flarn2006 Просто проверьте историю редактирования. Кто-то другой изменил это.   -  person underscore_d    schedule 31.01.2018


Ответы (5)


Конечный символ новой строки в вашем вводе. См. man fgets. Проверьте "выйти" + новую строку, например:

fgets(input,sizeof(input),stdin);
if(strcmp(input, "quit\n") == 0){
    exit(-1);
}

Я полностью пропустил последнее предложение, re char *input. В зависимости от архитектуры input будет иметь длину 4 или 8 байтов. Таким образом, код эффективно

fgets(input, 8, stdin);

который не отражает реальный размер памяти, указывает input. Это может «работать», пока ввод короче восьми байтов, но будет обрезать ввод, если он больше. Более того, вы получите остальную часть ввода при следующем вызове fgets.

Вы должны либо указать реальный размер, либо воспользоваться советом @JonathanLeffler и вместо этого объявить массив символов, например

char input[64];
fgets(input, sizeof(input), stdin);

or

char *input = malloc(N);
fgets(input, N, stdin);
person Olaf Dietsche    schedule 18.11.2012
comment
К сожалению, это не всегда работает. Допустим, вы объявили ввод как char input [5] и вводите quit. В то время fgets не добавляет новую строку в конец. Итак, всегда проверяйте, добавлена ​​ли новая строка. - person codaddict; 18.11.2012
comment
Чтобы прояснить мою мысль: сравните результаты: ideone.com/3vs6Ed и ideone.com/MVfvy6 - person codaddict; 18.11.2012

Функция fgets может добавить новую строку в конец прочитанной строки. Вам нужно будет проверить это:

size_t ln = strlen(input) - 1;
if (input[ln] == '\n')
    input[ln] = '\0';

или даже

strtok(input, "\n");
person codaddict    schedule 18.11.2012
comment
Похоже, что это так, когда я его распечатываю. Как мне удалить эту новую строку или изменить strcmp, чтобы она учитывала это? - person Man Person; 18.11.2012
comment
Спасибо, использовал решение Олафа, так как оно немного проще. Но это тоже работает. - person Man Person; 18.11.2012
comment
fgets() не будет добавлять новую строку; он будет включать новую строку, которую он прочитал, которая отмечает конец строки. Таким образом, вы сможете определить, прочитали ли вы всю строку или нет. - person Jonathan Leffler; 31.08.2013
comment
Если первое чтение char является нулевым символом, ln принимает значение SIZE_MAX, безусловно, вызывая чтение за пределами границ с input[ln] - ›UB. Чтобы избежать этой уязвимости, протестируйте ln или, возможно, используйте ln[strcspn(ln,"\n")] = 0;. strtok(input, "\n"); не удается отсечь '\n', если первым char является '\n'. - person chux - Reinstate Monica; 21.12.2016

Предлагаю вам закодировать это как:

if(strstr(input, "quit") != NULL){

Причина: это решит проблему добавления дополнительных символов (например, пробела до или после текста).

person Jonathon David White    schedule 31.05.2017

Это решение требует только стандартной библиотеки (stdio.h) и дает те же результаты.

for (i = 0; input[i] != '\0'; i++); /* getting the string size */
input[i-1] = '\0'; /* removing the newline */
person csr-nontol    schedule 24.05.2015

что я сделал, так это заменил новую строку на '\ 0' null.

while(fgets(message,80,stdin))
{
    l=strlen(message)-1;
    if(message[l]='\n') message[l]='\0';
            else message[i+1]='\0';
}
person Madan Ram    schedule 29.07.2013
comment
Это не гарантированное поведение. Проверьте man fgets: fgets () считывает из потока не более одного символа меньшего размера и сохраняет их в буфере, на который указывает s. Чтение останавливается после EOF или новой строки. Если читается новая строка, она сохраняется в буфере. Завершающий нулевой байт (aq \ 0aq) сохраняется после последнего символа в буфере. Таким образом, у вас может быть два случая, когда новая строка не будет добавлена: strlen(message) > 80 или использовать EOF как терминатор. - person artdanil; 31.08.2013
comment
if(message[l]='\n') message[l]='\0' whaaat? - person Jean-François Fabre; 07.01.2018