Nibbles Blog Nibbles Blog
  • 专题汇总
    • 技术学习
    • 个人成长
    • 运营技能
    • 自媒体
    • Minecraft
  • 推荐
    • 好物推荐
    • APP推荐
  • 关于我
    • Nibbles Studio
  • 友情链接
首页 › 技术学习 › 谈谈printf()和scanf() | C语言基础

谈谈printf()和scanf() | C语言基础

Avatar photo
Nibbles 尼布
20 4 月, 2025

不同于Python,直接就可以使用类似的print()和input(),C语言中这两个库函数都需要引入最基础的表示输入输出的stdio.h头文件
#include <stdio.h>

博主环境使用Windows 11,C语言IDE大多用的是Visual Studio 2022,校内使用CFree5;
按认识顺序撰文,从helloworld认识printf(),而后认识scanf()

1. printf() 打印输出

相比于博主之前学过的Python语言中的print(),C语言中的printf(),从函数名上多了个f字母,代表format(格式),说明可以定制输出⽂本的格式,这文本格式也叫数据类型。

数据类型

Intro

参考文档:https://zh.cppreference.com/w/c/language/arithmetic_types#.E6.95.B0.E6.8D.AE.E6.A8.A1.E5.9E.8B

sizeof() 函数

sizeof()是个用于计算操作符类型长度的函数,输出的单位为字节(Bite)(换算:1Bite=8bit)
虽然输出的单位是字节,看着输出类型好像是整数,但是根据实际的编辑器输出的附加提示可得这是size_t类型。所以printf中的占位符应该是%zd。

#include <stdio.h>
int main()
{
    printf("%zd",sizeof(int));  // 输出:4(表示int类型的长度为四个字节)
    return 0;
}
根据头文件来查数据类型对应的取值范围
  • limits.h ⽂件中说明了整型类型的取值范围。
  • float.h 这个头⽂件中说明浮点型类型的取值范围。(有的编译器下可能没有写)
    取值范围的极限值都是定义在头文件中的一些常量里的,比如INT_MIN、INT_MAX代表int数据类型的最⼩值和最⼤值,这些我们叫宏常量。
// 节选自limits.h

#define INT_MIN &nbsp; &nbsp; (-2147483647 - 1)
#define INT_MAX &nbsp; &nbsp; &nbsp; 2147483647

integer 整型

  • short:长度为2,范围为 -32767~32767
  • int:长度为4,范围为 -2147483647~2147483647
    (初学者目前刷到的题目都是int就能解决的,只要注意题目中有关于2147483647的提示就直接用int,巧记Tips:我们学校的学号正好和此范围都是十位数)
  • long:长度为4,范围为 -2147483647L~2147483647L (注意末尾有L)
  • long long:长度为8,范围为 -9223372036854775807i64~9223372036854775807i64
    (在算法竞赛中,为了不让长度作为判题有误的限制,一般使用long long)
  • unsigned int: 范围为0~4294967295,可以简写为unsigned
关于 signed 或 unsigned

C语⾔使⽤ signed 和 unsigned 关键字修饰字符型和整型的。
signed 关键字,表⽰该类型带有正负号,可以包含负值;
unsigned 关键字,表⽰该类型不带有正负号,只能表⽰零和正整数。
默认不带此关键字的话,省略的前缀为 signed
整数变量声明为 unsigned 的好处是,同样⻓度的内存能够表⽰的最⼤整数值,增⼤了⼀倍。

floating-point 浮点型

ps:到浮点型的话,范围数字很长,所以这里直接用十进制小数点位数来代表范围

  • float:长度为4,单精度,精确到小数点后6位,范围的末尾有f
  • double:长度为8,双精度,精确到小数点后15位。
  • long double:长度为8(msvs)或16(gcc),精确到小数点后15位,但实际范围比double更大。

character 字符型

char 字符类型,长度为1,字符型的常量一般用单引号包围'',这点尤其注意。
如果是转义字符,比如 \n,\0,\t都算作一个字符。
再比如有些看不见的操作也可以算作一个字符,比如空格和换行。

