【问题标题】:How to fix gibberish printed after use strtok如何修复使用 strtok 后打印的乱码
【发布时间】:2019-08-03 07:48:58
【问题描述】:

我有 uni 项目,我需要检查语法是否正确。我得到一个指向字符串的指针,并检查第一个标记是否可以接受。万一没问题,我就往前走。但万一不正常,我需要打印出什么问题。

我所做的是创建一个缓冲区,因为我无法更改原始字符串。 之后我使用strtok 剪切缓冲区,看看我得到的令牌是否可以接受。

char *str = "sz = 12345";
printf("The check of MACRO: %d\n", isMacro(str));

int isMacro(char *str)
{
    char buf = NULL;
    char *token;
    strcpy(&buf,str);
    token = strtok(&buf," ");
    printf("You here, value token is %s\n",token);
}

我预计 printf 会打印“sz”,但它会打印:

You here, value str is sz<▒R

【问题讨论】:

  • isMacro() 未返回值,因此 out printf() 可能会调用未定义的行为。

标签: c string strtok


【解决方案1】:
    char buf = NULL;

这是一个类型错误。 buf 是单个字符,但 NULL 是指针值。您不能将指针存储在 char 中。

    strcpy(&buf,str);

此代码具有未定义的行为(除非str 恰好是一个空字符串)。 buf 不是缓冲区,它是单个 char,因此它没有空间存储整个字符串。

如果你想复制一个字符串,你需要为它的所有字符分配足够的内存:

  1. 您可以使用strdup(在 POSIX 中,但不是标准 C):

    char *buf = strdup(str);
    if (!buf) {
        ... handle error ...
    }
    ...
    free(buf);
    
  2. 您可以手动复制strdup

    char *buf = malloc(strlen(str) + 1);
    if (!buf) {
        ... handle error ...
    }
    strcpy(buf, str);
    ...
    free(buf);
    
  3. 您可以使用可变长度数组(但您会受到堆栈大小的限制,并且无法检查错误):

    char buf[strlen(str) + 1];
    strcpy(buf, str);
    ...
    

【讨论】:

  • 为什么char buf = NULL 还能编译?
  • @Ayxan 在某些平台上,NULL 被定义为0,而不是((void *)0),因此代码实际上变成了buf = '\0'。其他编译器将(某些)类型错误视为可选警告,而不是硬错误。
【解决方案2】:

buf 是单个 char,而不是 pointerchar。事实上,如果你打算用strcpy 复制一个字符串到它,你需要先使用malloc 分配内存。相反,我建议您使用strdup 之类的函数而不是strcpy 来创建原始字符串的副本以使用strtok 对其进行修改。记得稍后freestrduped 字符串。

类似的东西。

int isMacro(char *str)
{
    char *buf = NULL;
    char *token;
    buf = strdup(str);
    token = strtok(buf," ");
    printf("You here, value of token is %s\n",token);
    free(buf);
}

【讨论】:

  • 很好的建议,但值得注意的是 strdup 不是 c 标准库的一部分(它是 POSIX),因此某些编译器可能不提供它(在这种情况下,您的 strlen, mallocmemcpy 建议很好)
  • isMacro() 未返回值。
猜你喜欢
  • 2020-12-24
  • 2018-11-28
  • 1970-01-01
  • 1970-01-01
  • 2013-07-28
  • 1970-01-01
  • 2020-07-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多