不同于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)