bool 布尔型

C语⾔原来并没有为布尔值单独设置⼀个类型,⽽是使⽤整数 0 表⽰false(假),⾮零值表示true(真)。
在 C99 标准中引⼊了布尔类型来表⽰真假的,需要包含<stdbool.h>头文件 #include <stdio.h>。
(对于老一点的编译器可能需要C99支持,比如CFree)
布尔类型(_Bool)长度为1,其类型的变量取值仅有true和false两个。

#include <stdio.h>
int main()
{
    // 整型
    printf("%hd", 5); //short对应的
    printf("%d", 5);  // int对应的【常用】
    printf("%ld", 5);  // long对应的
    printf("%lld", 5);  // long long对应的

    // 浮点型:根据小数点后面取到的位数不同选择不同的数据类型
    printf("%f", 3.14f);  // float对应的,注意末尾有f
    printf("%lf", 3.1415); // double对应的 【常用】
    printf("%Lf", 3.1415); // long double 对应的,注意大写L

    // 字符型:字符和其对应的ASCII码值是对应的
    printf("%c", 'A');
    printf("%c", 65);

    // 字符串
    printf("%s", "HelloWorld");
}

输出格式

基本格式

printf() 不会在⾏尾⾃动添加换⾏符,运⾏结束后,光标就停留在输出结束的地⽅,不会⾃动换 ⾏。
那么其中有占位符表示输入格式的部分,需要借助双引号参数1外的参数加入这个位置。

谈谈printf()和scanf() | C语言基础-Nibbles Blog

占位符到转换说明

占位符就是写在第一个字符串参数中%开头的,形如%d,%f,在一定位置可表示要填入的参数格式/控制参数输出格式的这类字符。
占位符表格:

数据类型变量声明类型占位符
短整型short%hd
整型int%d
无符号整型unsigned int%u
长整型long%ld
无符号长整型unsigned long int%lu
长长整型long long%lld
单精度浮点型float%f
双精度浮点型double%lf
长双精度浮点型long double%Lf
字符型char%c
字符串型String%s
指针(独立类型)–%p

如果对于上面表格中写的部分,那么只看这种占位符其实也是转换说明,但如果加上下面这些后就算是转换说明,转换说明基本格式如同%m.pX 或 %-m.pX。

限定最小宽度

在占位符中间插入数字(或转化说明基本格式中的小数点前的数字m)即代表输出的最小宽度。
最小宽度的理解:宽度对于整型来说就是数字位数,如果说位数小于最小宽度,会在数字前面自动补空格直到是最小宽度;如果给出的位数已经超过了最小宽度,那么直接输出。
默认在数字前面补空格即右对齐,如果需要左对齐的话,可以再在%后加一个-。

#include <stdio.h>
int main(){
    printf("%d\n", 123);   // Output:"123"
    printf("%5d\n", 123);  // Output:"  123"
    printf("%-5d\n", 123); // Output: "123  "
    return 0;
}
始终显示正负号

在占位符中间插入+就可以了。(和上面的的-的用法要分清哦!)

#include <stdio.h>
int main()
{
    printf("%+d\n", 123);  // Output: "+123"
    printf("%+d\n", -123); // Output: "-123"
    return 0;
}
限定小数点后位数

%和字母之间的小数点后紧接着的数字(或转化说明基本格式中的小数点前的数字p)就代表要保留的位数,会四舍五入到这个指定的位数。

#include <stdio.h>
int main()
{
    printf("%.2f\n", 1.233);  // Output: "1.23"
    printf("%.2f\n", 1.236);  // Output: "1.24"
    return 0;
}

ps:默认不指定保留几位的时候,输出的最多位数取决于数据类型精度。
可以和限定最小宽度的一起使用,小数点算一个宽度。

#include <stdio.h>
int main()
{
    printf("%5.2f\n", 1.236);  // Output: " 1.24"
    return 0;
}
输出部分字符串

如果把上面限定小数点后位数的方法,用到字符串输出用的%s上,那就是可以指定字符串输出的长度了。

