不同于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 (-2147483647 - 1)
#define INT_MAX 2147483647
integer 整型
short
:长度为2,范围为 -32767~32767int
:长度为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位,范围的末尾有fdouble
:长度为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外的参数加入这个位置。

占位符到转换说明
占位符就是写在第一个字符串参数中%
开头的,形如%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()
先给示例:

#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>
。
评论 (0)