gpt4 book ai didi

c - 使用 sscanf 从文件中读取

转载 作者:太空宇宙 更新时间:2023-11-03 23:48:26 24 4
gpt4 key购买 nike

当文件中的行格式如下时,如何从文件中读取行:

<string> "<string>"

第一个字符串不能有空格。引号内的字符串可以有空格。

在将文件读入char 数组后,我尝试了一些

sscanf(buffer, "%s", string1);
sscanf(buffer, "%*s \"%[^\"]\"", string2);

问题是我在某些行中得到了一些奇怪的字符。大多数字符都很好,但对于长字符串,我得到一些不应该出现的字符。

编辑:

看起来问题可能与 sscanf 无关。当我在 sscanf 之后立即打印 string1string2 时,我得到了正确的输出。我的程序设置方式必须malloc 新内存并将结果复制到char*。当我打印后一个结果时,出现了奇怪的行为。我使用 char *cpystring1 = malloc(strlen(string1)) 然后使用 memcpy(cpystring1, string1, strlen(string1)。这一直对我有用,但是,也许这不是最好的方法吗?

问题已解决:

查看我留下的最后一条评论了解详情。

最佳答案

作为BLUEPIXYcomment中说,一个问题是“你有足够的空间来存储字符串吗?”实际上,您的变量是 char string1[SOME_SIZE]; 还是 char *string1;,如果是后者,您如何为它们分配空间?奇怪的额外字符等症状通常是由于读取数据的空间不足造成的。

您可以将这两个操作合并为一个。您还应该限制阅读的大小;你应该检查你的阅读是否成功。假设您有两个大小为 128 的数组,您可以这样写

char string1[128];
char string2[128];

if (sscanf(buffer, "%127s \"%127[^\"]\"", string1, string2) != 2)
…format error…

请注意,格式字符串中指定的数字是字符串的最大长度,不包括 空字节。这与库的其余部分并不完全一致,但早在 C 标准出现之前就已确立惯例,更改规则带来的破坏多于修复。

另请注意,使用上面的代码,您永远不会知道结尾的双引号是否存在。如果您也需要该信息,则必须更加努力地工作:

int  offset = 0;
char string1[128];
char string2[128];

if (sscanf(buffer, "%127s \"%127[^\"]\"%n", string1, string2, &offset) != 2 || offset == 0)
…format error…

最后,如果您使用的是 POSIX 系统,%s%c% 的 m 修饰符[…] 操作为读取的数据动态分配正确的空间量(但是您将指针传递给 char * 以供转换规范使用,而不是普通的 char *):

int  offset = 0;
char *tag = 0;
char *value = 0;

if (sscanf(buffer, "%ms \"%m[^\"]\"%n", &tag, &value, &offset) != 2 || offset == 0)
…format error…

请注意,某些系统(例如 Mac OS X 10.10.1 Yosemite)不支持 m 修饰符,即使它是 sscanf() 的 POSIX 2008 规范的一部分| . GNU C 库(例如,可在 Linux 上找到)支持它。

sscanf() 是否是处理这些数据的最佳方式值得思考。它可以使用:我刚刚展示了如何使用(你在写问题时已经拥有了大部分你需要的东西)。然而,准确使用它是一项棘手的功能——这就是礼貌。 sscanf() 的好处在于,您可以实现“如果一开始您不成功,请尝试,再尝试,再尝试”。对于像 scanf() 这样的直接 I/O 函数,一般来说,你不能再试一次。但是,您也可以使用字符串操作来获得所需的输出,尽管这样做的简单方法会破坏输入字符串:

char *tag = buffer + strspn(buffer, " \t");  // Skip leading blanks and tabs
char *eot = tag + strcspn(tag, " \t"); // Tag does not contain blanks or tabs
if (*eot == '\0')
…report format error (no value after tag); do not continue…
*eot++ = '\0'; // Null terminate the tag
char *value = eot + strspn(eot, " \t"); // Skip separating blanks and tabs
if (*value++ != '"')
…report format error (missing open double quote); do not continue…
char *eov = strchr(value, '"');
if (eov == 0)
…report format error (missing close double quote); do not continue…
*eov = '\0';

还有其他方法可以进行扫描,但是 strspn()strcspn() 是 C89 和所有后续版本中标准的被忽视的函数标准。

工作测试代码

使用 GCC 4.8.2 在 Ubuntu 14.04 LTS 上测试。

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

static void parsing(char *buffer)
{
char *tag = buffer + strspn(buffer, " \t"); // Skip leading blanks and tabs
char *eot = tag + strcspn(tag, " \t"); // Tag does not contain blanks or tabs
if (*eot == '\0')
{
printf("Got tag <<%s>> but no following data\n", tag);
return;
}
*eot++ = '\0'; // Null terminate the tag
char *value = eot + strspn(eot, " \t"); // Skip separating blanks and tabs
if (*value++ != '"')
{
printf("Got tag <<%s>> but it is not followed by a double-quoted string\n", tag);
return;
}
char *eov = strchr(value, '"');
if (eov == 0)
{
printf("Got tag <<%s>> and value <<%s>> but it is not followed by a double-quote\n", tag, value);
return;
}
*eov = '\0';

printf("<<%s>> <<%s>>\n", tag, value);
}

int main(void)
{
char buffer[] = " \ttagname \" corresponding tag \tvalue is OK \" ";

{
int offset = 0;
char string1[128];
char string2[128];

if (sscanf(buffer, "%127s \"%127[^\"]\"%n", string1, string2, &offset) != 2 || offset == 0)
printf("sscanf() 1 failed\n");
else
printf("<<%s>> <<%s>>\n", string1, string2);
}

{
int offset = 0;
char *tag = 0;
char *value = 0;

if (sscanf(buffer, "%ms \"%m[^\"]\"%n", &tag, &value, &offset) != 2 || offset == 0)
printf("sscanf() 2 failed\n");
else
printf("<<%s>> <<%s>>\n", tag, value);

free(tag);
free(value);
}

parsing(buffer);

return 0;
}

输出:

<<tagname>> << corresponding tag    value is OK >>
<<tagname>> << corresponding tag value is OK >>
<<tagname>> << corresponding tag value is OK >>

关于c - 使用 sscanf 从文件中读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27073288/

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