#include <stdio.h>
int main()
{
    printf("%.7s\n", "Nibbles is handsome.");  // Output: "Nibbles"
    return 0;
}
限定值以 * 代
#include <stdio.h>
int main()
{
    printf("%*.*f\n", 6, 2, 0.5);  // Output: "  0.50"
    return 0;
}

2. scanf() 输入

除了按照上述的直接输出的程序方式。一个完整的简单程序应该有IO两部分(Process处理后续涉及):Input(输入),Output(输出)。 输出方式就是上面的 printf() 打印到屏幕,输入就是scanf()
先给示例:

谈谈printf()和scanf() | C语言基础-Nibbles Blog
#include <stdio.h>
int main()
{
    int num = 0;
    scanf("%d", &num);
    printf("Number: ", num);
}

变量

定义 = 声明 + 内存分配

int num = 0;

这样是定义了一个变量 num,并将其初始化,初始值设置为0。
变量的定义过程是 int num 部分,此时会在内存中分配一个空间。

extern 单独声明

extern int external_var;

单独只有声明的需要使用 extern 关键字,一般在头文件中声明,但不分配内存。
但是如果在其他文件中已经有定义了变量,在该文件中想要引用其他文件的定义可以使用 extern

变量的生命周期控制

全局变量

在函数的 { } 之外定义的变量,初始化如果不指定是默认为0。
如果是在定义之前使用 extern (如上在头文件中单独声明案例)
在内存的静态存储区。在整个程序中:程序开始执行时创建,在程序结束时销毁。

局部变量

在函数的 { } 之内定义的变量,要是出了花括号的部分就没法再引用。
在整个程序中:进入程序中变量所在函数时创建,在退出该函数时销毁。
通常存储在栈区(auto 变量)。使用 static 关键字把变量变为静态变量,默认初始值才可以是0,否则没有初始值是随机数,此时在内存的静态存储区。

变量的命名规则

  • 可以包含的字符:字母(a-z, A-Z)、数字(0-9)和下划线(_) 。
  • 第一个字符必须是字母或下划线。
  • 变量名区分大小写。
  • 变量名不能是C语言的关键字。
    • 关键字:auto, break, case, char, const, continue, default, do, double, else, enum, extern, float, for, goto, if, int, long, register, return, short, signed, sizeof, static, struct, switch, typedef, union, unsigned, void, volatile, while
  • 应选择具有描述性的变量名,以便于理解变量的用途(不建议学大学里课堂上那样,为了图快而使用abc这样的单字母变量名)。

输入格式

基本格式

如下在程序执行时,会在冒号后面停留光标,等待你输入整数。之后回车即可把刚输入的整数赋给value整型变量。

第一个参数就是格式化字符串,之后的参数的基本格式应该是 <取地址运算符><变量名>
一次可以读入多个变量,但是要注意,有多少个占位符/转换说明,后面其后就要有多少个参数,遵循按顺序对应。如果一次输入多个值,各个值之间常可以用空格换行隔开,函数处理时候会⾃动过滤空⽩字符,包括空格、制表符、换⾏符。(但是如果是%c会把空格作为一个字符,如果要忽略可以写成% c,即在%和字母间加个空格)
scanf()函数中的占位符决定了输入的格式。如果输入的格式不一样的话,会强制把输入的截断到与占位符表示的格式一样的部分。

#include <stdio.h>
int main()
{
    int num_int;
    float num_float;
        // Input: "3.14"
    scanf("%d", &num_int);  
    printf("%d\n", num_int);   // Output: "3"
    scanf("%f", &num_float);
    printf("%f\n", num_float); // Output: "0.140000"
}

还可以简化为:

#include <stdio.h>
int main()
{
    int num_int;
    float num_float;
        // Input: "3.14"
    scanf("%d%f", &num_int, &num_float);  
    printf("INT: %d\nFLOAT: %f\n", num_int, num_float); 
    /**
    Output:
        INT: 3
        FLOAT: 0.140000
    */
}

字符串输入不建议使用该函数,%s 不会包含空⽩字符,所以⽆法⽤来读取多个单词组成的短语/句子。读入时不会检测字符串是否超过数组⻓度。储存字符串时,很可能报错表示超过数组的边界。

