【考研C语言】【王道】哭哭羊进阶史(数据的类型、数据的输入输出)2024.7.28

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

1 数据类型

 2 常量

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

3 变量 

变量代表内存中具有特定属性的一个存储单元,它用来存放数据,即变量的值。这些值在程序的执行过程中是可以改变的。

变量名实际上以一个名字代表一个对应的存储单元地址,编译、链接程序时,由编译系统为每个变量名分配对应的内存地址(就是空间)。从变量中取值实际上是通过变量名找到内存中存储单元的地址,并从该存储单元中读取数据,如下图所示。


变量的命名规定如下:C语言规定标识符只能由字母、数字和下画线三种字符组成,并且第一个字符必须为字母或下画线。 

注意:

(1)编译系统认为大写字母和小写字母是不同的字符,因此C语言要求对所有用到的变量做强制定义,即“先定义,后使用”

(2)在选择变量名和其他标识符时,应尽量做到“见名知意”,即选择具有含义的英文单词(或其缩写)作为标识符。

(3)变量名不能与关键字同名!

 4 整型数据

4.1  符号常量

符号常量直接替换

 4.2  符号变量

注意:int i,变量i是4个字节。

5 浮点型数据

5.1  浮点型常量

5.2  浮点型变量

注意:float f,变量f是4个字节。 

6 字符型数据

 6.1  字符型常量

单引号括起来的一个字符是字符型常量,且只能包含一个字符!

例如,'a'、'A'、'1'、' '是正确的字符型常量,而'abc’、"a"、" "是错误的字符型常量。下表中给出了各种转义字符及其作用。以"\"开头的特殊字符称为转义字符,转义字符用来表示回车、退格等功能键。

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

字符型变量使用关键字 char进行定义一个字符型变量占用1字节大小的空间一个字符常量存放到一个字符型变量中时,实际上并不是把该字符的字型放到内存中,而是把该字符的ASCII码值放到存储单元中

ASCII码表

打印(printf)字符型变量时,如果以字符形式("%c")打印,那么计算机会到 ASCII码表中查找字符型变量的ASCII码值,查到对应的字符后会显示对应的字符,如下图所示。

这样,字符型数据和整型数据之间就可以通用。字符型数据既可以以字符形式输出,又可以以整数形式输出,还可以通过运算获取想要的各种字符,请看下面例子。 

对于字符型变量,无论是赋 ASCII码值还是赋字符,使用%c打印输出时得到的都是字符,使用%d打印输出时得到的都是 ASCI码值将小写字母转换为大写字母时,由ASCII码表发现小写字母与大写字母的差值为32,因此将c减去32就可以得到大写字母A。

 7 字符串型常量

字符串型常量是由一对双引号括起来的字符序列。例如,"How do you do."、"CHINA"、"a"和"$123.45"是合法的字符串型常量,我们可用语句 printf("How do you do.")输出一个字符串,但要注意的是,'a'是字符型常量,而"a"是字符串型常量,二者是不同的
例如,如果先用语句char c定义字符型变量c,后令 c="a"或 c="CHINA",那么这样的赋值都是非法的,原因是不可以将字符串型常量赋值给字符型变量C语言中没有定义字符串型变量的关键字,介绍字符数组时我们将详细讲解如何存放字符串。
C语言规定,在每个字符串型常量的结尾加一个字符串结束标志,以便系统据此判断字符串是否结束。C语言规定以字符'/0'作为字符串结束标志
例如,字符串型常量"CHINA"在内存中的存储结果如下图所示,它占用的内存单元不是5个字符,而是6个字符,即大小为6字节,最后一个字符为'/0'。然而,在输出时不输出'/0',因为'/0'无法显示。


01.1.2  混合运算-printf

1  混合运算

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

2  print函数 

