欢迎光临
我们一直在努力

C语言学习笔记20260713-格式化输入输出家族汇总

C语言学习笔记20260713-格式化输入输出家族汇总

核心概念:这组函数本质相同,区别仅在于数据源(Source)和目的地(Destination)不同。
头文件:<stdio.h>

核心对比总览

函数族函数名数据来源 (Input)数据去向 (Output)典型应用场景
标准 I/O scanf 键盘 (stdin) 内存变量 用户交互输入
printf 内存变量 屏幕 (stdout) 打印结果、日志
文件 I/O fscanf 文件指针 (FILE*) 内存变量 读取配置文件、解析文本数据
fprintf 内存变量 文件指针 (FILE*) 写入日志文件、保存数据
字符串 I/O sscanf 字符串 (char*) 内存变量 解析字符串中的特定数据(如提取 IP)
sprintf 内存变量 字符串 (char*) 拼接字符串、数字转字符串

1. 标准输入输出:人机交互

这是最基础的函数,默认绑定到控制台(黑窗口)。

  • scanf:等待用户在键盘敲击并回车,将数据读入变量。
  • printf:将变量的内容显示在屏幕上。

代码示例

#include <stdio.h>

int main() {
int age;
// printf: 提示用户输入
printf("请输入你的年龄: ");

// scanf: 从键盘读取整数存入 age
// 注意:这里必须加 & 取地址符
if (scanf("%d", &age) == 1) {
// printf: 格式化输出结果
printf("你今年 %d 岁了。\\n", age);
} else {
printf("输入无效!\\n");
}

return 0;
}


2. 文件流操作:持久化存储

这两个函数比标准 I/O 多了一个参数 FILE *stream,用于指定操作哪个文件。

  • fscanf:从文件中按格式读取数据。
  • fprintf:按格式将数据写入文件。

代码示例

#include <stdio.h>

int main() {
FILE *fp = fopen("data.txt", "w+");
if (!fp) return 1;

char name[50] = "Alice";
int score = 98;

// fprintf: 将数据格式化写入文件
// 类似于 printf,但第一个参数是文件指针
fprintf(fp, "Name: %s, Score: %d\\n", name, score);

// 重置文件指针到开头以便读取
rewind(fp);

char read_name[50];
int read_score;

// fscanf: 从文件读取格式化数据
// 类似于 scanf,但第一个参数是文件指针
if (fscanf(fp, "Name: %s, Score: %d", read_name, &read_score) == 2) {
printf("读取成功 -> 姓名: %s, 分数: %d\\n", read_name, read_score);
}

fclose(fp);
return 0;
}


3. 字符串流操作:内存中的转换

这两个函数不依赖外部设备或文件,直接在内存中的字符数组(字符串)进行操作。

  • sscanf (String Scan):从一个已存在的字符串中提取数据。
  • sprintf (String Print):将各种类型的数据拼接到一个字符串中。

场景 A:使用 sscanf 解析复杂字符串

假设你有一个字符串 "2023-10-05",想把它拆分成年、月、日。

#include <stdio.h>

int main() {
const char *date_str = "2023-10-05";
int year, month, day;

// sscanf: 从 date_str 中按 "-" 分割提取整数
// 返回值是成功匹配并赋值的变量个数
int count = sscanf(date_str, "%d-%d-%d", &year, &month, &day);

if (count == 3) {
printf("解析成功: %d 年 %d 月 %d 日\\n", year, month, day);
}

return 0;
}

场景 B:使用 sprintf 拼接/转换字符串

假设你想把多个变量拼成一句话,或者把数字变成字符串。

#include <stdio.h>

int main() {
char buffer[100]; // 目标缓冲区,必须足够大
int id = 1001;
double price = 99.5;

// sprintf: 将数据格式化写入 buffer 字符串
// 注意:如果数据太长超过 buffer 大小,会发生溢出(危险!)
sprintf(buffer, "ID: %d, Price: %.2f USD", id, price);
printf("生成的字符串: %s\\n", buffer);

// 应用:数字转字符串
char num_str[20];
sprintf(num_str, "%d", 12345);
printf("数字转字符串: %s\\n", num_str);

return 0;
}


⚠️ 安全提示与最佳实践

  • sprintf 的隐患:

    • sprintf 不检查目标缓冲区的大小,容易导致缓冲区溢出。
    • 推荐替代方案:使用 snprintf(buffer, size, …),它可以限制写入的最大长度,更加安全。

    // 安全写法:限制最多写入 sizeof(buffer)-1 个字符
    snprintf(buffer, sizeof(buffer), "ID: %d", id);

  • scanf 的隐患:

    • 读取字符串时如果不限制长度(如 %s),用户输入过长也会导致溢出。
    • 推荐写法:scanf("%19s", str)(假设 str 大小为 20)。
  • 返回值检查:

    • 所有的 scanf 系列函数都会返回成功匹配并赋值的项数。务必检查返回值以确保数据解析正确。

  • 总结

    C 语言的格式化输入输出家族提供了灵活的数据处理能力:

    • 标准 I/O 用于人机交互
    • 文件 I/O 用于数据持久化
    • 字符串 I/O 用于内存中的数据转换和解析

    掌握这些函数的区别和使用场景,能够让你在处理各种数据输入输出任务时更加得心应手。记住安全第一,始终检查返回值并使用安全的替代函数(如 snprintf)。

    赞(0)
    未经允许不得转载:171主机测评 » C语言学习笔记20260713-格式化输入输出家族汇总
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址