• [一篇读懂]C语言一讲:数据的类型、数据的输入输出



    1. 数据类型-常量-变量(整型-浮点-字符)

    1 数据类型

    数据类型分类:
    数据类型
    关键字:

    autoconstdoublefloatintshortstructunsigned
    breakcontinueelseforlongsignedswitchvoid
    casedefaultenumgotoregistersizeoftypedefvolatile
    chardoexternifreturnstaticunionwhile

    2 常量

    • 常量指在程序运行过程中,值不发生变化的量。
    • 可分为整型、实型(也称浮点型)、字符型和字符串型。
    • 整型 - 100,125,-100,0
    • 实型 - 3.14,0.125,-3.789
    • 字符型 - ‘a’,‘b’,‘2’
    • 字符串型 - “a”,“ab”,“1c34”

    3 变量

    变量名、变量值和存储单元的关系:
    变量

    • 变量指内存中具有特定属性的一个存储单元,它用来存放数据,即变量的值。
    • 这些值在程序的执行过程中是可以改变的。
    • 每个变量名分配对应的内存地址(空间)。
    • 变量命名规定如下:只能由字母、数字和下划线三种字符组成,并且第一个字符必须为字母或下划线。

    例如:
    sum,_total,month,Student_name,lotus_1_2_3,BASIC,li_ling
    是正确的。
     
    而M.D.John,¥123,3D64,a>b
    是错误的。

    • 先定义,后使用
    • 尽量做到“见名知意”,注意,变量名不能与关键字同名!

    4 整型数据

    4.1 符号常量

    定义整型变量时要使用关键字int:

    #include 
    
    #define PI 3+2
    int main()
    {
    	int i = PI * 2;
    	printf("i = %d\n",i);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    最终输出的结果是7,原因是符号常量PI是直接替换的效果,即3+2*2=7,而不是8。

    4.2 整型变量

    • 通过int i来定义整型变量,i占用4个字节空间

    5 浮点型数据

    5.1 浮点型常量

    • 表示浮点型常量的方式有两种,如下所示,其中e代表10的幂次,幂次可正可负。
    小数形式指数形式
    0.1233e-3(为 3 × 1 0 − 3 3×10^{-3} 3×103,即0.003)
    • 注意,字母e(或E)之前必须有数字,且e后面的指数必须为整数。

    正确示例:1e3、1.8e-3、-123e-6、-.1e-3。
    错误实例:e3、2.1e3.5、.e3、e。

    5.2 浮点型变量

    • 通过float f来定义浮点变量,f占用4个字节空间

    6 字符型数据

    6.1 字符型变量

    • 用单引号括起来的一个字符是字符型常量,且只能包含一个字符! 例如, ‘a’、‘A’、‘1’。
    • ’ '是正确的字符型常量。

    ‘abc’、“a”、" "是错误的字符型常量。

    • 转义字符:以“\”开头的特殊字符,转义字符可用来表示回车、退格等功能键。
    转义字符作用
    \n换行
    \b退格
    \\反斜杠

    6.2 字符数据在内存中的存储形式及使用方法

    • 字符型变量使用关键字char进行定义,一个字符型变量占用1字节大小的空间。
    • 一个字符常量把该字符的ASCII码值放到存储单元中。
    • 字符型数据和整型数据之间可以通用。
    • 字符型数据既可以以字符形式输出,又可以以整数形式输出,还可以通过运算获取想要的各种字符:
    #include 
    int main()
    {
    	char c = 'A';
    	printf("%c\n",c+32);
    	printf("%d\n",c);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 对于字符型变量,无论是赋ASCII码值还是赋字符,使用%c打印输出时得到的都是字符,使用%d打印输出时得到的都是ASCII码值。
    • 将小写字母转换为大写字母时,由ASCII码表发现小写字母与大写字母的差值为32,因此将a减去32就可以得到大写字母A。

    7 字符串型常量

    • 字符串型常量是由一对双引号括起来的字符序列。
    • 例如,“How do you do.”、“CHINA”、“a”和“$123.45”。
    • 注意,'a’是字符型常量,而“a”是字符串型常量,二者是不同的。
    • 在字符串型常量的结尾加一个字符串结束标志’\0’,以便判断字符串是否结束。

    例如,字符串型常量“CHINA”在内存中占用的内存单元不是5个字符,而是6字符,即大小为6个字节,最后一个字符为’\0’。
     
    在内存中的存储结果:
    图

    8 ASCII码表

    1234在这里插入图片描述


    2. 混合运算 - printf讲解

    1 混合运算

    类型强制转换场景

    • 整型数进行除法运算时,如果运算结果为小数,那么存储浮点数时一定要进行强制类型转换:
    #include 
    //强制类型转换
    int main()
    {
    	int i = 5;
    	float f = i / 2;//2.0 - 左右操作数都是整型,这里做整型运算,商为2余数1
    	//类型强制转换
    	float k = (float)i / 2;//2.5 - 表达式的类型为浮点型
    	printf("%f\n", f);//2.0
    	printf("%f\n", k);//2.5
    
    	return 0;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    j得到的值为2,k得到的值是2.5,因为当我们整数做除法时,默认进行整除,要得到小数,需要首先进行强制类型转换操作。

    2 printf函数介绍

    • printf函数可以输出各种类型的数据,是printf函数将这些类型的数据格式化为字符串后,放入标准输出缓冲区,然后将结果显示到屏幕上。
    #include 
    int printf(const char *format, ...);
    
    • 1
    • 2
    • 字符串格式(format)由两部分组成:显示到屏幕上的字符和定义printf函数显示的其他参数。
    int age = 21;
    printf("Hello %s, you are %d years old\n","Bob",age);
    
    • 1
    • 2

    输出:Hello Bob, you are 21 years old

    printf函数的具体代码格式:

    代码格式
    %c字符
    %d带符号整数
    %f浮点数
    %s一串字符
    %u无符号整数
    %x无符号十六进制数,用小写字母
    %X无符号十六进制数,用大写字母
    %p一个指针
    %%一个’%'符号

    位于%和格式化命令之间的一个整数被称为最小字段宽度说明符,通常会加上空格来控制格式。

    • 用%f精度修饰符指定想要的小数位数。例如,%5.2f会至少显示5位数字并带有2位小数的浮点数。
    • 用%s精度修饰符简单地表示一个最大的长度,以补充句点前的最小字段长度。
    • printf函数的所有输出都是右对齐的,除非在%符号后放置了负号。例如,%-5.2f 会显示5位字符、2位小数位的浮点数并且左对齐
    #include 
    //练习printf
    //int main()
    //{
    //	int age = 21;
    //	printf("Hello %s, you are %d years old\n", "Bob", age);
    //	return 0;
    //}
    
    int main()
    {
    	int i = 10;
    	float f = 96.3;
    	printf("student number =%d score=%f\n", i, f);
    
    	printf("student number =%3d score=%5.2f\n",i,f);//%3d 占三个位置 - 对齐 //%5.2f 5 - 整体占五个位置 2 - 小数点后保留两位
    
    	printf("student number =%-3d score=%-5.2f\n",i,f);//默认是右对齐,加一个负号 - %-3d - 左对齐
    	i = 100;//第一次是定义,再次使用不需要定义
    	f = 98.21;
    	printf("student number =%d score=%f\n", i, f);//上下不对齐
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    运行结果:
    结果


    3. 整型进制转换

    1 整型常量的不同进制表示

    • 计算机中只能存储二进制数,即0和1,而在对应的物理硬件上则是高、低电平。
    • 除我们正常使用的十进制数外,计算机还提供了十六进制数和八进制数。
    进制基数
    二进制0和1
    十进制(%d)0-9
    八进制(%o)0-7
    十六进制(%x)0-9和a-f
    • 1字节(byte)为8位(bit),1位即二进制的1位,它存储0或1。

    int型常量的大小为4字节,即32位。

    • 二进制数0100 1100 0011 0001 0101 0110 1111 1110
      最高位0是符号位。
      对应的是2的幂次
    • 十六进制在观察内存时需要频繁使用。
    • 例i的值是7b(十六进制),其十进制值为7×16+11=123,i的值是0x0000007b。
       
      地址显示结果为7b 00 00 00,
      原因是CPU采用了小端方式进行数据存储,因此低位在前、高位在后。
    #include 
    
    int main()
    {
    	int i = 123;
    	//二进制 0000 0000 0000 0000 0000 0000 0111 1011
    	printf("%d\n", i);//123
    	printf("%o\n", i);//173
    	printf("%x\n", i);//7b
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    十进制数转换为二进制的方法:

    1
    小技巧

    • 可在Windows操作系统下选择“开始”→“计算器”,打开“计算器”。
    • 选择菜单项“查看”→“程序员”可以得到对应进制的转换结果。

    1


    4. scanf读取标准输入

    1 常用的数据输入/输出函数

    • C语言可通过函数库读取标准输入。
      1

    1 scanf函数的原理

    • C语言通过scanf函数读取键盘输入,键盘输入又称为标准输入。
    • 当scanf函数读取标准输入时,如果没有输入任何内容,那么scanf函数会被阻塞。
    #include
    
    //scanf用来读取标准输入,scanf把标准输入内的内容,需要放到某个变量空间里,因此变量必须取地址
    //scanf会阻塞,是因为标准输入缓冲区是空的
    
    //scanf %d %f 发现里边有\n空格,忽略
    //scanf %c 不忽略内容
    int main()
    {
    	int i = 10;
    	char c;
    	float f;
    	scanf("%d", &i);//注意一定要取地址
    	printf("i = %d\n", i);//把标准缓冲区中的整型数读走了
    
    	//rewind(stdin);//清空标准输入缓冲区
    
    	//scanf("%c", &c);//读取走了转义字符\n!!!
    	//printf("c = %c\n", c);//没有等待输入c - 输出了换行!!!
    
    	scanf("%f", &f);//忽略转义字符\n
    	printf("f = %f\n", f);
    
    	//fflush(stdin);//清空标准输入缓冲区
    	return 0;
    }//直接运行程序卡住 - 阻塞
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    为什么第二个scanf函数不会被阻塞呢?

    • 其实是因为第二个scanf 函数读取了缓冲区中的’\n’,即 scanf(“%c”,&c)实现了读取,打印其实输出了换行,所以不会阻塞。

    但是如果将注释的 fflush(stdin)打开,就会发现第二个scanf(“%c”,&c)会阻塞,这是什么原因呢?

    • 行缓冲:在这种情况下,当在输入和输出中遇到换行符时,将执行真正的IO处理操作。
       
      scanf 函数在读取整型数、浮点数、字符串时,会忽略’\n’(回车符)、空格符等字符。
       
      忽略指scanf函数执行时会首先删除这些字符,然后再阻塞。
       
      在执行scanf(“%c”,&c)语句时,不会忽略任何字符,所以其读取了还在缓冲区中残留的’\n’。

    2 多种数据类型混合输入

    • 为了避免字符型数据读取时,并不会忽略空格和’\n’(回车符)。
    • 如下,编写时,在%d与%c之间加入一个空格。
    #include
    
    int main()
    {
    	int i,ret;//ret是scanf匹配成功的个数
    	char c;
    	float f;
    
    	//输入100 a 98.2
    	//ret = scanf("%d%c%f", &i, &c, &f);//"%d%c%f"之间不加空格 i=100,c= ,f=0.00
    	//ret = 2 只匹配成功了两个,因为&c不会忽略任何字符 - %d读走100后,%c读走空格,%f读a时报错返回,所以只匹配成功两个。
    
    	ret = scanf("%d %c%f", &i, &c, &f);//要在%c之前加个空格
    	printf("i=%d,c=%c,f=%f\n", i, c, f);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    格式字符串中的空白字符的含义(来自http://www.cplusplus.com/reference/cstdio/scanf/?kw=scanf):
     
    空白字符:该函数将读取并忽略在下一个非空白字符之前遇到的任何空格字符(空格字符包括空格,换行符和制表符 -
    请参阅isspace).格式字符串中的单个空格验证从流中提取的任何数量的空白字符(包括无).
     
    当您的代码是:

    scanf("%d%c", &x, &ch)
    
    • 1

    然后你进入

    10 
    
    • 1

    在你的控制台:

    1. 10被读取并存储在x.
    2. 读取并存储换行符ch.

     
    如果你使用

    scanf("%d %c", &x, &ch) 
    
    • 1

    然后你进入

    10
    
    • 1
    1. 10被读取并存储在x.
    2. 消费换行符和其他空白字符.程序等待非空白字符.输入一行输入并且该行中至少存在一个非空白字符后,将读入该行的第一个非白色字符ch.这是因为stdin通常是行缓冲的.

    总结

    1.2

    • 常量指在程序运行过程中,值不发生变化的量。
    • 可分为整型、实型(也称浮点型)、字符型和字符串型。

    1.3

    • 变量指内存中具有特定属性的一个存储单元,它用来存放数据,即变量的值。
    • 这些值在程序的执行过程中是可以改变的。
    • 每个变量名分配对应的内存地址(空间)。
    • 变量命名规定如下:只能由字母、数字和下划线三种字符组成,并且第一个字符必须为字母或下划线。

    1.4

    • 通过int i来定义整型变量,i占用4个字节空间

    1.5

    • 表示浮点型常量的方式有两种,如下所示,其中e代表10的幂次,幂次可正可负。
    • 注意,字母e(或E)之前必须有数字,且e后面的指数必须为整数。
    • 通过float f来定义浮点变量,f占用4个字节空间

    1.6

    • 用单引号括起来的一个字符是字符型常量,且只能包含一个字符! 例如, ‘a’、‘A’、‘1’。

    • 转义字符:以“\”开头的特殊字符,转义字符可用来表示回车、退格等功能键。

    • 字符型变量使用关键字char进行定义,一个字符型变量占用1字节大小的空间。

    • 一个字符常量把该字符的ASCII码值放到存储单元中。

    • 字符型数据和整型数据之间可以通用。

    • 字符型数据既可以以字符形式输出,又可以以整数形式输出,还可以通过运算获取想要的各种字符:

    • 字符型变量,用%c打印输出时得到字符,用%d打印输出时得到ASCII码值。

    • 将小写字母转换为大写字母时,由ASCII码表发现小写字母与大写字母的差值为32,因此将a减去32就可以得到大写字母A。

    1.7

    • 字符串型常量是由一对双引号括起来的字符序列。
    • 注意,'a’是字符型常量,而“a”是字符串型常量,二者是不同的。
    • 在字符串型常量的结尾加一个字符串结束标志’\0’,以便判断字符串是否结束。

    1.8

    1234在这里插入图片描述

    2.1

    • 整型数进行除法运算时,如果运算结果为小数,那么存储浮点数时一定要进行强制类型转换。

    2.2

    位于%和格式化命令之间的一个整数被称为最小字段宽度说明符,通常会加上空格来控制格式。

    • 用%f精度修饰符指定想要的小数位数。例如,%5.2f会至少显示5位数字并带有2位小数的浮点数。
    • 用%s精度修饰符简单地表示一个最大的长度,以补充句点前的最小字段长度。
    • printf函数的所有输出都是右对齐的,除非在%符号后放置了负号。例如,%-5.2f 会显示5位字符、2位小数位的浮点数并且左对齐

    3.1

    • 计算机中只能存储二进制数,即0和1,而在对应的物理硬件上则是高、低电平。
    • 除我们正常使用的十进制数外,计算机还提供了十六进制数和八进制数。
    进制基数
    二进制0和1
    十进制(%d)0-9
    八进制(%o)0-7
    十六进制(%x)0-9和a-f
    • 1字节(byte)为8位(bit),1位即二进制的1位,它存储0或1。

    int型常量的大小为4字节,即32位。

    • 二进制数0100 1100 0011 0001 0101 0110 1111 1110
      最高位0是符号位。
      对应的是2的幂次
    • 十六进制在观察内存时需要频繁使用。
    • 例i的值是7b(十六进制),其十进制值为7×16+11=123,i的值是0x0000007b。
       
      地址显示结果为7b 00 00 00,
      原因是CPU采用了小端方式进行数据存储,因此低位在前、高位在后。

    十进制数转换为二进制的方法:
    1
    小技巧

    • 可在Windows操作系统下选择“开始”→“计算器”,打开“计算器”。
    • 选择菜单项“查看”→“程序员”可以得到对应进制的转换结果。

    3.2

    • 数组名作为实参传递给子函数是,是弱化为指针的。

    4.1

    • C语言通过scanf函数读取键盘输入,键盘输入又称为标准输入。
    • 当scanf函数读取标准输入时,如果没有输入任何内容,那么scanf函数会被阻塞。

    4.2

    • 为了避免字符型数据读取时,并不会忽略空格和’\n’(回车符)。
    • 如下,编写时,在%d与%c之间加入一个空格。
  • 相关阅读:
    leetcode&lintcode分类刷题:图论(一、连通域/岛屿问题)
    微服务系列:分布式文件存储之 MinIO 入门指南
    SpringBoot 整合 Minio 实现 文件上传
    『忘了再学』Shell基础 — 23、其他环境变量配置文件
    诡异的定时任务
    Java泛型中K、T、V、E、?等的含义
    C++学习笔记(十二)
    幸福里 C 端 iOS 编译优化实践-优化 40% 耗时
    『C语言』题集 of ⑩
    开发框架DevExpress XAF - Entity Framework Core 8支持.NET 8性能基准
  • 原文地址:https://blog.csdn.net/m0_58991879/article/details/127907694