- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
当文件中的行格式如下时,如何从文件中读取行:
<string> "<string>"
第一个字符串不能有空格。引号内的字符串可以有空格。
在将文件读入char
数组
后,我尝试了一些
sscanf(buffer, "%s", string1);
sscanf(buffer, "%*s \"%[^\"]\"", string2);
问题是我在某些行中得到了一些奇怪的字符。大多数字符都很好,但对于长字符串,我得到一些不应该出现的字符。
编辑:
看起来问题可能与 sscanf
无关。当我在 sscanf
之后立即打印 string1
和 string2
时,我得到了正确的输出。我的程序设置方式必须malloc
新内存并将结果复制到char*
。当我打印后一个结果时,出现了奇怪的行为。我使用 char *cpystring1 = malloc(strlen(string1))
然后使用 memcpy(cpystring1, string1, strlen(string1)
。这一直对我有用,但是,也许这不是最好的方法吗?
问题已解决:
查看我留下的最后一条评论了解详情。
最佳答案
作为BLUEPIXY在comment中说,一个问题是“你有足够的空间来存储字符串吗?”实际上,您的变量是 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/
这个问题不太可能对任何 future 的访客有帮助;它只与一个较小的地理区域、一个特定的时间点或一个非常狭窄的情况相关,通常不适用于全世界的互联网受众。如需帮助使此问题更广泛适用,visit the
我在程序中遇到了以下行。通过阅读手册,我知道 sscanf 从 argv[2] 指向的任何地方复制,但我不确定为什么格式被指定为 %d,同时指定为 %c (我见过其他双引号中包含更多格式说明符的示例)
我可以使用字符指针 (char *) 作为 sscanf() 函数中的输出字符串吗?考虑到我不知道字符串的长度(这就是我使用指针的原因)。 char *name; sscanf(data, "Name
我有一个表单的输入字符串 char *s = "one.two three" 我想把它分成 3 个字符串变量。我在做 sscanf(s, "%s.%s %s", one, two, three); 但
我一直在尝试让 sscanf 使用字符类识别一种相当简单的格式。我注意到,当我为 sscanf 提供 char* 以匹配字符类时,它也会覆盖前一个字节,就好像它需要一个指向 2 个字节的指针一样。 我
我正在将 MAC 地址的字符串表示形式转换为 UINT8 的数组s 定义为 unsigned char 。我很好奇为什么sscanf()当我读入 UINT8 数组时,将读取全 0当我读入常规 32 位
我有一个包含空格和标签的字符串,例如: sp|P02671|FIBA_HUMAN Fibrinogen alpha chain OS=Homo sapiens GN=FGA PE=1 SV=2 我只想
我正在尝试在 C 中使用 sscanf 函数,但它不读取格式是必需的,我已经阅读了该函数的文档并遵循了示例,但它对我来说仍然效果不佳,因此我想要一些建议.. int main() { long i
我需要在c中解析一个格式为“foo=%d”的字符串,我需要检查格式是否正确并读取int值。 我的初始代码是: int foo_set = 0; int foo; if (sscanf(text, "f
在下面的代码中,我想读取十六进制字符串 'a' 中的前 2 个字符,使用 sscanf 将它们转换为相应的字节值并将结果放入 'b'。不应对“a”执行任何修改。 #include #include
我试图找出我应该给 sscanf 的模式。 我有一个字符串 abcde(1GB)。我想提取 1 和 GB。我在用 char list[]= "abcde(1GB)"; int memo
我应该得到一个可以是以下任何格式的输入行: 单词 1 和单词 2 之间必须有空格。 单词 2 和单词 3 之间必须有逗号。 单词 2 和单词 3 之间不一定要有空格,但可以有任意数量的空格。 如何分离
最近发现的对 GTA 冗长加载时间 (1) 的解释表明 sscanf() 的许多实现调用 strlen()在他们的输入字符串上为与其他扫描函数( scanf() , fscanf() ...)共享的内
我需要将字符串分成两部分,字符串的第一列是第一部分,字符串的其余部分是第二部分。第一部分需要存储在 first_str 中,第二部分需要存储在 rest_str 中。 我正在使用 sscanf 来实现
我需要从char数组中提取数字,它以hh:mm的格式存储值(示例20:20) 我尝试使用sscanf函数将hh提取为小时变量,将mm提取为分钟变量。 直到时间类似于0number:0number或如果
所以我想知道 sscanf 在遇到像这样的行时是如何工作的: sscanf(input_string, "%s %s %s", cmd1, cmd2, cmd3); 但是假设 input_string
我在以下代码中遇到 sscanf() 问题: void num_check(const char*ps){ char *ps1=NULL; int number=0; unsigned sum_num
谁能解释一下为什么在下面的代码中没有拆分字符串 #include int main(void) { char name[] = "first:last"; char first[20
我正在尝试解析一个 URL,并编写了这段代码: #include int main() { char host[100]; char port[100]; char path
我正在为我正在制作的程序使用 AT 命令,但在使用 sscanf() 函数解析它们时遇到问题。 例如,如果我执行此命令: "AT\r\r\nOK\r\n" 我想:* 在第一次调用时,仅获取“AT”部分
我是一名优秀的程序员,十分优秀!