printf 函数可以输出各种类型的数据,包括整型、浮点型、字符型、字符串型等,实际原理是 printf函数将这些类型的数据格式化为字符串后,放入标准输出缓冲区,然后将结果显示到屏幕上。

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

  • %f精度修饰符指定想要的小数位数例如,%5.2f至少显示5位数字并带有2位小数的浮点数。
  • %s精度修饰符简单地表示一个最大的长度,以补充句点前的最小字段长度。

printf函数的所有输出默认是右对齐的,在%符号后放一个负号代表左对齐例如,%-5.2f会显示5位字符2位小数位浮点数并且左对齐


01.1.3  整型进制转换

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

计算机中只能存储二进制数,即0和1,而在对应的物理硬件上则是高、低电平,为了更方便地观察内存中的二进制数情况,除我们正常使用的十进制数外,计算机还提供了十六进制数八进制数

下面介绍不同进制数的对应关系。

首先,在计算机中,1字节为8位,1位即二进制的1位,它存储0或1。int型常量的大小为4字节,即32位

设有二进制数0100 1100 0011 0001 0101 0110 1111 1110,其最低位是2的零次方,代表数值的最高位是2的30次方,最高位为符号位,符号位为1时是补码

上面的二进制数对应的八进制数是 011414253376,它以0开头标示,数位的变化范围是0~7二进数转换为八进制数的方式是,对应的二进制数每3位转换为1位八进制数,首先将上面的二进制数按每3位隔开,得到01 001 100 001 100 010 101 011 011 111 110,然后每3位对应0~7范围内的数进行对应转换,得到八进制数011414253376。由于实际编程时,识别八进制数时前面需要加0,所以在前面加了一个0

上面的二进制数对应的十六进制数是0x4C3156FE,它以0x开头标示,数位的变化范围是0~9和A~F,其中A代表10,F代表15对应的二进制数每4位转换为1位十六进制数,十六进
制在观察内存时需要频繁使用。

上面的二进制数对应的十进制数是1278301950,具体计算需要以2的幂次相加依次来计算2^{1}+2^{2}+2^{3}+...+2^{30}来实现(为1的位置就需要2的幂次,为零不需要),最好通过计算器来进
行。

二进制:0和1

十进制:0-9

八进制:0-7

十六进制:0-9 a-f

目前我们执行到语句 int i = 123,变量i会在内存上被分配空间,大小为4字节,会看到如下图所示,其中 i 的值变为7b,其十进制值为 7x16+11=123。i 的值是 0x0000007b。

#include <stdio.h>
//进制转换
int main() {
    int i = 123;
    printf("%d\n",i);  //十进制输出
    printf("%o\n",i);  //八进制输出
    printf("%x\n",i);  //十六进制输出
    return 0;
}

输出结果 

我们以十六进制方式查看内存, 为什么显示结果为7b 00 00 00?

原因是英特尔的CPU采用了小端方式进行数据存储,因此低位在前、高位在后。

十进制数转换为二进制数

Eg:十进制数 123 转换为二进制数

方法:让123不断地除以2,并把余数写在右边,把商写在下方,直到商为0,然后逆序写出所有余数,即可得到转换后的二进制数1111011。详细过程如下图所示。

对应的十六进制数为76,十进制数转换为十六进制数的方式是除以16,十进制数转换为八进制数的方式是除以8。 

小技巧

手动转换一个数的进制后,若不知道转换后的进制数是否正确,则可在视窗操作系统下选择"开始"一>"计算器"(或win+r打开运行,输入calc),打开"计算器",然后选择菜单项"查看"一>"程序员",得到如下图所示的计算器。输入一个十进制数后,单击"十六进制""八进制"或"二进制",即可得到对应进制的转换结果。


 01.1.4  scanf读取标准输入

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

如下图所示,程序员可以给程序输人数据,程序处理后会返回一个输出,C语言通过函数库读取标准输入,然后通过对应函数处理将结果打印到屏幕上,前面我们学习了printf函数,理解了通过 printf函数可以将结果输出到屏幕上。下面详细讲解标准输人函数 scanf

1 scanf函数的原理

