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;
}
注意事项:
使用
sprintf
时,需确保目标字符串有足够的空间容纳格式化后的结果,否则可能导致内存溢出。为了防止缓冲区溢出,可以先计算需要的长度,或者使用
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
}
评论区