文章

`sscanf` 高级用法与实用技巧

本文记录了一些C语言的一些技巧

`sscanf` 高级用法与实用技巧

sscanf 高级用法与实用技巧

sscanf 是C语言中强大的字符串解析函数,能够根据格式字符串从输入字符串中提取结构化数据。以下是其核心技巧和实用场景的总结。


目录


1. 基础用法

基本格式

1
int sscanf(const char *str, const char *format, ...);
  • 功能: 从 str 中按 format 格式提取数据。
  • 返回值: 成功匹配并赋值的参数个数。

示例

1
2
3
4
5
6
char str[] = "ID:123 Name:Alice";
int id;
char name[20];
sscanf(str, "ID:%d Name:%s", &id, name);
// id=123, name="Alice"


2. 高级技巧

字段宽度控制

用途: 防止缓冲区溢出。 ​```c char buffer[5]; sscanf(“ABCDEFG”, “%4s”, buffer); // 读取最多4字符 + ‘\0’ // buffer = “ABCD”

1
2
3
4
5
6
7
8
9
### <a id="跳过不需要的数据"></a>跳过不需要的数据

使用 `*` 修饰符忽略字段。

```c
int age;
sscanf("Name:Bob Age:30", "Name:%*s Age:%d", &age);
// age=30(跳过"Bob")

字符集合匹配

  • %[a-z]: 匹配小写字母。
  • %[^:]: 匹配除 : 外的字符。
1
2
3
4
char time_str[] = "2023-10-05T14:30:00";
char date[11], time[9];
sscanf(time_str, "%10[^T]T%8s", date, time);
// date="2023-10-05", time="14:30:00"

返回值与错误处理

检查返回值以验证匹配数量。

1
2
3
4
int a, b;
if (sscanf("10 20", "%d %d", &a, &b) != 2) {
    // 处理解析失败
}

动态解析位置

使用 %n 获取已读取的字符数。

1
2
3
4
char str[] = "1234,5678";
int num1, num2, pos;
sscanf(str, "%d,%n%d", &num1, &pos, &num2);
// num1=1234, pos=5(逗号后的位置), num2=5678

3. 复杂格式解析

多分隔符处理

1
2
3
4
char log[] = "[ERROR] 2023-10-05: File not found";
char level[10], date[11], msg[50];
sscanf(log, "[%[^]]] %10[^:]: %49[^\n]", level, date, msg);
// level="ERROR", date="2023-10-05", msg="File not found"

混合数据类型

1
2
3
4
5
char data[] = "Temp:25.5C,Humidity:60%";
float temp;
int humidity;
sscanf(data, "Temp:%fC,Humidity:%d%%", &temp, &humidity);
// temp=25.5, humidity=60

循环解析

结合 %n 和指针偏移实现循环。

1
2
3
4
5
6
char input[] = "10,20,30,40";
int value, offset = 0, bytes_read;
while (sscanf(input + offset, "%d,%n", &value, &bytes_read) == 1) {
    printf("%d ", value); // 输出: 10 20 30 40
    offset += bytes_read;
}

4. 安全注意事项

  1. 缓冲区溢出防护 始终指定字段宽度(如 %255s 对应 char[256])。

  2. 输入验证 检查返回值,避免未初始化数据。

  3. 避免未定义行为 确保格式字符串与参数类型严格匹配。


5. 实战示例

解析GPS数据

1
2
3
4
5
char gps[] = "$GPRMC,083559.00,A,4717.11437,N,00833.91522,E,0.004,77.52,091202,,,A*53";
char status;
float lat, lon;
sscanf(gps, "$GPRMC,%*f,%c,%f,%*c,%f,%*c,%*f,%*f,%*s", &status, &lat, &lon);
// status='A', lat=4717.11437, lon=00833.91522

提取IP地址

1
2
3
4
char ip[] = "192.168.1.100";
int a, b, c, d;
sscanf(ip, "%d.%d.%d.%d", &a, &b, &c, &d);
// a=192, b=168, c=1, d=100

通过灵活运用 sscanf,可以高效解析复杂字符串,但需注意安全性和错误处理。建议结合具体场景选择最佳格式字符串设计。

本文由作者按照 CC BY 4.0 进行授权