c语言 scanf printf

99ANYc3cd6
预计阅读时长 20 分钟
位置: 首页 C语言 正文

printf - 格式化输出

printf 的全称是 "Print Formatted",即“格式化打印”,它的作用是将数据按照你指定的格式,输出到标准输出设备(通常是你的屏幕)。

c语言 scanf printf
(图片来源网络,侵删)

基本语法

int printf(const char *format, ...);
  • 返回值:它返回成功打印的字符个数(不包括结尾的 \0),如果发生错误,则返回一个负数。
  • format:这是一个格式化字符串,它包含了两种类型的字符:
    • 普通字符:会原样输出。
    • 格式说明符:以 开头,用来指定后面要输出的变量的类型和格式。
  • (省略号):表示这是一个可变参数列表,你需要提供与格式说明符一一对应的变量。

常用格式说明符

格式说明符 对应数据类型 描述
%d%i int 以十进制形式输出一个整数。
%c char 输出一个字符。
%s char * (字符串) 输出一个字符串。
%f float 以小数形式输出一个浮点数。
%lf double 注意printf%lf%f 对于 double 类型通常可以混用,但 %f 是标准写法。
%p void * 输出一个指针地址。
%x%X int (无符号) 以十六进制形式输出整数,%x 用小写字母,%X 用大写字母。
%o int (无符号) 以八进制形式输出整数。
- 输出一个百分号 本身。

示例代码

#include <stdio.h>
int main() {
    int age = 25;
    char initial = 'J';
    float height = 1.75f;
    double pi = 3.141592653589793;
    char name[] = "Alice";
    // 普通字符和格式说明符混合
    printf("My name is %s.\n", name); // 输出: My name is Alice.
    printf("My initial is %c and my age is %d.\n", initial, age); // 输出: My initial is J and my age is 25.
    // 输出浮点数,可以控制小数位数
    printf("My height is %.2f meters.\n", height); // 输出: My height is 1.75 meters. (.2f 表示保留2位小数)
    // 输出 double 类型
    printf("The value of pi is %.10f.\n", pi); // 输出: The value of pi is 3.1415926536.
    // 输出变量的地址
    int num = 10;
    printf("The address of num is %p.\n", &num); // 输出: The address of num is 0x7ffc... (具体地址值)
    // 输出百分号
    printf("This is a percent sign: %%\n"); // 输出: This is a percent sign: %
    // 打印 printf 的返回值
    int chars_printed = printf("This line has some text.\n");
    printf("The last printf printed %d characters.\n", chars_printed); // 输出: The last printf printed 21 characters.
    return 0;
}

scanf - 格式化输入

scanf 的全称是 "Scan Formatted",即“格式化扫描”,它的作用是从标准输入设备(通常是你的键盘)读取数据,并按照指定的格式存入变量中。

基本语法

int scanf(const char *format, ...);
  • 返回值:它返回成功匹配并赋值的参数个数,如果到达文件末尾(EOF),则返回 EOF,如果发生匹配错误,则返回一个小于预期参数个数的值。
  • format:格式化字符串,包含普通字符和格式说明符。
  • (省略号):可变参数列表,这里必须是变量的地址,而不是变量本身,因为 scanf 需要知道把读到的数据存到哪里去。

关键点:变量地址

scanf 需要变量的地址,在 C 语言中,使用取地址运算符 & 来获取变量的地址。

  • &age 获取 int 变量 age 的地址。
  • &initial 获取 char 变量 initial 的地址。
  • 对于字符串数组(如 char name[50]),name 本身就代表数组的首地址,所以不需要 & 符号。

常用格式说明符

格式说明符 对应数据类型 描述
%d int * 从输入读取一个十进制整数。
%c char * 读取一个字符。注意:它会读取包括空格、换行在内的任何字符。
%s char * 读取一个字符串,直到遇到空白字符(空格、Tab、换行)。
%f float * 读取一个浮点数。
%lf double * 注意scanf 中读取 double 类型必须使用 %lf,使用 %f 是错误的,会导致数据读取不正确。
%x int * 以十六进制形式读取一个整数。

示例代码

