繁体   English   中英

从用户中提取格式化的输入

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM