ZetCode

C sscanf 函数

最后修改日期:2025 年 4 月 6 日

字符串解析是 C 编程中的一项关键技能,它允许您高效地从字符串中提取和转换数据。 `sscanf` 函数是实现此目的的强大工具,它提供了各种格式说明符来满足您的需求。本教程将深入探讨 `sscanf`,解释其格式说明符,并提供实际示例。在安全环境中,始终优先使用 `sscanf_s` 等安全替代方案来防止缓冲区溢出。

什么是 sscanf?

`sscanf` 函数从字符串而不是标准输入读取格式化输入。它接受三个参数:输入字符串、格式字符串以及存储结果的变量参数。该函数返回成功匹配的项数。与 `scanf` 不同,它更安全,因为它不直接从用户输入读取。但是,请务必验证返回值以确保正确解析。

基本字符串解析

让我们从一个从字符串中提取基本数据类型的简单示例开始。

basic_parse.c
#include <stdio.h>

int main() {
    char input[] = "John 25 3.5";
    char name[20];
    int age;
    float height;

    int result = sscanf(input, "%s %d %f", name, &age, &height);

    if (result == 3) {
        printf("Name: %s\n", name);
        printf("Age: %d\n", age);
        printf("Height: %.1f\n", height);
    } else {
        printf("Failed to parse all items\n");
    }

    return 0;
}

此示例演示了基本的 `sscanf` 用法。格式字符串 `"%s %d %f"` 匹配输入中的字符串、整数和浮点数。 `result` 变量检查是否所有三个项都已成功解析。始终包含此验证以优雅地处理解析错误。然后打印提取的值以确认成功解析。

使用字段宽度进行解析

通过指定读取字符串的最大字段宽度来防止缓冲区溢出。

width_specifier.c
#include <stdio.h>

int main() {
    char input[] = "ProgrammingInC 42";
    char lang[15];  // Buffer for language name
    int version;

    int result = sscanf(input, "%14s %d", lang, &version);

    if (result == 2) {
        printf("Language: %s\n", lang);
        printf("Version: %d\n", version);
    } else {
        printf("Parsing failed\n");
    }

    return 0;
}

`%14s` 格式说明符将字符串读取限制为 14 个字符,为我们 15 个字符的缓冲区留出空终止符的空间。这对于防止缓冲区溢出至关重要。该示例还展示了如何在单个 `sscanf` 调用中混合不同的数据类型。为了安全起见,请始终将缓冲区大小与字段宽度说明符匹配。

高级格式说明符

使用高级格式说明符精确解析复杂的字符串模式。

advanced_format.c
#include <stdio.h>

int main() {
    char date_str[] = "2025-04-15";
    int year, month, day;

    int result = sscanf(date_str, "%d-%d-%d", &year, &month, &day);

    if (result == 3) {
        printf("Year: %d\n", year);
        printf("Month: %d\n", month);
        printf("Day: %d\n", day);
    } else {
        printf("Date parsing failed\n");
    }

    return 0;
}

此示例使用多个整数说明符解析带连字符分隔符的日期字符串。格式字符串 `"%d-%d-%d"` 精确匹配输入结构。请注意,格式字符串中的连字符必须与输入中的连字符匹配才能成功解析。返回值检查确保在使用所有三个日期组件之前已提取它们。

跳过字符

了解如何使用星号修饰符在解析过程中跳过不需要的字符。

skip_characters.c
#include <stdio.h>

int main() {
    char log_entry[] = "Error: 404 - Not Found";
    int error_code;

    int result = sscanf(log_entry, "Error: %d - %*s", &error_code);

    if (result == 1) {
        printf("Error code: %d\n", error_code);
    } else {
        printf("Failed to parse error code\n");
    }

    return 0;
}

带星号的 `"%*s"` 格式说明符告诉 `sscanf` 读取但丢弃后面的字符串。在这里,我们只提取错误代码,同时跳过错误消息。返回值为 1,因为只存储了一个项(error_code)。当您只需要格式化字符串的特定部分时,此技术非常有用。

安全替代方案:sscanf_s

为了安全编码,请使用 `sscanf_s`,它需要缓冲区大小参数。

secure_sscanf.c
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>

int main() {
    char input[] = "SecureCoding 123";
    char name[20];
    int value;

    int result = sscanf_s(input, "%s %d", name, (unsigned)sizeof(name), &value);

    if (result == 2) {
        printf("Name: %s\n", name);
        printf("Value: %d\n", value);
    } else {
        printf("Secure parsing failed\n");
    }

    return 0;
}

`sscanf_s` 函数是 `sscanf` 的安全版本,它需要字符串参数的缓冲区大小。请注意,需要 `#define` 来启用此 C11 功能。大小参数 `(unsigned)sizeof(name)` 可防止缓冲区溢出。虽然并非普遍可用,但对于可用且对安全性至关重要的应用程序,建议使用它。

使用 sscanf 的最佳实践

来源

C sscanf 文档

本教程展示了 `sscanf` 在 C 中进行字符串解析的多功能性,从基本提取到高级模式匹配。正确使用格式说明符和验证可确保应用程序中进行稳健且安全的字符串处理。

作者

我叫 Jan Bodnar,是一名敬业的程序员,对编码充满热情。自 2007 年以来,我通过 1,400 多篇文章和 8 本电子书分享我的专业知识。凭借十多年的教学经验,我致力于让编程变得平易近人且引人入胜。

列表 C 标准库