#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student {
char name[20];
int age;
float score;
};
int main() {
char input[100];
struct student stu;
char output[100];
// 从标准输入读取一行字符串
if (fgets(input, sizeof(input), stdin) == NULL) {
perror("fgets");
return 1;
}
// 移除换行符
input[strcspn(input, "\n")] = '\0';
// 使用sscanf解析输入字符串到结构体
if (sscanf(input, "%19s %d %f", stu.name, &stu.age, &stu.score) != 3) {
fprintf(stderr, "解析输入失败\n");
return 1;
}
// 使用snprintf将结构体信息格式化为新字符串
snprintf(output, sizeof(output), "姓名: [%s], 年龄: [%d], 成绩: [%.2f]", stu.name, stu.age, stu.score);
// 输出新生成的字符串
printf("%s\n", output);
return 0;
}
sscanf
函数作用及可能问题
- 作用:
sscanf
函数用于从字符串中按照指定格式读取数据,并将数据存储到相应的变量中。在上述代码中,sscanf(input, "%19s %d %f", stu.name, &stu.age, &stu.score)
从 input
字符串中读取姓名(最多19个字符以避免缓冲区溢出)、年龄和成绩,并分别存储到 stu.name
、stu.age
和 stu.score
中。
- 可能问题:
- 输入格式不匹配:如果输入的字符串格式与
sscanf
中的格式说明符不匹配,如缺少数据或数据类型不一致,sscanf
可能无法正确解析,返回值也会不等于期望的项数(这里是3)。
- 缓冲区溢出:如果输入的姓名长度超过
stu.name
的大小(20个字符),会导致缓冲区溢出,可能破坏其他内存数据。因此在 sscanf
中对 %s
使用了宽度限制 %19s
。
snprintf
函数作用及可能问题
- 作用:
snprintf
函数用于将格式化的数据写入到指定的字符串缓冲区中,并确保不会发生缓冲区溢出。在上述代码中,snprintf(output, sizeof(output), "姓名: [%s], 年龄: [%d], 成绩: [%.2f]", stu.name, stu.age, stu.score)
将结构体 stu
中的信息按照指定格式写入到 output
字符串中,并且会确保写入的字符数不会超过 output
的大小(sizeof(output)
)。
- 可能问题:
- 缓冲区过小:如果
output
缓冲区的大小不足以容纳格式化后的字符串,snprintf
会截断字符串,以避免缓冲区溢出。但返回值会表示完整字符串的长度(不包含终止空字符),可以通过检查返回值判断是否发生截断。例如,如果返回值大于等于 sizeof(output)
,说明发生了截断。