strtok() 然后 strcmp() 在 true 时返回 false

strtok() then strcmp() returning false when true

我猜这是一个类型问题,也许你可以告诉我它是如何正确完成的。

我正在读取来自 stdin 的命令输入,我想在用户输入 q.

时退出

我正在使用 fgets() 将来自 stdin 的用户输入读取到指向字符数组的指针中。然后我使用 strtok() 拼接第一个单词并将其分配给另一个指向字符数组的指针。然后我将它与 q 进行比较,以查看用户是否要使用 strcmp() 函数退出程序。

这是一些代码:

    char *input = (char*)malloc(32 * sizeof(char));
    char *command = (char*)malloc(8 * sizeof(char));

    while (strcmp(command, "q") != 0)
    {
        memset(input, 0, sizeof(input));
        printf("Enter command: ");
        fgets(input, 64, stdin);
        command = strtok(input, " ");
        //if I enter q --> printf("%d", strcmp(command, "q")) == 10
        //if I enter w --> printf("%d", strcmp(command, "q")) == 6
    }

我想要的是,如果 command == q 那么 printf("%d", strcmp(command, "q")) 应该等于 0 否则它应该打印任何其他整数。

我还应注意,我已确认 command 已正确分配。换句话说,当我输入 q, command == "q".

也许你可以试试这个代码:

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

int main()
{
    char *input = (char*)malloc(32 * sizeof(char));
    char *command = (char*)malloc(8 * sizeof(char));

    while (strcmp(command, "q") != 0)
    {
        memset(input, 0, sizeof(input));
        printf("Enter command: ");
        fgets(input, 64, stdin);
        command = strtok(input, " \n"); // Line corrected.
        //if I enter q --> printf("%d", strcmp(command, "q")) == 10
        //if I enter w --> printf("%d", strcmp(command, "q")) == 6
    }

return 0;

}

这里有几个问题。

  1. 这里分配的内存

    char *command = (char*)malloc(8 * sizeof(char));
    

    这条线泄露的那一刻

    command = strtok(input, " ");
    

    作为对分配的内存的唯一引用被覆盖并因此丢失。

  2. 此处可能发生缓冲区溢出

    fgets(input, 64, stdin);
    

    允许读取更多字节 (64) ito input 因为它指向此处完成的分配

    char *input = (char*)malloc(32 * sizeof(char));
    
  3. 假设用户输入的数据不包含像'[blanks]q ...thencommandget assignedNULL`这样的序列调用

    command = strtok(input, " ");
    

    这导致在此处将 NULL 传递给 strcmp() 以在此处测试下一次迭代

    while (strcmp(command, "q") != 0)
    

    这样做会调用未定义的行为。

  4. 代码未检查相关函数调用的结果,例如 malloc()`` andfgets()`。

  5. 在 C 中不需要转换 malloc() & friends 的结果,也不推荐这样做。所以不要这样做。它可能很好地隐藏错误。

  6. sizeof (char) 定义为 1。不用用了

  7. 不要用 "Magic Numbers"/"Tokens" 破坏您的代码,例如 32864"q" ...

  8. 如果您想至少执行一次,从概念上讲使用 while 循环是错误的方法。在这种情况下使用 do-while 循环。

修复所有这些问题可能会导致以下代码:

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


#define INPUT_BUFFER_SIZE (64)
#define QUIT_STRING "q"


int main(void)
{
  int result = EXIT_SUCCESS; /* Be optimistic. */

  char *input = malloc(INPUT_BUFFER_SIZE * sizeof *input);
  if (NULL == input)
  {
    perror("malloc () failed");
    result = EXIT_FAILURE;
  }
  else
  {
    char *command;

    do 
    {
      printf("Enter command:\n");
      if (NULL == fgets(input, INPUT_BUFFER_SIZE, stdin))
      {
        if (!feof(stdin))
        {
          result = EXIT_FAILURE;
          fprintf(stderr, "fgets() failed.\n");
        } 

        break;
      }

      command = strtok(input, " \n"); 
    } while ((command == NULL) || strcmp(command, QUIT_STRING) != 0);

    if (NULL != command)
    {
      printf("User quit.\n");
    }

    free(input);
  }

  return result;
}