【发布时间】:2020-07-22 20:58:10
【问题描述】:
解析字符串
char* "AS LSLDS SAAL SS"
【问题讨论】:
标签: c string parsing scanf c89
解析字符串
char* "AS LSLDS SAAL SS"
【问题讨论】:
标签: c string parsing scanf c89
为什么不简单地使用sscanf 字符类格式说明符 "%[^\n]" 来读取名称,例如
if (sscanf (str, "%7s %7s %d %63[^\n]", loc, dir, &len, name))
printf ("loc : %s\ndir : %s\nlen : %d\nname: %s\n", loc, dir, len, name);
field-width 修饰符必须与任何字符串转换一起使用,否则sscanf 并不比gets() 好。宽度将对应于以下声明,例如
char str[] = "D4 E 3 NullByte Sub",
loc[8], dir[8], name[64];
int len;
一个完整的例子是:
#include <stdio.h>
int main (void) {
char str[] = "D4 E 3 NullByte Sub",
str2[] = "D4 E 3 NullByte Sub Ship Barrier",
loc[8], dir[8], name[64];
int len;
if (sscanf (str, "%7s %7s %d %63[^\n]", loc, dir, &len, name))
printf ("\nloc : %s\ndir : %s\nlen : %d\nname: %s\n", loc, dir, len, name);
if (sscanf (str2, "%7s %7s %d %63[^\n]", loc, dir, &len, name))
printf ("\nloc : %s\ndir : %s\nlen : %d\nname: %s\n", loc, dir, len, name);
}
使用/输出示例
$ ./bin/sscanf_loc-dir-name
loc : D4
dir : E
len : 3
name: NullByte Sub
loc : D4
dir : E
len : 3
name: NullByte Sub Ship Barrier
【讨论】:
char [128] = "D4 E 3 NullByte Sub";和line = "D4 E 3 NullByte Sub Ship Barrier"的支持——它们都不能包含嵌入的'\n'。
问题在于scanf 的%s 格式(以及sscanf 等相关函数)读取的是空格分隔 字符串。
由于字符串中没有良好的“记录结束”标记(超出字符串的实际结尾),因此很难使用 sscanf,即使使用其特殊的 %[ 格式说明符。
相反,我建议您了解strtok 以及如何使用它来“标记”字符串。
有了它,您可以执行以下操作:
char *p = strtok(line, " ");
strcpy(location, p);
p = strtok(NULL, " ");
strcpy(direction, p);
p = strtok(NULL, " ");
length = strtol(p, NULL, 10);
strcpy(name, p + strlen(p) + 1); // p + strlen(p) skips over the number, +1 to skip over the space as well
【讨论】:
p + strlen(p) + 1 是对的,但它看起来超级粗略。
像这样:
int offset;
sscanf(line, "%s %s %d %n", location, direction, &length, &offset);
name = line + offset; // or strncpy or something, if you want a new string instead of just a pointer into the old one
%n 记录到目前为止已经消耗了多少个字符。如果你向前跳转那么多字符,那么你会得到字符串的其余部分。
旁注:在没有最大字段宽度的情况下使用%s(或让它使用m 修饰符自行分配)是危险的,除非你100% 确定你永远不会得到一个过长的单词。
【讨论】: