printf函数和scanf函数很简单吗?其实里面大有学问!

数据类型介绍

常见的数据类型有整型类型、字符类型、浮点类型。

整型类型来描述整数,字符类型来描述字符,浮点类型来描述小数。

具体类型如下图

printf函数和scanf函数很简单吗?其实里面大有学问!_第1张图片

整型

在程序定义一个整型可以使用int

int在内存中占4个字节

由于在内存中定义一个int可使用的空间有限

若数据较大内存无法存储过多

此时定义一个整型可以使用long int 或者 long long int

long int 占 4或8个字节(64位编译器即为8字节,32编译器即为4字节) long long int 占8个字节

本着不浪费空间的原则,一般定义int就够用了

若数据更小,如年龄最多只为3位数这类的,可以用short int定义,位2个字节(一个字节8个bit,若是无符号位则可存储8位二进制数,有符号位为7位二进制数,关于内存中符号位有更多内容,就不展开了)

int x; //4个字节
short int x;//2个字节
long int x;//4或8个字节
long long int x;//8个字节

字符型

程序定义一个字符型可以使用char

char在内存中占1个字节

char x;

浮点型

在程序定义一个浮点型可以使用float

float在内存中占4个字节

double在内存中占8个字节

long double在内存中占12个字节

浮点型和整型类似(本着节省空间的原则看情况使用多大字节来定义)

float x;//4个字节
double x;//8个字节
long double x;//12个字节

布尔类型

在C99中也引入了布尔类型,来专门表示真or假

true表示真,falsse表示假

但是布尔类型的使用需要包含头文件

bool类型可以用在判断或者循环语句中作为条件

#include 

int main()
{
    _Bool x = true;
    if (x) {
      printf("helloworld");
    }
}

数据类型的长度

sizeof 操作符

sizeof是一个关键字,也是操作符,抓门用来计算sizeof的操作符数的类型长度的,单位是字节。

printf("%d",sizeof(int)) //输出即为4(int类型4个字节)

注:sizeof 中表达式不计算

#include 

int main()
{
    short a = 2;
    int b = 10;
    printf("%d\n",sizeof(a = b + 1));
    printf("a = %d",a); //运行结果为 a = 2
    return 0;
}

signed 和 unsigned

signed 关键字表示一个类型带有正负号,包含负值

unsigned 关键字表示该类型不带有正负号,只能表示零和正整数

这两个关键字是用来修饰字符型整型

int类型

对于整型(int)来说,默认是带有正负号的,也就是说 int 等同于 signed int

所以一般signed可以省略,当然加上也不会有错误

signed int x;
//等同于
int x;

用unsigned的好处是,同样长度的内存能够表示的最大整数值增大了一倍

例如:signed short int 为2个字节,也就是16个bit,第一个为符号位,则取值范围为(-32768~32767),而unsigned short int 的取值范围是:(0~65535),最大值增大了一倍

char类型

而在字符类型char中,C语言规定 char 类型默认是否带有正负号,是由当前系统决定的

所以 char 不一定等于 signed char ,也有可能等于 unsigned char

signed char a; //范围为 -128 ~ 127
unsigned char a; //范围为 0 ~ 255

变量

C语言中把经常变化的值称为变量,不变的值称为常量

变量的创建

变量创建的语法形式如下

char name; //char 为数据类型,name为变量名
int age; //整型变量
char ch; //字符变量
double weight; //浮点型变量

如果给变量一个初始值,就叫初始化

int age = 10;
char ch = 'w';
double weight = 50.5;

变量的分类

全局变量

全局变量:在大括号外部定义的变量就是全局变量

全局变量的使用范围更广,整个工程中想使用,都是有办法使用的

#include 

int a = 10;
int main()
{
    printf("a = %d",a);  // 输出结果为 a = 10
    return 0;
}

局部变量

局部变量:在大括号内部定义的变量就是局部变量

局部变量的使用范围比较局限,只能在自己所在的局部范围内使用

#include 


int main()
{
    int a = 10;
    printf("a = %d",a);  // 输出结果为 a = 10
    return 0;
}

如果有两个相同的变量名字a既在大括号外部定义也在内部定义会发生什么?

#include 

int a = 10;
int main()
{
    int a = 5;
    printf("a = %d",a);  // 输出结果为 a = 5
    return 0;
}

如此看来局部变量的优先级是高于全局变量的

一般我们在学习C语言或者C++的时候都会关注内存里的三个区域:栈区、堆区、静态区

printf函数和scanf函数很简单吗?其实里面大有学问!_第2张图片

算术操作符:++、--、+、-

在写代码的时候,一定会涉及计算,为了方便计算,C语言提供了一种操作符,名叫算术操作符。分别有+ - * / %,这些操作符都是双目操作符

注:操作符也被叫做算术符

运算符+ 和 -

+和-都是用来完成加法和减法,加和减都是有两个操作数的,这种操作符也被叫做双目操作符

加法如下:

#include 

int main()
{
    int a = 5,b = 10,ret; //初始化
    ret = a + b;     //运算结果
    printf("%d", ret);     //打印结果ret = 15
    return 0;
}

减法如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include 

int main()
{
    int a = 5,b = 10,ret;
    ret = b - a;      //减法运算
    printf("%d", ret);   //打印结果为 ret = 5
    return 0;
}

运算符*

运算符*是用来进行乘法运算,如:

#include 
int main()
{
 int num = 5;
 printf("%d\n", num * num); // 输出 25
 return 0;
}

运算符/

运算符/是用来进行除法运算,如:

#include 
int main()
{
 float x = 6 / 4;
 int y = 6 / 4;
 printf("%f\n", x); // 输出 1.000000
 printf("%d\n", y); // 输出 1
 return 0;
}

至于为什么 6 / 4结果为1,是因为 6和4都为整型数据,除法运算之后得到的结果只能为整型数据,所以得到的计算他的商,x和y都被赋值6/4,故都为1,但x为float类型,所以会有小数点

再来看个例子:

#include 
int main()
{
 int score = 5;
 score = (score / 20) * 100;
 return 0;
}

如果你经过一通计算,可能会认为score的结果为25,但其实答案是0

因为score先除以20,再乘的0,在除以20的过程中,结果已经变成了0,所以0*100=0

运算符%

运算符%是进行取余运算,该运算符只能用于2个整型数据,如:

#include 
int main()
{
 int x = 6 % 4; // x = 2
 return 0;
}

负数的规则是结果的正负号由第一个运算数的正负号决定,例如:

#include 

int main()
{
    int a = -10 , b = 4 , ret;
    ret = a % b;
    printf("ret = %d\n", ret); //ret = -2
    b = -4;
    printf("ret = %d\n", ret); //ret = -2
    return 0;
}

开头的a = -10决定了ret只能是负数

赋值操作符:= 和复合赋值

连续赋值

在变量创建时给予的值叫做初始化,而变量创建好后给予一个值叫做赋值

int a = 100;//初始化
a = 200;//赋值,这⾥使⽤的就是赋值操作符

赋值操作符=是一个可以随时可以给变量赋值的操作符

赋值操作符可以连续赋值,例如:

int a = 3;
int b = 4;
int c = 5;
c = b = a + 5;

上图最后一行的操作可以等同为

b = a + 5;
c = b;

但建议还是拆开来写,这样更方便自己和他人看代码

复合赋值符

在写代码时,我们经常可能对一个数进行自增自减的操作,如下代码:

int a = 10;
a = a+3;
a = a-2;

在C语言中提供了 很多方便的操作符有:+= -= *= /= %= >>= <<= &= |= ^=,这些复合赋值符更加方便了我们编写代码

例如上述代码可用以下代码替换,效果相等

int a = 10;
a += 3;
a -= 2;

单目操作符

前面介绍的都是双目操作符,有两个操作数,现在所说的单目操作符,只要一个操作数,被称为单目操作符。

++和--

++和--是一种自增或自减的操作符,都分为前置++(--)、后置++(--)

前置++

int a = 10;
int b = ++a;  //++a将a + 1,再将a+1赋值给b
printf("a = %d,b = %d",a,b); //输出结果为a = 11,b = 11

上述代码也可以理解为:

int a = 10;
a = a + 1;
int b = a;
printf("a = %d,b = %d",a,b);

计算口诀为:先加1,后使用

a原先为10,之后加了1变成11,11再赋值给b

后置++

int a = 10;
int b = a++; //先赋值给b,a再自增
printf("a = %d,b = %d",a,b); //输出结果为a = 11,b = 10

上述代码也可以理解为:

int a = 10;
int b = a;
a = a + 1;
printf("a = %d,b = %d");

计算口诀为:先使用,后加1

a原先为10,先使用赋值给了b,再加1

前置--

如果你听明白了前置++,那么前置--也类似,只是将+1变成-1

int a = 10;
int b = --a;  //--a将a - 1,再将a-1赋值给b
printf("a = %d,b = %d",a,b); //输出结果为a = 9,b = 9

计算口诀:先使用,后减1

后置--

与后置++类似

int a = 10;
int b = a--; //先赋值给b,a再自减
printf("a = %d,b = %d",a,b); //输出结果为a = 9,b = 10

计算口诀:先减1,后使用

强制类型转换

操作符中还有一种特殊的操作符是强制类型转换,形式如下:

int a = 3.14;
//a的是int类型, 3.14是double类型,两边的类型不⼀致,编译器会报警告

如果为了消除这种警告,我们可以强制类型转换

int a = (int)3.14;
//意思是将3.14强制类型转换为int类型,这种强制类型转换只取整数部分

强扭的瓜不甜,如果不需要强制类型转换就能实现代码,就尽量不要使用

scanf和printf介绍

printf

基本用法

printf的作用是将参数的文本输出到屏幕上,print表示打印,f是format(格式化),表示可以定制输出文本格式

#include 

int main()
{
    printf("Hello world\n");
    return 0;
}

上面的代码会将Hello world输出到屏幕上

printf不会在行尾自动添加换行符,光标就停留在末尾

若想换行输出新内容,可以使用\n添加这个换行符

#include 
int main(void) 
{
    printf("Hello\nWorld\n"); //输出为Hello
    return 0;                 //     World
}

printf()是在标准库的头文件stdio.h定义的。使用这个函数之前必须加上这个头文件

占位符

在前面的代码中

printf函数和scanf函数很简单吗?其实里面大有学问!_第3张图片

%d即为占位符占位符的第一个字符必须为%,第二个字符表示占位符的类型,%d表示里面填入的是一个整数

输出文本里面可以使用多个占位符,上面的代码就是使用了两个,并传递了两个变量,他们是一一对应的关系,如果不给东西给占位符,那么很可能会输出一个随机值

占位符举例

printf函数和scanf函数很简单吗?其实里面大有学问!_第4张图片

输出格式

printf()可以定制占位符的输出格式

限定宽度
#include 
int main()
{
 printf("%5d\n", 123); // 输出为 " 123"
 return 0;
}

%5d表示这个占位符的宽度至少为5位,所以上面只有123的话不够5位,会自动添加两个空格补齐,默认是右对齐,如果希望是左对齐,可以加个-,如下:
 

#include 
int main()
{
 printf("%-5d\n", 123); // 输出为 "123 "
 return 0;
}

当然也可以对%f使用,如:

#include 
int main()
{
 printf("%12f\n", 123.45);  // 输出 " 123.450000"
 return 0;
}

一共也是十二位,小数点后默认6位,再向前补齐两位,所以自动添加了两个空格

总是显示正负号

默认情况下,printf()不会有正号在前面,只会显示负号,我们可以这么做

#include 
int main()
{
 printf("%+d\n", 12); // 输出 +12
 printf("%+d\n", -12); // 输出 -12
 return 0;
}
限定小数位数

输出小数时,会默认输出小数点后六位,如果只希望有两位的话,可以这么做:

#include 
int main()
{
 printf("Number is %.2f\n", 0.5); //输出Number为0.50
 return 0;
}

如果想保留三位的话,可以改成%.3f

所以还能这么做:

#include 
int main()
{
 printf("%6.2f\n", 0.5);  // 输出为 "  0.50"
 return 0;
}

%6.2f的6将最小宽度定为6,2是保留两位小数,所以输出0.50的时候会在前面加上两个空格,(.)也算一位

当然以上最小宽度和小数位数这两个限定值,都可以用*代替,通过printf()的参数传入,如:

#include 
int main()
{
 printf("%*.*f\n", 6, 2, 0.5);
 return 0;
}
// 等同于printf("%6.2f\n", 0.5);
输出部分字符串

