[英]Extract formatted input from user
我有一些遵循这种格式的用户输入:
Playa Raco#path#5#39.244|-0.257#0-23
此处的#
用作分隔符,而|
也是纬度和经度的分隔符。 我想提取这些信息。 请注意,字符串可以有空格。 我尝试将%[^\\n]%*c
格式化程序与scanf
并添加#
和|
,但它不起作用,因为它匹配整行。
我想让这尽可能简单,我知道我可以读取每个字符,但我很想看看最佳实践并检查是否有scanf
或类似的替代方案。
正如评论中提到的,有很多方法可以解析字符串中的信息。 您可以沿着字符串遍历一对指针,测试每个字符并采取适当的操作,您可以使用strtok()
,但注意strtok()
修改原始字符串,因此它不能用于字符串文字,您可以使用sscanf()
解析字符串中的值,或者您可以使用strcspn()
、 strspn()
、 strchr()
等的任意组合,然后手动复制开始和结束指针之间的每个字段。
但是,您的问题也强加了“我想尽可能保持简单......”并且直接指向sscanf()
。 您只需要验证退货即可。 例如,你可以这样做:
#include <stdio.h>
#define MAXC 16 /* adjust as necessary */
int main (void) {
const char *str = "Playa Raco#path#5#39.244|-0.257#0-23";
char name[MAXC], path[MAXC], last[MAXC];
int num;
double lat, lon;
if (sscanf (str, "%15[^#]#%15[^#]#%d#%lf|%lf#%15[^\n]",
name, path, &num, &lat, &lon, last) == 6) {
printf ("name : %s\npath : %s\nnum : %d\n"
"lat : %f\nlon : %f\nlast : %s\n",
name, path, num, lat, lon, last);
}
else
fputs ("error: parsing values from str.\n", stderr);
}
(注意: %[..]
转换不消耗前导空格,因此如果在字符串转换之前有可能出现前导空格或'#'
后面的空格,请在格式字符串中包含一个空格,例如" %15[^#]# %15[^#]#%d#%lf|%lf# %15[^\\n]"
)
其中要拆分的输入的每个字符串部分都声明为一个16
字符的数组。 查看格式字符串,您会注意到每个字符串的读取限制为15
字符(加上 nul 终止字符),以确保您不会尝试存储超过数组可以容纳的字符。 (这将调用Undefined Behavior )。 由于请求了 6 次转换,因此您可以通过确保返回值为6
验证转换。
示例使用/输出
采用这种方法,上面的输出将是:
./bin/parse_sscanf
name : Playa Raco
path : path
num : 5
lat : 39.244000
lon : -0.257000
last : 0-23
只要您验证转换并保护填充的任何字符数组的数组边界,就没有一种方法一定比另一种“更好”。 但是,尽可能简单,在这里很难击败sscanf()
—— 并且它不会修改您的原始字符串,因此与字符串文字一起使用是安全的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.