gpt4 book ai didi

c++ - 使用 sscanf 读取格式化字符串数据

转载 作者:太空宇宙 更新时间:2023-11-04 08:04:20 25 4
gpt4 key购买 nike

我有以下代码:

int main(int argc, char* argv[])
{
char tempBuf[100] = {"|BOD|01|02|100|ID000001|EOD|"};
char startSentinel[10], endSentinel[10], s1[10], s2[10], s3[10], s4[10];
sscanf((char *)tempBuf, "|%[^|]|%[^|]|%[^|]|%[^|]|%[^|]|%[^|]|", startSentinel, s1, s2, s3, s4, endSentinel);

cout<<startSentinel<<" "<<s1<<" "<<s2<<" "<<s3<<" "<<s4<<" "<<endSentinel;
return 0;
}

以上代码打印出正确的数据。输出:BOD 01 02 100 ID000001 EOD


如果我修改以下行:

char tempBuf[100] = {"|BOD|||100|ID000001|EOD|"};

输出:垃圾输出。


如果我给出空格,如下所示:

char tempBuf[100] = {"|BOD| | |100|ID000001|EOD|"}; //Inserted space.

输出正确:

BOD     100 ID000001 EOD

谁能告诉我为什么?以及如何在不插入空格的情况下获得正确的输出?

最佳答案

请注意,在调用 sscanf() 时不需要转换 (char *)tempBuf,因为数组名在函数调用中衰减为指针(和在大多数表达式中)。问题在于扫描集[^|] 匹配一个或多个 不是'|' 的字符;当没有发生这样的匹配时,匹配失败并且 sscanf() 返回。

最简单的解决方案是使用 BSD(包括 macOS)和 Linux 函数 strsep()将输入字符串解析为标记。由于此函数修改输入字符串,您可能需要使用 strdup() (POSIX) 制作原始字符串的拷贝以供使用。 strdup() 使用 malloc() 为重复的字符串分配内存,因此在使用后需要freed。此外,可能需要功能测试宏来启用这些功能。

请注意,当发现两个分隔符彼此相邻时,strsep() 会返回一个空字符串。在下面的代码中,第一个字符被假定为定界符,并被跳过。需要进行一些更改以处理格式不太严格的输入。

#define _DEFAULT_SOURCE

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

int main(void)
{
char tempBuf[100] = {"|BOD|||100|ID000001|EOD|"};
char startSentinel[10], endSentinel[10], s1[10], s2[10], s3[10], s4[10];
char *delims = "|";
char *string = strdup(tempBuf);
char *next = string + 1; // skip first delimiter
char *token;

token = strsep(&next, delims);
strncpy(startSentinel, token, 10);
token = strsep(&next, delims);
strncpy(s1, token, 10);
token = strsep(&next, delims);
strncpy(s2, token, 10);
token = strsep(&next, delims);
strncpy(s3, token, 10);
token = strsep(&next, delims);
strncpy(s4, token, 10);
token = strsep(&next, delims);
strncpy(endSentinel, token, 10);

printf("%s %s %s %s %s %s\n", startSentinel, s1, s2, s3, s4, endSentinel);

free(string);

return 0;
}

如果没有strsep()strdup()函数,可以简单实现,上面的基本代码不变:

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

char * my_strdup(const char *);
char * my_strsep(char **, const char *);

int main(void)
{
char tempBuf[100] = {"|BOD|||100|ID000001|EOD|"};
char startSentinel[10], endSentinel[10], s1[10], s2[10], s3[10], s4[10];
char *delims = "|";
char *string = my_strdup(tempBuf);
char *next = string + 1; // skip first delimiter
char *token;

token = my_strsep(&next, delims);
strncpy(startSentinel, token, 10);
token = my_strsep(&next, delims);
strncpy(s1, token, 10);
token = my_strsep(&next, delims);
strncpy(s2, token, 10);
token = my_strsep(&next, delims);
strncpy(s3, token, 10);
token = my_strsep(&next, delims);
strncpy(s4, token, 10);
token = my_strsep(&next, delims);
strncpy(endSentinel, token, 10);

printf("%s %s %s %s %s %s\n", startSentinel, s1, s2, s3, s4, endSentinel);

free(string);

return 0;
}

char * my_strdup(const char *str)
{
char *dup = malloc(strlen(str) + 1);
char *c = dup;

if (dup) {
while (*str != '\0') {
*c++ = *str++;
}
*c = '\0';
}

return dup;
}

char * my_strsep(char **strp, const char *delims)
{
char *tok = NULL;

if (*strp) {
char *end = strpbrk(*strp, delims);

if (end) {
*end = '\0';
tok = *strp;
*strp = end + 1;
}
}

return tok;
}

以上两个程序都给出了输出:

BOD   100 ID000001 EOD

关于c++ - 使用 sscanf 读取格式化字符串数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43932053/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com