#include <stdio.h>
int main() {
    int number;
    char grade;
    char full_name[50];
    double gpa;
    printf("Please enter an integer: ");
    int ret1 = scanf("%d", &number);
    if (ret1 != 1) {
        printf("Failed to read an integer.\n");
        return 1; // 非正常退出
    }
    printf("You entered: %d\n", number);
    printf("Please enter a single character: ");
    // 注意:在 %c 前加一个空格,可以跳过之前输入留下的换行符
    scanf(" %c", &grade); 
    printf("You entered: %c\n", grade);
    printf("Please enter your full name: ");
    // scanf 读取字符串时,遇到空格就停止,所以不能读取带空格的名字。
    scanf("%s", full_name); 
    printf("Hello, %s\n", full_name);
    printf("Please enter your GPA: ");
    int ret2 = scanf("%lf", &gpa); // 必须使用 %lf 来读取 double
    if (ret2 != 1) {
        printf("Failed to read a double.\n");
        return 1;
    }
    printf("Your GPA is: %.2f\n", gpa);
    return 0;
}

scanf 的常见问题与解决方案

问题1:缓冲区残留的换行符

当你使用 scanf("%d", &num); 读取一个整数后,按下的回车键(\n)会留在输入缓冲区中,如果下一个 scanf"%c",它会直接读取这个残留的换行符,而不是等待你输入新字符。

c语言 scanf printf
(图片来源网络,侵删)

解决方案: 在 "%c" 前面加一个空格 " %c",这个空格会告诉 scanf 跳过所有的空白字符(包括换行符),直到遇到一个非空白字符。

问题2:scanf 的返回值检查

如果用户输入了非预期的数据(比如你期望输入数字,但用户输入了字母),scanf 会失败,错误的输入会留在缓冲区中,导致后续的 scanf 也立即失败,程序可能进入死循环。

解决方案始终检查 scanf 的返回值,如果返回值不等于你期望读取的变量个数,就说明出错了,这时,你需要清空输入缓冲区,防止后续读取失败。

c语言 scanf printf
(图片来源网络,侵删)

示例:健壮的输入处理

#include <stdio.h>
#include <ctype.h> // 用于 isprint 函数
void clear_input_buffer() {
    int c;
    // 读取并丢弃缓冲区中所有剩余的字符,直到遇到换行符或文件结尾
    while ((c = getchar()) != '\n' && c != EOF); 
}
int main() {
    int age;
    printf("Enter your age: ");
    // 循环直到成功读取一个整数
    while (1) {
        int result = scanf("%d", &age);
        if (result == 1) {
            // 成功读取,跳出循环
            break; 
        } else if (result == EOF) {
            printf("Input ended unexpectedly.\n");
            return 1;
        } else {
            // 输入无效,清空缓冲区并提示用户重新输入
            printf("Invalid input. Please enter an integer: ");
            clear_input_buffer();
        }
    }
    printf("You are %d years old.\n", age);
    return 0;
}

scanfprintf 的总结与对比

特性 printf scanf
功能 输出数据到屏幕 输入数据从键盘
参数 变量 变量地址 (用 & 获取)
返回值 成功打印的字符数 成功赋值的参数个数
double类型 使用 %f%lf 必须使用 %lf
健壮性 相对简单,不易出错 需要检查返回值并处理缓冲区,容易出错
核心 将内存中的数据转换为字符流显示 将键盘输入的字符流转换为内存中的数据

最佳实践

  1. 使用 printf,格式化字符串要清晰,适当使用 \n 控制换行。
  2. 使用 scanf
    • 务必检查返回值
    • 对于 char 类型,考虑在格式说明符前加空格 " %c" 来跳过空白。
    • 如果输入可能失败,准备好清空输入缓冲区的函数。
  3. 对于复杂的输入输出场景,尤其是读取整行文本(包括空格),scanf 往往不是最佳选择,可以考虑使用 fgets + sscanf 的组合,或者直接使用 fgets 然后自己解析字符串。
-- 展开阅读全文 --
头像
c语言double printf
« 上一篇 2025-12-24
dede archives分表如何实现?
下一篇 » 2025-12-24

相关文章

取消
微信二维码
支付宝二维码

目录[+]