为什么strtok无法正确分离此字符串? C

时间:2018-10-10 23:25:00

标签: c

  • riga_corrente中的字符串是:"apelle figlio di apollo"
  • d [0] .stringa的内容为“ pelle”,compresso_s为“ $ 11 $”。
  • 温度是200个字符的数组。

我想在"a$11$ figlio di apollo"中放入riga_corrente,但我只得到"a$11$ fig",我不明白为什么。

部分代码:

strcpy(temp,strtok(riga_corrente,d[i].stringa));
strcat(temp,compresso_s);
strcat(temp,strtok(NULL,d[i].stringa));
strcpy(riga_corrente,temp);

1 个答案:

答案 0 :(得分:0)

您的问题在这里转换为MCVE(Minimal, Complete, Verifiable Example):

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

int main(void)
{
    char riga_corrente[200] = "apelle figlio di apollo";
    char stringa[] = "pelle";
    char compresso_s[] = "$11$";
    char temp[200];

    strcpy(temp, strtok(riga_corrente, stringa));
    strcat(temp, compresso_s);
    strcat(temp, strtok(NULL, stringa));
    strcpy(riga_corrente, temp);
    printf("[%s]\n", riga_corrente);

    return 0;
}

这将产生以下输出,这意味着库函数正在按设计工作(但显然不是您期望的那样):

[a$11$ fig]

strtok()的第一次调用在p中的apelle处停止,用空字节换行,然后返回指向a的指针,该指针被复制到temp。然后,您从$11$附加compresso_s。对strtok()的下一次调用会跳过e的{​​{1}},lle,并在空白处开始令牌。字母apellefi与定界符不匹配,但是g匹配,因此l中的l用空字节并返回指向空白的指针。将该字符串正确添加到figlio的末尾,然后temp由于temp覆盖riga_corrente

乍一看,您可以通过将第二个调用中的定界符更改为strcpy()来解决它,也许只是换行符,甚至是空字符串。但是,这也将strtok()的{​​{1}}作为输出的一部分。需要不同技术的修复-可能使用自1989年以来在标准C中已被低估(鲜为人知)的strspn()strcspn()函数,或者可能使用strstr()查找字符串elle

它不是很优雅(这里可能有一个函数试图转义),但这可以起作用:

apelle

这里没有缓冲区溢出保护;通常不需要它,但是原则上,如果pelle从未出现在#include <stdio.h> #include <string.h> int main(void) { char riga_corrente[200] = "apelle figlio di apollo"; char stringa[] = "pelle"; char compresso_s[] = "$11$"; char temp[200]; char *source = riga_corrente; char *p1 = strstr(source, stringa); if (p1 == NULL) strcpy(temp, source); else { *p1 = '\0'; strcpy(temp, source); source = p1 + strlen(stringa); } strcat(temp, compresso_s); if (p1 != NULL) { p1 = strstr(source, stringa); if (p1 == NULL) strcat(temp, source); else { *p1 = '\0'; strcat(temp, source); } } strcpy(riga_corrente, temp); printf("[%s]\n", riga_corrente); return 0; } 中,则可能会导致缓冲区溢出。