Ввод возвращает правильную строку, но не запускает функцию

У меня есть следующий код:

bool get_command(char *cmd){
    char *cm = (char*)malloc(strlen(cmd));
    strcpy(cm,cmd);
    const char *tok = strtok(cm," ");
if(!tok)
    return false;

if(!strcmp(tok,"MULTIPLY"))
{
    printf("WORKING!\n");
    return true
}
....




int main(void){
  while(1){
    char *input = NULL;
    char buf[MAX_LINE_LENGTH] = {0};
    int read;
    size_t len;
    read = getline(&input, &len, stdin);
    if (-1 != read){
      printf("Input: %s\n", input);
      sprintf(buf, "%s", input);
      get_command(input);
    } else {
       printf("No line read\n");
   }
   free(input);
  }
 return 0;
}

Когда я запускаю код и ввожу MULTIPLY, он возвращается

ввод: УМНОЖИТЬ

ЖЕТОН: УМНОЖИТЬ

Однако это не распечатывает WORKING. Может ли кто-нибудь объяснить, почему это не работает должным образом?


person Kadana Kanz    schedule 02.05.2015    source источник
comment
Попробуйте напечатать tok после вызова strtok.   -  person tivn    schedule 02.05.2015
comment
@tivn tok — это то же самое, что и ввод, который должен вызывать функцию printf, но не работает.   -  person Kadana Kanz    schedule 02.05.2015
comment
tok случайно не равно "MULTIPLY\n"?   -  person D.Shawley    schedule 02.05.2015
comment
@ Д.Шоули, это не так! Я узнал из комментария от Cool Guy!   -  person Kadana Kanz    schedule 02.05.2015
comment
перед возвратом из get_command() необходимо вызвать 'free(cm)', иначе в коде будет утечка памяти   -  person user3629249    schedule 02.05.2015
comment
get_command() возвращает либо true, либо false, однако main() игнорирует возвращаемое значение   -  person user3629249    schedule 02.05.2015
comment
относительно вызова malloc(): 1) в C не приводить возвращаемое значение 2) всегда проверять (!=NULL) возвращаемое значение, чтобы убедиться, что операция прошла успешно   -  person user3629249    schedule 02.05.2015
comment
Я бы также рекомендовал заменить код, который выглядит как char *p = malloc(strlen(q) + 1); strcpy(p, q);, на char *p = strdup(q);.   -  person D.Shawley    schedule 02.05.2015


Ответы (1)


В вашем коде вам нужно изменить

char *cm = (char*)malloc(strlen(cmd));

to

char *cm = malloc(strlen(cmd) + 1);

иметь место для завершающего нулевого символа.

strlen() не учитывает завершающий нуль, и если вы не выделите память для хранения нулевого значения во время копирования, вы столкнетесь с переполнением памяти, что приведет к неопределенное поведение.

Согласно справочной странице strcpy()

char *strcpy(char *dest, const char *src);

Функция strcpy() копирует строку, на которую указывает src, включая завершающий нулевой байт ('\0'), в буфер, на который указывает dest. Строки не должны перекрываться, а целевая строка dest должна быть достаточно большой, чтобы получить копию.

Тем не менее, согласно справочной странице getline()

getline() читает всю строку из потока, сохраняя адрес буфера, содержащего текст, в *lineptr. Буфер завершается нулем и включает символ новой строки, если он был найден.

Поскольку ваша строка разделителя не включает \n, токен будет содержать \n. Чтобы избежать, выполните одно из следующих действий.

  • включить \n в строку разделителя
  • используйте strncmp() для сравнения.
  • уберите \n после ввода.

Кроме того, не приводить возвращаемое значение malloc().

person Sourav Ghosh    schedule 02.05.2015
comment
Хм, я думал, что это что-то с нулевыми терминаторами, поэтому я попробовал это, но, похоже, ничего не печатает. - person Kadana Kanz; 02.05.2015
comment
@KadanaKanz, попробуйте добавить cmd[strcspn(cmd,"\n")]=0 в начале get_command - person Spikatrix; 02.05.2015
comment
@KadanaKanz getline() читает и сохраняет новую строку во входной буфер. вместо этого вы можете попробовать strncmp(), это сработает. или вам нужно убрать завершающий \n. - person Sourav Ghosh; 02.05.2015
comment
@CoolGuy, это сработало! Благодарю вас! (прочитал тоже неплохо! :)) - person Kadana Kanz; 02.05.2015
comment
@Sourav спасибо за информацию, обязательно сделаю это в следующий раз. - person Kadana Kanz; 02.05.2015
comment
@KadanaKanz Пожалуйста. :-) обновил мой ответ, чтобы решить эту проблему. - person Sourav Ghosh; 02.05.2015
comment
Почему сняли актерский состав? g++ или gcc дают error: invalid conversion from ‘void*’ to ‘char*’ [-fpermissive] без приведения. - person omerfarukdogan; 02.05.2015
comment
@farukdgn, пожалуйста, посмотрите последнюю строку моего ответа, чтобы найти ссылку на ответ на ваш запрос. :-) - person Sourav Ghosh; 02.05.2015
comment
@SouravGhosh Если вы не выполняете кастинг, вы НЕ можете его скомпилировать, поскольку gcc дает error, а не warning. Так что нам делать? - person omerfarukdogan; 02.05.2015
comment
@farukdgn, Опять же, когда я компилирую на C++, я получаю эту ошибку. Похоже, вы компилируете в режиме C++ с использованием GCC. В C++ приведение требуется, а в C приведение должно быть удалено. - person Spikatrix; 03.05.2015