侧边栏壁纸
博主头像
张种恩的技术小栈博主等级

行动起来,活在当下

  • 累计撰写 748 篇文章
  • 累计创建 65 个标签
  • 累计收到 39 条评论

目 录CONTENT

文章目录

C库函数-sprintf和sscanf

zze
zze
2024-03-27 / 0 评论 / 0 点赞 / 19 阅读 / 9286 字

不定期更新相关视频,抖音点击左上角加号后扫一扫右方侧边栏二维码关注我~正在更新《Shell其实很简单》系列

sprintf

函数原型:

#include <stdio.h>

int sprintf(char *str, const char *format, ...);

功能:sprintf函数将格式化的数据写入到一个字符串中,其行为类似printf函数,但它不是将结果输出到屏幕,而是写入到指定的字符数组(也就是字符串)中。

参数说明:

  • str:指向一个足够大的字符数组,用于接收格式化输出的字符串。

  • format:是一个包含格式说明符的字符串,格式说明符告诉函数如何格式化其余的参数。

  • ...:可变参数列表,根据format字符串中的格式说明符所指示的类型和顺序提供相应的值。

示例:

#include <stdio.h>

int main() {
    char output[100]; // 创建一个足够大的字符数组来存储结果字符串

    // 示例1:将整数和字符串格式化输出到output数组
    int num = 42;
    char name[] = "Alice";
    sprintf(output, "Hello, %s! Your number is %d.", name, num);
    printf("%s\n", output); // 输出:"Hello, Alice! Your number is 42."

    // 示例2:格式化输出浮点数
    float pi = 3.14159265;
    sprintf(output, "Value of PI: %.2f", pi);
    printf("%s\n", output); // 输出:"Value of PI: 3.14"

    return 0;
}

注意事项:

  1. 使用sprintf时,需确保目标字符串有足够的空间容纳格式化后的结果,否则可能导致内存溢出。

  2. 为了防止缓冲区溢出,可以先计算需要的长度,或者使用snprintf函数,它允许指定目标字符串的最大长度。

安全版本: 在C99标准中引入了snprintf函数,其原型如下:

int snprintf(char *str, size_t size, const char *format, ...);

这里的size参数指定了str数组的大小,可以防止意外地超过数组边界。如果输出的字符串长度超过size-1(留一个字符空间给字符串结束符'\0'),则snprintf会截断输出,以保证字符串始终是有效的。

sscanf

函数原型:

#include <stdio.h>

int sscanf(const char *str, const char *format, ...);

功能:sprintf函数的逆操作,sscanf从字符串中读取并解析数据,按照指定的格式将字符串转换为对应的变量值。它可以从字符串中提取并解析整数、浮点数、字符串以及其他数据类型。

参数说明:

  • str:源字符串,从中读取数据。

  • format:格式字符串,用于指导如何解析源字符串中的数据,其格式与printf函数的格式说明符相同。

  • ...:可变参数列表,按照format中格式说明符的顺序放置待填充的变量地址。

示例:

#include <stdio.h>

int main() {
    char input[] = "Name: Alice, Age: 25, City: New York";
    char name[50];
    int age;
    char city[50];

    // 使用sscanf解析输入字符串
    int items_read = sscanf(input, "Name: %s, Age: %d, City: %s", name, &age, city);

    // 输出解析后的数据
    printf("Name: %s, Age: %d, City: %s\n", name, age, city);

    // 返回值:成功读取的项目数
    printf("Items read: %d\n", items_read);

    return 0;
}

运行示例代码后的输出:

Name: Alice, Age: 25, City: New York
Items read: 3

注意事项:

1. sscanf的返回值表示成功读取并赋值的参数个数,可用于检测是否成功读取所有预期的数据项。

2. 在使用 %s 格式符读取字符串时,务必确保目标数组足够大,以防溢出。此外,如果不指定最大读取长度,可能会读取过长的字符串导致安全问题,可以使用%Ns的形式(N为数组长度减一)来限定读取的字符数。

3. 对于整数和浮点数的读取,也需要确保目标变量的类型与格式符匹配,否则可能出现数据丢失或未定义的行为。

高级用法示例:

  • 例 1:限定长度读取字符串。

#include <stdio.h>

int main()
{
    char str[10];
    const char *input = "Hello, World!";
    sscanf(input, "%9s", str); // 读取最多9个字符(包括终止符'\0')
    printf("%s", str); // Hello,
}

此处 %9s 表示读取不超过 9 个字符的字符串(遇到空白字符会停止读取),防止读取过长导致缓冲区溢出。

  • 例 2:忽略指定字符。

#include <stdio.h>

int main()
{
    int num;
    sscanf("abc 123", "%*s %d", &num);
    printf("%d\n", num);
}

此处 %*s 表示忽略该占位。

#include <stdio.h>

int main()
{
    // 34 用整数提取,67用字符串提取
    int num34 = 0;
    char str67[8];
    char str[] = "12345678";
    sscanf(str, "%*2s%2d%*1s%2s", &num34, str67);
    printf("num34: %d, str67: %s\n", num34, str67);
}
  • 例 3:限定字符匹配。

#include <stdio.h>

int main()
{
    char buf[128];
    char str[] = "abcde2334fg";
    sscanf(str, "%[a-z,1-2]", str);
    printf("str: %s\n", str);
}
  • 例 4:取反与限定字符长度。

#include <stdio.h>

int main() {
    char input[] = "Name: Alice, Age: 25, Phone: (123) 456-7890";
    char name[50];
    int age;
    char phone[20];
    
    if (sscanf(input, "Name: %49[^,], Age: %d, Phone: %19[^\n]", name, &age, phone) == 3) {
        printf("Name: %s\n", name);
        printf("Age: %d\n", age);
        printf("Phone: %s\n", phone);
    } else {
        printf("Failed to extract the fields.\n");
    }
    
    return 0;
}

此处 %49[^,] 表示提取最多 49 位非 , 字符串。

  • 例 5:歌词解析。

#include <stdio.h>

int main()
{
    char buf[128] = "[02:04.94][00:36.09]滴滴滴滴滴滴滴滴等待";
    char *song_start = buf;

    while (*song_start == '[')
    {
        song_start += 10;
    }

    printf("歌词: %s\n", song_start);

    char *time_start = buf;
    while (*time_start == '[')
    {
        int m, s = 0;
        sscanf(time_start, "[%d:%d%*[^.]", &m, &s);
        printf("第 %d 秒唱歌词: %s\n", m *60 + s , song_start);
        time_start += 10;
    }
}
  • 例 6:邮箱解析。

#include <stdio.h>

int main()
{
    char qq[12], mail_host[12];
    char buf[128] = "632404164@qq.com";
    sscanf(buf, "%[^@]@%[^.].com", qq, mail_host);
    printf("qq: %s, mail_host: %s", qq, mail_host);
    // qq: 632404164, mail_host: qq
}

0

评论区