%s用来表示输出字符串,默认是全部输出。如果只想输出指定长度,可以用 %.[m]s 指定输出的长度,其中[m]代表一个数字,表示所要输出的长度,如下:

#include 
int main()
{
 printf("%.5s\n", "hello world"); //只输出了hello
 return 0;
}

上面的 %.5s 表示只要5个字符,即为hello

scanf

当我们定义了一个变量,如果我们需要给变量输入值就可以使用 scanf()函数,如果要打印在屏幕上就用printf()函数,如下:

#include 
int main()
{
 int score = 0;
 printf("请输⼊成绩:");
 scanf("%d", &score);
 printf("成绩是:%d\n", score);
 return 0;
}

运行结果为

printf函数和scanf函数很简单吗?其实里面大有学问!_第5张图片

下面来介绍scanf()函数

基本用法

scanf()用于读取用户的键盘输入

当程序运行到了scanf()函数的时候就会停止运行,等待用户输入,当用户输入完毕就带着用户赋给变量的值继续运行,使用scanf()函数时也要注意和printf()函数一样,都需要包含头文件stdio.h

scanf()的语法与printf()类似

scanf("%d", &i);

但要注意的是一般的变量前面都要加入&这个取地址符号,不一般的情况就是变量本身就是地址,例如数组、指针这些赋值时可以不用&

在用户输入数值时,会自动过滤空白符号,包括空格制表符换行符

所以用户输入时,有多个空格和换行并不影响scanf()函数解读

解读用户输入时,如果上次的scanf()函数输入的值过多,则这次会从上一次遗漏的第一个字符开始,直到读完缓存,或者遇到不符合条件的字符为止

#include 
int main()
{
 int x;
 float y;
 
 // ⽤⼾输⼊ " -13.45e12# 0"
 scanf("%d", &x);
 printf("%d\n", x);
 scanf("%f", &y);
 printf("%f\n", y);
 return 0;
}

上述代码中,第一个scanf()函数只会解读到-13,然后碰到.就结束,因为它并不属于有效字符,然后下一个scanf()就会开始读取.45e12 (e12表示的是12次方),到#不属于有效字符就停止了,以下是结果

printf函数和scanf函数很简单吗?其实里面大有学问!_第6张图片

前面的-13理所当然

而后面的一长串其实应该是0.45 * 10 ^ 12,但内存中数据有时候无法精确保存,所以算出来的值是近似相等而不是绝对相等。所以0.45 * 10 ^ 12进去后保存的就是最后那一行的数字

scanf的返回值

scanf函数返回的是一个整数,表示成功读取的变量个数。

如果没有读取到任何项或者保存失败,则返回0,如果在读取成功之前发生了读取错误或者遇到读取到该文件末尾,则返回常量EOF

#include 
int main()
{
 int a = 0;
 int b = 0;
 float f = 0.0f;
 int r = scanf("%d %d %f", &a, &b, &f);
 printf("a=%d b=%d f=%f\n", a, b, f);
 printf("r = %d\n", r);
 return 0;
}

结果为

printf函数和scanf函数很简单吗?其实里面大有学问!_第7张图片

如果输入两个数按 ctrl + z提前结束,可以看见

printf函数和scanf函数很简单吗?其实里面大有学问!_第8张图片

这时候r=2

如果直接按 ctrl + z

printf函数和scanf函数很简单吗?其实里面大有学问!_第9张图片

则返回值为EOF也就是-1

赋值忽略符

有时用户的输入可能不符合scanf的格式

#include 
int main()
{
 int year = 0;
 int month = 0;
 int day = 0;
 scanf("%d-%d-%d", &year, &month, &day);
 printf("%d %d %d\n", year, month, day);
 return 0;
}

上面示例中,如果用户输入2023-11-24就可以正常读入,但万一用户是输入2023/11/24呢?

为了避免这种情况,scanf函数提供了一种赋值忽略符,只要把*加在任意的占位符的百分号后面,该占位符就不会返回值,解析后将被丢弃

#include 
int main()
{
 int year = 0;
 int month = 0;
 int day = 0;
 scanf("%d%*c%d%*c%d", &year, &month, &day);
 return 0;
}

这样就可以成功避免格式不对而导致的错误了

希望此文章对您有帮助

你可能感兴趣的:(c语言)