Использование функции fgets в C - PullRequest
4 голосов
/ 04 февраля 2011

Одно из моих заданий написать свою собственную оболочку UNIX. Чтобы получить ввод от пользователя, я использую fgets для захвата ввода в виде строки, но я не совсем уверен, как это работает. Когда я бегу:

char command[50];
fgets(command, sizeof(command), stdin);

printf("Your Command: %s", &command);
int length = strlen(command);
printf("Length of String: %d\n", length);

Допустим, мой вход был "выход". Стрлен говорит, что длина строки 5 символов, а не 4. Я хочу сделать это:

if( (strcmp(command, "exit")) == 0 ){
    doSomething();
}

но команда никогда не совпадает со строкой, которую я хочу; как будто у него есть неизвестный характер, в котором я не уверен. Это нулевой символ в конце? Как мне изменить оператор if, чтобы проверить, что пользовательский ввод, перехваченный с помощью fgets, равен «exit»? Спасибо!

Ответы [ 7 ]

7 голосов
/ 04 февраля 2011

fgets считает терминатор строки допустимым символом. Это дополнительный персонаж, который вы получаете.

Просто сделайте что-то вроде command[strlen(command) - 1] = '\0';, чтобы удалить терминатор строки. Тогда вы можете делать все свои strcmp.

4 голосов
/ 04 февраля 2011

Со страницы руководства fgets:

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

Итог: у вас естьдополнительная строка в конце строки при сравнении.

3 голосов
/ 04 февраля 2011

fgets всегда будет включать символ завершения строки во входной строке. Вы можете удалить любой пробел, включая символы новой строки, в конце своей «команды», выполнив:

char command[50];
fgets(command, sizeof(command), stdin);

size_t length = strlen(command);
// Trim off trailing "spaces" including newline characters
while ((length > 0) && isspace(command[length-1]))
      command[--length] = '\0';

printf("Your Command: %s\n", &command); // Include newline now...
// This is computed above...
// int length = strlen(command);

// Continue as before
2 голосов
/ 04 февраля 2011

Вероятно, самый простой способ справиться с этим - перейти на использование scanf для чтения ввода:

char command[51];

scanf("%50[^\n]", command);

if (0 == strcmp(command, "exit"))
    do_something();
2 голосов
/ 04 февраля 2011

fgets также захватывает разрыв строки.

Обратите внимание, что вы можете преодолеть это несколькими способами, можно использовать strncmp:

if((strncmp(command, "exit", 4)) == 0)

, который проверяет, совпадают ли только первые 4 символа команды (хотя здесь это может быть неправильным вариантом).

Другая тактика - проверка с разрывом строки на месте:

if((strcmp(command, "exit\n")) == 0)
1 голос
/ 04 февраля 2011

Ваша строка все еще имеет перевод строки в конце.Вы можете сравнить с "exit\n" или использовать что-то вроде strncmp(command, "exit", 4).Обратите внимание, что это будет принимать все, что начинается с «выхода», и игнорировать все остальное.

0 голосов
/ 04 февраля 2011

Как уже отмечалось, fgets (3) дает вам трейлинг '\ n'. Если вы используете gets (3), вы не получите завершающий символ новой строки. Ничего подобного последовательности, сэз I.

В Perl есть функция hand chomp (), которая обрезает завершающий символ новой строки, если он присутствует & mdash; Вы могли бы сделать хуже, чем бросить свой собственный:

#define NUL ((char)0)
void chomp( char *s )
{
  if ( s != null )
  {
    int len = strlen(s) ;
    if ( len >= 1 && s[len-1] == "\n" )
    {
      s[len-1] = NUL ;
    }
  }
  return ;
}
...