我有一些遵循这种格式的用户输入:
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);
}
Run Code Online (Sandbox Code Playgroud)
(注:该%[..]转换不消耗前导空白,因此,如果有的前导空白或以下的空间中的可能性'#'的字符串转换前,包括在格式字符串的空间中,例如" %15[^#]# %15[^#]#%d#%lf|%lf# %15[^\n]")
其中要拆分的输入的每个字符串部分都声明为16字符数组。查看格式字符串,您会注意到每个字符串的读取仅限于15字符(加上空终止字符),以确保您不会尝试存储比数组可以容纳的更多字符。(这将调用Undefined Behavior)。由于请求了六次转换,您可以通过确保返回为 来验证转换6。
示例使用/输出
采用这种方法,上面的输出将是:
./bin/parse_sscanf
name : Playa Raco
path : path
num : 5
lat : 39.244000
lon : -0.257000
last : 0-23
Run Code Online (Sandbox Code Playgroud)
只要您验证转换并保护填充的任何字符数组的数组边界,就没有一种方法一定比另一种“更好”。但是,尽可能简单,这里很难被击败sscanf()——而且它不会修改您的原始字符串,因此与字符串文字一起使用是安全的。
| 归档时间: |
|
| 查看次数: |
43 次 |
| 最近记录: |