目录
一.数据类型介绍
在这部分先不讲自定义函数,先讲一下内置函数。
(1) C语言提供了丰富的字符数据类型来描述生活中的各种数据。
数据类型分为两大类 : 内置函数 、 自定义函数 。
内置函数 是C语言本身就有的,自定义函数 是自己创造的。
内置函数又分为: 字符型 、 整型 、 浮点型 、 布尔类型
自定义函数又分为: 数组 、 结构体-struct 、 枚举-enum 、 联合体-union
① 字符类型 : char (character) ( [ ] 里的内容可以省略不写 )
[signed] char (有符号的)
unsigned char (无符号的)
② 整型 : short-短整型 、 int-整型 、 long-长整型 、 long long-更长整型(C99引入)
·短整型
short [int] 、 [signed] short [int] 、 unsigned short [int]
·长整型
long [int] 、 [signed] long [int] 、 unsigned long [int]
·更长整型
long long [int] 、 [signed] long long [int] 、 unsigned long long [int]
③浮点型: float-单精度浮点型、double-双精度浮点型、long double-精度更高的浮点型
④布尔类型:_Bool(早期) 或 bool(重匿名) , 取值要么true (1),要么false (0) (表示真假的变量,有一种变量,取值要么 真,要么 假) 。 布尔类型的使用得包含头文件 <stdbool.h>。
(2各种数据类型的长度 ( sizeof )
这么多数据类型有什么区别?区别在于这些数据类型的长度。每一种数据类型都有自己的长度,使用不同的数据类型,能够创造出长度不同的变量,变量长度的不同,存储的数据范围就有所差异。
所以在这里讲一下 计算机的单位
计算机的最小存储单位:bit , 一个bit存放一个二进制数 0、1。
但是计算机存储容量基本单位是 byte (字节)。
1B(Byte 字节)=8bit,
1KB (Kilobyte 千字节)=1024B,
1MB (Megabyte 兆字节 简称“兆”)=1024KB,
1GB (Gigabyte 吉字节 又称“千兆”)=1024MB,
1TB (Trillionbyte 万亿字节 太字节)=1024GB,
1PB(Petabyte 千万亿字节 拍字节)=1024TB,
1EB(Exabyte 百亿亿字节 艾字节)=1024PB,
1ZB (Zettabyte 十万亿亿字节 泽字节)= 1024 EB,
1YB (Yottabyte 一亿亿亿字节 尧字节)= 1024 ZB,
1BB (Brontobyte 一千亿亿亿字节)= 1024 YB. (其中1024=2^10)
sizeof 是一个关键字,也是操作符。专门用来计算sizeof的操作符数的类型的长度的,单位是 字节,其操作可以是 类型,也可以是 变量 或 表达式。
下面演示一下sizeof的使用
#include<stdio.h>
int main()
{
printf("%zd \n",sizeof(int));
return 0;
}
这时候屏幕会输出 4 ,也就是 int 占4个字节。
注意:
①sizeof得计算结果是 size_t 类型 (sizeof的返回值就是size_t) size_t这个值的打印用 %zd 来打印,%zd对应的就是size_t类型的值
②sizeof的操作数如果不是类型,是 表达式 或者 变量 的时候,可以省略后面的括号
#include<stdio.h>
int main()
{
int a = 10;
printf("%zd \n",sizeof(a));
printf("%zd \n",sizeof a);
return 0;
}
③sizeof后面的表达式是不真实参与运算的,根据表达式的类型来得出大小
#include<stdio.h>
int main()
{
int a = 1;
short b = 2;
printf("%zd \n",sizeof( b = a+1 ));
return 0;
}
(1是整型,a也是整型,但是b是短整型,所以只用知道s的类型就行)
二.signed和unsigned
C语言中使用 sign 和 unsigned 关键字来修饰 字符型 和 整数 类型的。
signed 关键字,表示一个类型带有正负号,包含负值。(比如温度)
unsigned 关键字,表示该类型不带有正负号,只能表示 0 和 正整数。(年龄)
整数变量 声明为unsigned的好处是,同样长度的内存能够表示的最大整数值,增大了一倍。
( 16位的signed short int的取值范围是:-32768-32768;而unsigned short int的取值范围是:0-65535,最大值增到了65535 ) (32位signed int的取值范围可以参看limits.h中给出的定义 。)
对于 int类型,默认是带有正负号的,也就是说 int = signed int ; 对于char类型,char到底有符号还是无符号?这个取决于编译的实现 (大部分编译器的 char = signed char)。
注意:对于有符号的整数打印应该使用 %d ,对于无符号的整数的打印应该使用 %u。
三、数据类型的取值范围
查看当前系统上不同数据类型的极限值:
limits.h 文件中说明了整型类型的取值范围。
float.h 这个文件中说明浮点型类型的取值范围。
为了代码的可移植性,需要知道某些整数类型的极限值时,应该尽量使用这些常量。
·SCHAR_MIN , SCHAR_MAX : signed char 最小值和最大值
·SHRT_MIN , SHRT_MAX : short 的最小值和最大值
·INT_MIN , INT_MAX : int 的最小值和最大值
·LONG_MIN , LONG_MAX : long 的最小值和最大值
·LLONG_MIN , LLONG_MAX : long long 的最小值和最大值
·UCHAR_MAX : unsigned char 的最大值
·USHRT_MAX : unsigned short 的最大值
·UINT_MAX : unsigned short 的最大值
·ULONG_MAX : unsigned long 的最大值
·ULLONG_MAX : unsigned long long 的最大值
四、变量
C语言中把经常变化的值称为 变量,不变的值称为 常量。
变量创建的语法形式:
data_type name:
·data_type是数据类型
·name是变量名
(1)变量的创建
变量在创建的时候给一个初始值,就叫 初始化。 (局部变量 没给初始化值得时候,里面放的随机值,是不能直接使用的)
#include<stdio.h>
{
int a = 1888;
printf("%d \n",a);
int b;
float score = 3.14f;
return 0;
}
这里在创建a变量的时候,给了它一个初始值1888,这叫初始化,而b却没有,b不能直接使用。
另外 3.14 后面没有带f的话,3.14就默认是double类型;带上f的话,就是float类型。
(2)变量的分类
变量分为 全局变量 和 局部变量
·全局变量:在大括号(“{}”)外部定义的变量就是 全局变量。 (比如共享单车)
全局变量的使用范围更广, 整个工程 中想使用,都是有办法的。
·局部变量:在大括号(“{}”)内部定义的变量就是 局部变量。 (私家自行车)
局部变量的使用范围就是比较局限,只能在自己所在的局部范围内使用。
注意:当全局变量和局部变量同名的时候,局部变量 优先使用
#include<stdio.h>
int a = 8;
int main()
{
int b = 10;
for (b=0 ;b<10 ;b++)
{
int c = 0;
int c = b+5;
printf("%d \n",c);
}
return 0;
}
在这里,首先a创建在main函数之外,a属于全局变量,b和c创建在{}内,b和c属于局部变量,
但是b的作用域大于c的作用域,b的作用域在main函数内,也就是第一个大括号内,而c的作用域只在for循环内,在for循环中可以使用b,而在for循环外不能使用变量c。
全局变量和局部变量同名的时候。
(3)全局变量和局部变量的存储
在学C/C++语言的时候,我们会关注内存中的三个区域: 栈区、堆区、静态区
·局部变量 放在内存的 栈区
·全局变量 放在内存的 静态区
·堆区 是用来动态内存管理的
五、算术操作符: + - * / %
算术操作符也被称为 双目操作符(有两个操作数的操作符),操作符也叫 运算符,一个意思。
(1) + - (加、减)
(2) * (乘)
(3) / (除)
除号的两端如果是整数,执行的整数除法,得到的结果也是整数。
如果希望得到浮点数的结果,两个运算数必须有一个是浮点数,这时的C语言就会进行浮点数除法。
(4)% (取余)
运算符%表示求模(余)运算,即返回两个整数相除的 余值 ,这个运算符只能用于 整数,不能用于 浮点数。
负数求模的规则是,结果的正负号由第一个运算符的正负号决定。
#include<stdio.h>
int main()
{
int a = 5;
int b = 2;
int c = 2.0;
//(1)
printf("%d\n",a+b);
//(2)
printf("%d\n",a*b);
//(3)
printf("%d\n",a/b);
printf("%f\n",a/c);
printf("%d\n",10.0 / 4);
printf("%f\n", 10 / 4.0);
printf("%f\n", 10.0 / 4.0);
//(4)
printf("%f\n",a%c);
printf("%d\n",11%-5);
printf("%d\n",-11%-5);
printf("%d\n",-11%5);
return 0;
}
各位伙伴可以去自己的IDE上面去执行这段代码,看看输出什么结果。
六、赋值操作符: = 和 复合赋值
赋值操作符 = 是一个随时可以给变量赋值的操作符。
(1)连续赋值
赋值操作符也可以连续赋值。(从右向左进行一次赋值的) 。
C语言虽然支持这种连续赋值,但写出代码不容易理解,建议拆开来写,这样方便观察代码的执行细节。
#include<stdio.h>
int main()
{
int a = 1;
int b = 2;
int c = 3;
a = b = c+4;
printf("%d\n",a);
printf("%d\n",b);
return 0;
}
c的值加4就是7,7再赋给b和a,所以a和b输出的值就是7。
(2)复合赋值
+= 、 -= 、 *= 、 /= 、 %= 、 >>=(右移等) 、 <<=(左移等) 、 &=(按位与等) |=(按位或等) 、 ^=(按位异或等)
今天先讲前五个,上代码。
七、单目操作符: ++ -- + -
C语言中还有一些操作符只有一个操作数,被称为单目操作符
(1)++ 、 --
++是一种自增的操作符,又分为 前置++ 和 后置++,--是一种自减的操作符,也分为 前置-- 和 后置--
①前置++ (b = ++a): 先++,后使用 (a的值先加1再赋值给b)
②后置++ (b = a++): 先使用,后++ (先赋值给b,再给a的值加1)
对a来说没有区别,而b就不同
③前置-- : 先--,再使用
④后置-- : 先使用,再--
++a是 先给a的值+1,然后再赋值给b;c++是 先把c的值赋给d,然后c的值再+1。所以说a和c的值都加1,不同的是b和d的值。
(3)+ 、 -
+号对a的值没有影响,而-号的会让负数变成正数。
八、强制类型转换
语法格式:
(类型)
如下:
(int) 的意思是把3.14强制类型转换成整型,也就是只取整数部分,小数部分省略。
我们使用的强制类型转换是万不得已的时候使用,如果不需要强制类型转化就能实现代码,这样自然更好。
九、printf 和 scanf介绍
scanf和printf要介绍的东西有很多。
(1)printf
①基本用法:
printf()的作用是将参数文本输出到屏幕,它名字里面的 f 代表 format(格式化) ,表示可以定制输出文本的格式。
printf()不会在行尾自动添加换行符,运行结束后,光标就停留在输出结果的地方,不会自动换行(不像Python语言的print,默认会换行的),为了让光标移动到下一行的开头,可以在输出文本的结尾,添加一个换行符 \n。
printf()是在标准库的头文件 stdio.h 定义的.使用这个函数之前,必须在源文件头部引入这个文件。
②占位符:
printf()可以在输出文本中指定占位符,所谓“占位符”就是这个位置可以用其他值代入。
占位符的第一个字符一律为百分号 % ,第二个字符表示 占位符的类型 ,%d 表示这里代入的值必须是一个 整数。printf()的第二个参数就是替换占位符的值。输出文本里面可以使用多个占位符。
printf()参数与占位符是一一对应关系,如果有n个占位符,printf()参数就应该有n+1(前面的格式串)个。如果参数个数少于对应的占位符,printf()可能会输出内存中的任意值。
③占位符列举:
%a: 十六进制浮点数, 字母输出为小写
%A: 十六进制浮点数,字母输出为大写
%c: 字符
%d: 十进制整数
%e: 使用 科学计数法 的浮点数,指数部分的e为小写
%E: 使用 科学计数法 的浮点数,指数部分的E为大写
%i: 整数,基本等同于 %d
%f: 小数(包含 float 类型和 double类型) // float %f ; double %lf
%g: 6个有效数字的浮点数。整数部分一旦超过6位, 就会自动转为科学计数法, 指数部分的e为小写。
%G: 等同于 %g, 唯一的区别是指数部分的E为大写
%hd: 十进制 short int型
%ho: 八进制 short int型
%hx: 十六进制 short int类型
%hu: unsigned short int型
%ld: 十进制 long int类型
%lo: 八进制 long int类型
%lx: 十六进制 long int类型
%lu: unsigned long int 类型
%lld: 十进制 long long int类型
%llo: 八进制 long long int类型
%llx: 十六进制 long long int型
%llu: unsigned long long int型
%Le: 科学计数法表示的long double类型浮点
%Lf: long double类型浮点
%n: 已输出的字符串数量。该占位符本身不输出,只将值存储在指定变量之中
%0: 八进制整数
%p: 指针
%s: 字符串
%u: 符(unsigned int)
%x: 十六进制整数
%zd: size_t类型
%%: 输出一个百分号
%f和%lf默认打印小数点后六位
%d %hd
%u %hu
标有颜色的占位符是用的比较多的。
④输出格式:
·限定宽度:printf()允许限定占位符的最小宽度,%5d 表示这个占位符的宽度至少占5位,如果不满5位,对应的值前面会添加空格,默认是右对齐,即输出内容前面会有空格,如果希望改成左对齐,在输出内容后面添加空格,可以在占位符的%的后面插入一个 - 号(%-5d)。
·总是显示正负号:默认情况下,printf()不对整数显示+号,只对负数显示-号,如果想让正数也输出+号,可以在占位符的%后面加一个+。
·限定小数位数:如果希望保留n位,则就 %.nf 或 %.nlf。
(比如: %.2f 保留2位小数; %12.1f 的意思是宽度最小12位,小数1位 (如果前面的12小于值,则值就按正常的来输出))
·输出部分字符串: %s占位。符用来输出字符串,默认是全部输出。如果只想输出开头部分,可以用%.ms指定输出长度。其中m代表一个数字,表示所要输出的长度。
(2)scanf
当我们有了变量,我们需要给变量输入值就可以使用scanf函数,如果需要将变量的值输出在屏幕上的时候可以使用printf函数。scanf函数中占位符后边的参数需要的是地址 (&取地址操作符)。当我们使用的时候,会看到以下情况
为了解决这个问题有个一劳永逸的办法:
在vs上.c/.cpp的文件,新建的时候其实是拷贝了newc++file.cpp的内容,如果在newc++file.cpp的文件中增加 #define _CRT_SECURE_NO_WARNINGS 1,以后新建.c/.cpp文件的时候自动就有这句话了 。
①基本用法:
scanf()函数用于读取用户的键盘输入,程序运行到这个语句时,会停下来,等待用户从键盘输入。用户输入数据,按下回车键后,scanf()就会处理用户的输入,将其存入变量。它的原型定义在头文件stdio.h,scanf()的语法和printf()类似。
·scanf("%d\n",&i);
它的第一个参数是一个格式字符串,里面会放置占位符(与printf()的占位符基本一致),告诉编译器如何解读用户的输入,需要提取的数据是什么类型。这是因为C语言的数据都是有类型的,scanf()必须提前知道用户输入的数据类型,才能处理数据。它的其余参数就是存放用户输入的变量,格式字符串里面有多少个占位符,就有多少个变量。
(上面示例中,scanf()的第一个参数 %d,表示用户输入的应该是一个 整数。%d就是一个占位符, %是占位符的标志,d表示整数。第二个参数&i表示,将用户从键盘输入的数存入变量i。)
注意:变量前面必须加上&运算符(指针变量除外),因为scanf()传递的不是值,而是 地址,即将变量i的地址指向用户输入的值 如果这里的变量是指针变量(比如字符串变量),那就不用加&运算符。
·可以一次输入多个变量:
scanf()处理数值占位符时,会自动过滤空白字符,包括空格、制表符\t、换行符\n等,所以用户输入的数据之间,有一个或多个空格不影响scanf()解读数据。另外,用户使用回车键,将输入分成几行,也不影响解读。
·scanf()处理用户输入的数据的原理
用户的输入先放入缓存,等到按下回车键后,按照占位符对缓存进行解读,解读用户输入时,会从上一次解读遗留的第一个字符开始,直到读完缓存,或者遇到第一个不符合条件的字符为止。
②scanf返回值:
·scanf()的返回值是一个整数,表示成功读取的变量的个数。(读到几个返回几个)
·如果没有读取任何项,或者匹配失败,则返回0
·如果在成功读取任何数据之前,发生了 读取错误 或者 遇到读取文件结尾,则返回常量EOF(-1),EOF-end of file 文件结束标志。(如果不想让让它停下来就按三次 Ctrl+z回车 )
#include<stdio.h>
int main()
{
int a = 0;
int b = 0;
int c = 0;
int ret = scanf("%d %d %d ",&a,&b,&c);
printf("ret = %d\n",ret);
return 0;
}
③占位符:
scanf()常用的占位符与printf()的占位符基本一致
%c: 字符
%d: 整数
%f: float类型浮点数
%lf: double类型浮点数
%Lf: long double类型浮点数
%s: 字符串
%[]: 在方括号中指定一组匹配的字符(比如%[0-9]),遇到不在集合之中的字符,匹配将会停止
(上面的占位符,除了%c以外,都会自动忽略起首的空白字符.%c不会忽略空白字符,总是返回当前第一个字符,无论该字符是否为空格。如果要强制跳过字符前的空格,可以写成scanf(" %c",&ch),即%c前加上一个空格,表示跳过0个或多个空白字符)
#include<stdio.h>
int main()
{
char ch = 0;
printf("输入ch:");
scanf(" %c",&ch);
printf("xxxx%cyyyy\n",ch);
return 0;
}
注意:%s,它其实不能简单地等同于字符串,它的规则是,从当前第一个非空字符串开始读起,直到遇到空白字符(即空格、换行符、制表符等)为止。scanf()遇到%s占位符,会在字符串变量末尾存储一个空字符串\0。
scanf()将字符串读入字符数组时,不会检测字符串是否超过了数组长度。所以,储存字符串时,很可能会超过数组的边界,导致预想不到的结果。为了防止这种情况,使用 % 占位符时,应该指定读入字符串的最长长度,即写成 %ms,其中的 m 是一个整数,表示读取字符串的最大长度,后面的字符将被丢弃。
④赋值忽略符 * :
有时用户的输入可能不符合预定的格式,为了避免这种情况,scanf()提供了一个赋值忽略符*。只要把*加在任何占位符的百分号% 后面(%*c),该占位符就不会返回值,解析后将被丢弃。
#include<stdio.h>
int main()
{
int year = 0;
int month = 0;
int day = 0;
scanf("%d %*c %d %*c %d %*c",&year,&month,&day);
printf("%d %d %d\n",year,month,day);
return 0;
}
本章完结,希望对大家有所帮助,也会有错误,希望大家指出来,我们一起学习。