数据的类型和数据的输入输出

数据的类型、数据的输入输出

数据类型 1、基本类型 整型 int
510,1414,500
浮点型 float
8.2,11.23,44.673
字符型 char
'a','b','c'

"caijxlinux","mmssb","nihaoma"
2、构造类型 数组 [] 结构体 struct 3、指针类型 * 4、空类型 void
变量(整型、浮点型、字符型)
变量代表内存中具有特定属性的一个存储单元,它用来存放数据,即变量的值。这些值在程序的执行过程中是可以改变的。 变量名实际上以一个名字代表一个对应的存储单元地址。编译、链接程序时,由编译系统为每个变量名分配对应的内存地址(就是空间)。从变量中取值实际上是通过变量名找到内存中存储单元的地址,并从该存储单元中读取数据。 变量的命名规定如下:C语言规定标识符只能由字母、数字和下划线三种字符组成,并且第一个字符必须为字母或下划线。 编译系统认为大写字母和小写字母是不同的字符,因此C语言要求对所有用到的变量做强制定义,即“先定义,后使用”。同时在选择变量名和其他标识符时,应尽量做到“见名知意”,即选择具有含义的英文单词(或其缩写)作为标识符。注意,变量名不能与关键字同名!

整型数据

符号常量
#include <stdio.h>
#define PI 3+2
int main(){
    int i=PI*2;
    printf("i=%d\n",i);
} 
此时输出结果为7,因为符号常量会直接替换,而不是赋值之后再替换
整型变量
#include <stdio.h>
#define PI 3+2
int main(){
    int i=PI*2;
    printf("i=%d\n",i);
    printf("int size=%d\n",sizeof(i)); //sizeof()输出某个变量的大小
} 
输出结果提示:整型变量的大小为4个字节

浮点型数据

浮点型常量
两种表现形式 ​ 小数形式:0.123 ​ 指数形式:3e-3(代表3*10的负三次方,即0.003) ​ 注意:字母e之前必须有数字,且e后面的指数必须为整数
浮点型变量
#include <stdio.h>

int main(){
    float f=4e-4;
    printf("f=%f\n",f);
    printf("float size=%zd\n",sizeof(f));
    return 0; 
} 
输出结果为f=0.000400,float size=4 思考:为什么将%zd修改为%f时,float size输出为0?

字符型数据

字符型常量
字符数据在内存中的存储形式及其使用方法
​ 一个字符型变量占用1字节大小的空间
int main(){
    char c='A';
    printf("%c\n",c+32);
    printf("%d\n",c);
    printf("chart size=%zd\n",sizeof(c));
    return 0; 
} 
输出结果为a、65、chart size=1 对于字符型变量,无论是赋ASCⅡ码值还是赋字符,使用%c打印输出时得到的都是字符,使用%d打印输出时得到的都是ASCⅡ码值。将小写字母转换为大写字母时,由ASCⅡ码表发现小写字母与大写字母的差值为32,因此将c减去32就可以得到大写字母A。

字符串常量

'a'是字符型常量,"a"是字符串常量。二者是不同的。 C语言规定,在每个字符串型常量的结尾加一个字符串结束标志,以便系统据此判断字符串是否结束。C语言规定以字符'\0'作为字符串结束标志。

混合运算

强制类型转换
#include <stdio.h>

int main(){
    int i=5;
    float j=i/2; //此处由于左右操作数都为整型,所以做整型运算,输出结果为2.0000000
    float k=(float)i/2;//此处将左操作数强制转换为float类型,做浮点型运算,输出结果为2.5000000
    printf("%f\n",j);
    printf("%f\n",k);
    return 0; 
} 
printf函数
printf函数可以输出各种类型的数据,包括整型、浮点型、字符型、字符串型等,实际原理是printf函数将这些类型的数据格式化为字符串后,放入标准输出缓冲区,然后将结果显示到屏幕上。 ​ printf函数的具体代码格式
代码 格式
%c 字符
%d 带符号整数
%f 浮点数
%s 字符串
%o 八进制
%u 无符号整数
%x 无符号十六进制数,用小写字母
%X 无符号十六进制数,用大写字母
%p 一个指针
%% 一个'%'符号
格式控制
#include <stdio.h>