函数返回值和EOF文件结束

在刷题时候,碰到题目要求函数式编程,在题目中已经给出了基本的代码结构,如下:

#include <stdio.h>
void print(int m, int n);

int main() {
    int m, n;
    while (scanf("%d%d", &m, &n) != EOF) {
        print(m,n);
        printf("\n");
    }
    return 0;
}

在while的表达式里有关于scanf()函数返回值的条件语句。
scanf()函数的返回值是个整数,且是和函数的占位符数是一致的。如果什么都没读取到就是返回0。如果在成功读取任何数据之前,发⽣了读取错误或者遇到读取到⽂件结尾,则返回常量 EOF (-1)。
那么这个EOF的结束效果如何在我们输入中体现呢?
Ctrl+Z 连按三次(VS2022中的效果),或者其他有的编译器中按一次即可。

赋值忽略说明

这一符号的设计主要是服务用户的。比如你规定了日期的输入格式为2025/4/19,结果输了个2025.4.19。此时就需要赋值忽略符(assignment suppression character)这样的处理了。

#include <stdio.h>
int main()
{
    int year = 0;
    int month = 0;
    int day = 0;
    scanf("%d%*c%d%*c%d", &year, &month, &day);
    printf("%d-%d-%d", year, month, day);
    return 0;
}

这里的 %*c 中间的*就是作为赋值忽略符,这里的 %*c 可以不必和后面参数对应,不必返回,且读取到值也不输出,我们输出格式在 printf()函数里标定了 <year>-<month>-<day> 。

声明:本站原创文章文字版权归本站所有,转载务必注明作者和出处;本站转载文章仅仅代表原作者观点,不代表本站立场,图文版权归原作者所有。如有侵权,请联系我们删除。
C语言
1
0
Avatar photo
Nibbles 尼布
向着终生成长者迈进!
赞赏

评论 (0)

取消
    发表评论

猜你喜欢

  • 从本质理解指针的那些知识 | C语言基础
  • 从猜数字程序来理解结构和随机数 | C语言基础
  • CTF Web 信息搜集 知识总结
Avatar photo

Nibbles 尼布

向着终生成长者迈进!
24
文章
4
评论
34
获赞

多平台更新

▲ “尼布是我”小程序
▲ 个人公众号

热门文章

TOP1
Python数据分析 Ⅰ:pandas模块
7 6 月, 2023
TOP2
更大挑战,更多机遇 | 2023 年终总结
8 1 月, 2024
TOP3
【杂谈】真的需要系统地学那么多编程语言吗?
14 8 月, 2024

标签云

AI (2) anaconda (1) Bilibili (1) Cookie (1) CS50x (1) CTF (1) C语言 (4) Git (1) Github (1) HTTP (1) Java (1) matplotlib module (1) Minecraft (2) NamelessMC (1) pandas module (1) PHP (1) python (2) Serverless (1) vim (1) VuePress (1) WordPress (1) zeabur (1) 公众号 (2) 年终总结 (2) 思维导图 (1) 换源 (1) 数据库 (1) 杂谈 (1) 浪前 (2) 自媒体 (2) 解密 (1) 运营 (2) 飞书 (1)

支持我!

Blog Circle

开往-友链接力
博客录(boke.lu) 随机博客
博客圈
  • SiteMap
  • Umami
  • xLog
  • Substack
Copyright © 2022-2025 Nibbles Blog. Designed by nicetheme. 浙公网安备33038102332481号 浙ICP备2024120131号
技术博客: AHdark Blog Tkong Blog iVampireSP 的物语 我不是咕咕鸽 热心市民 L 先生 ncc的个人网站 岚天小窝 天远笔记
  • C语言4
  • python2
  • AI2
  • 公众号2
  • 运营2
  • 专题汇总
    • 技术学习
    • 个人成长
    • 运营技能
    • 自媒体
    • Minecraft
  • 推荐
    • 好物推荐
    • APP推荐
  • 关于我
    • Nibbles Studio
  • 友情链接