C语言未提供输入/输出关键字,其输入和输出是通过标准函数库来实现的。C语言通过scanf 函数读取键盘输入,键盘输入又被称为标准输入当scanf 函数读取标准输入时,如果还没有输入任何内容,那么scanf函数会被卡住(专业用语为阻塞),下面来看一个例子。

【例】scanf读取标准输入

#include <stdio.h>

//scanf时,%d %f发现里面有空格或\n --忽略
//scanf时,%c --不忽略

int main() {
    int i  = 10;
    char c;
    scanf("%d",&i);  //注意一定要取地址
                     //scanf用来读取标准输入,scanf把标准输入内的内容,需要放到某个变量空间里
                     //因此变量必须取地址
    printf("%d\n",i);
//    fflush(stdin);  //清空标准输入缓冲区
    scanf("%c",&c);
    printf("c=%c\n",c);
    return 0;
}

执行时输入 20,然后回车,显示结果如下图所示。为什么第二个scanf函数不会被阻塞呢?其实是因为第二个scanf函数读取了缓冲区中的'\n',即 scanf("%c",&c)实现了读取,打印其实输出换行,所以不会阻塞。

程序执行结果

但是如果我们将上面例子中注释的标准输入缓冲区fflush(stdin)打开,就会发现第二个scanf("%c",&c)会阻塞,这是什么原因呢?下面介绍缓冲区原理

行缓冲:在这种情况下,当在输入和输出中遇到换行符时,将执行真正的I/O处理操作。这时,我们输入的字符先存放到缓冲区中,等按下回车键换行时才进行实际的IO操作,典型代表是标准输入缓冲区(stdin)标准输出缓冲区(stdout)printf使用的是stdout

在使用scanf进行输入时,输入的其实为一串字符串,而字符串里为'键盘输入内容\n'

如上面的例子所示,我们向标准输入缓冲区中放入的字符为'20\n',输入'\n'(回车)后,scanf函数才开始匹配,scanf 函数中的%d 匹配整型数 20,然后放入变量i中,接着进行打印输出,这时'\n'仍然在标准输入缓冲区(stdin)内,如果第二个scanf函数为scanf("%d",&i),那么依然会发生阻塞,因为scanf函数在读取整型数浮点数字符串时,会忽略'\n'(回车符)、空格符等字符(忽略是指scanf函数执行时会首先删除这些字符,然后再阻塞)。scanf函数匹配一个字符时,会在缓冲区删除对应的字符,因为在执行scanf("%c",&c)语句时,不会忽略任何字符,所以scanf("%c",&c)读取了还在缓冲区中残留的'\n'。

2 多种函数类型混合输入

当我们让scanf函数一次读取多种类型的数据时,对于字符型数据要格外小心,因为当一行数据中存在字符型数据读取时,读取的字符并不会忽略空格和'\n'(回车符),所以使用方法如下例所示。编写代码时,我们需要在%d与%c之间加入一个空格。输入格式和输出效果如下图所示,scanf 函数匹配成功了4个成员,所以返回值为4,我们可以通过返回值来判断scanf函数匹配成功了几个成员,中间任何有一个成员匹配出错,后面的成员都会匹配出错。

【例】一次读取多种类型的数据

#include<stdio.h>
int main(){
    int i,ret;  //ret为scanf返回值,通过返回值来判断scanf函数匹配成功了几个成员
    char c;
    float f;
    ret = scanf("%d %c%f",&i,&c,&f);  //要在%c前加一个空格
    printf("i=%d,c=%c,f=%5.2f\n",i,c,f);
    return 0;
}

输出结果 


 练习题

1.printf的输出默认是左对齐
A.正确     B.错误
答案:B
解释:printf的输出默认是右对齐,不是左对齐。如果需要左对齐,那么加人负号。

2.整型数124对应的十六进制值是0x7c
A.正确     B.错误
答案:B
解释:把一个10进制数转为16进制,只要不断除16即可,124除16,商是7,余数是12,而12就是c,因此是 0x7c。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值