int main(){
    int i=10;
    float f=96.6;
    printf("i=%d,f=%f\n",i,f); //没有进行格式控制,输出结果为i=10,f=96.599998
    i=17;
    f=98.99;
    printf("i=%3d,f=%5.2f\n",i,f); //进行格式控制,输出结果为i=100,f=98.99
    printf("i=%-3d,f=%5.2f\n",i,f); //进行格式控制(左对齐) 
    return 0; 
} 
%5.2f显示5位字符、2位小数位的浮点数并且左对齐
整型常量的不同进制表示
计算机中只能存储二进制数,即0和1,而在对应的物理硬件上则是高、低电平。为了更方便地观察内存中的二进制数情况,除我们正常使用的十进制数外,计算机还提供了十六进制数和八进制数。
#include <stdio.h>

int main(){
    int i=123;
    printf("%o\n",i); //八进制 
    printf("%d\n",i); //十进制 
    printf("%x\n",i); //十六进制 
    return 0; 
}  
首先,在计算机中,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的幂次相加依次来计算是为1的位置就需要2的幂次,为零不需要,第一位是2的0次方
scanf函数原理
C语言未提供输入输出关键字,其输入和输出是通过标准函数库来实现的,C语言通过scanf函数读取键盘输人,键盘输入又被称为标准输入,当scanf函数读取标准输入时,如果还没有输入任何内容,那么scanf函数会被卡住(专业用语为阻塞)
#include <stdio.h>

int main(){
    int i;
    char c;
    float b;
    scanf("%d",&i); //第一个scanf
    printf("i=%d\n",i);
    //fflush(stdin); //清空标准输入缓冲区 
    scanf("%c",&c); //第二个scanf
    printf("c=%c\n",c);
//  scanf("%f",&b); //第三个scanf
//  printf("b=%f\n",b);
    return 0; 
}  
读者在使用此代码时,会发现在初始注释不变的情况下,第二个scanf甚至不会弹出提示,直接就输出了内容,只有fflush(stdin)代码能正常运行时,第二个scanf才能正确取数,而注释掉第二个scanf和对应的prinft语句,打开第三个scanf语句和对应的printf语句时,在不执行fflush代码的情况下,第三个scanf也能正确取数,这是为什么呢? 原因: 行缓冲:在这种情况下,当在输入和输出中遇到换行符时,将执行真正的/O处理操作.这时,我们输入的字符先存放到缓冲区中,等按下回车键换行时才进行实际的I/O操作。典型代表是标准输入缓冲区(stdin)和标准输出缓冲区(stdout),printf使用的是stdout. 如上面代码所示,我们向标准输入缓冲区中放入的字符为'20\n',输入'\n'(回车)后,scanf函数才开始匹配,scaf函数中的'%d'匹配整型数20,然后放入变量i中,接着进行打印输出,这时'\n'仍然在标准输入缓冲区(stdin)内,如果第二个scanf函数为scanf("%d",&i),那么依然会发生阻塞,因为scanf函数在读取整型数、浮点数、字符串时,会忽略'\n'(回车符)、空格符等字符(忽略是指scanf函数执行时会首先删除这些字符,然后再阻塞)。scanf函数匹配一个字符时,会在缓冲区删除对应的字符。因为在执行scanf("%c",&c)语句时,不会忽略任何字符,所以 scanf"%c",&c)读取了还在缓冲区中残留的'\n',最终就导致了第二个scanf函数没出现阻塞就输出了。
多种数据类型混合输入
#include <stdio.h>

int main(){
    int i,ret;
    char c;
    float b;
    ret=scanf("%d %c%f",&i,&c,&b); //ret判断scanf正确取值的位数 
    printf("i=%d,c=%c,f=%3.1f",i,c,b); //保留浮点型三位,小数点后一位 
    return 0; 
}  
读者可以发现scanf函数%d和%c之间有空格,如果删除此空格,或者在%c和%f之间增加一个空格,输出的结果是否会不同? 答:确实输出结果不一样,如果删除了空格,那么输出会出现问题,第二个%c取得的字符为空格,读者可以自行尝试。因为当scanf函数一次读取多种类型的数据时,当一行数据中存在字符型数据读取时,读取的字符并不会忽略空格和'\n'(回车符),所以在上面编写代码时,需要在%d与%c之间加入一个空格。又或者是将字符型的%c放在最前面。