最近又稍微过了一些C和C++的基础知识
1.整型
①整型int:32bit,取值范围,范围以内整数都可定义成整型
②长整型long long:64bit ,取值范围,如果longlong型赋值大于的数,需要在初值后面加上LL
%d是int型的输出格式
2.浮点数
①单精度float:32bit,范围,但是有效精度只有6-7位
②双精度double:64bit,范围,有效精度15-16位。
对浮点型来说,不要使用float,碰到浮点型的数据都应该用double来存储
%f是float和double型的输出格式
3.字符型
字符常量(必须是单个字符)必须用单引号标注
%c是char型的输出格式
(2)转义字符
换行 tab 代表空字符NULL
(3)字符串常量
字符串常量可以作为初值赋给字符串数组,并使用%s的格式输出
char str[25] = "hello world!"
print("%s",str)
4.布尔型
bool型在C++中可以直接用,但是在c语言中必须添加stdbool.h头文件才可以使用;
整型常量在赋值给布尔型变量是都会自动转换为true(非零)和false(零)
2.1.3强制类型转换
(新类型名)变量名
2.1.4符号常量和const常量
宏定义: #define 标识符 常量
例如:#define pi 3.14
const: const 数据类型 变量名 = 常量;
例如:const double pi = 3.14
2.2 顺序结构
2.2.2 使用scanf和printf输入输出
1.scanf
scanf 是输入函数,格式如下:
scanf(“格式控制”,“变量地址”)
scanf("%d",&n)
数据类型 | 格式符 | 举例 |
---|---|---|
int | %d | scanf("%d",&n) |
long long | %lld | scanf("%lld",&n) |
float | %f | scanf("%f",&f) |
double | %lf | scanf("%lf",&n) |
char | %c | scanf("%c",&ch) |
字符串(char数组) | %s | scanf("%s",str) |
注意str前不需要加取地址符
scanf的%c格式是可以读入空格和换行的
printf
数据类型 | 格式符 |
---|---|
int | %d |
long long | %lld |
float | %f |
double | %f |
char | %c |
字符串(char数组) | %s |
对于double类型的变量,其输出格式变成了%f,而不是%lf
三种实用的输出函数
(1)%md
可以使不足m位的int型变量以m位进行右对齐输出
(2)%0md
当变量不足m位时,补足够数目的0,而不是空格
(3)%.mf
可以让浮点数保留m位小数,这个保留使用的是精度的“四舍五入成双”原则;如果是四舍五入,需要用到round函数。
2.2.3 使用getchar 和putchar 输入输出字符
getchar用来输入单个字符,putchar用来输出单个字符
getchar可以接收空格和换行
2.2.5 typedef
typedef可以给一个复杂的数据类型起一个别名
例如 typedef long long LL;
在接下来就可以使用LL代替longlong
2.2.6 常用math函数
1.fabs(double x) 绝对值函数
2.floor(double x) 向下取整 ceil(double x) 向上取整
3.pow(double r,double p)
4.sqrt(doble x) 算数平方根
5.log(double x) 以自然对数为底的对数
C语言中没有对任意底数求对数的函数,必须使用换底公式
6.sin(double x)、cos(double x)、tan(double x)
7.asin(double x)、acos(double x) 、atan(double x)
8.round(double x) 四舍五入
2.5.3 二维数组
特别提醒:如果数组较大(大概级别),则需将其定义在主函数外边,否则会使程序异常退出,原因是函数内部申请的局部变量来自系统栈,允许申请的空间较小;而函数外面的全局变量来自静态存储区,允许申请的空间较大。
2.5.4 memset--对数组中每一个元素赋相同的值
给数组的每一个元素赋相同的值有两种方法:memset函数和fill函数
memset函数的格式为:memset(数组名,值,sizeof(数组名))
需要添加string.h头文件
建议初学者使用memset赋值0或-1,因为其按字节赋值,即对每个字节赋同样的值,如果要对数组赋其他数字,请使用fill函数
2.5.5 字符数组
1.字符数组的初始化
字符数组可通过直接赋值字符串来初始化,但仅限于初始化,程序其他位置不允许这样直接赋值整个字符串
2.字符数组的输入输出
(1)scanf /printf
%c能够识别空格和换行并将其输入,而%s通过空格或换行来识别一个字符串的结束
(2)getchar输入,putchar输出
(3)gets输入,puts输出
gets用输入一行字符串,识别换行符 作为输入结束,因此scanf完一个整数后,如果使用gets,需要先使用getchar接收整数后的换行符
puts用来输出一行字符串,即将一位数组在界面上输出,并紧跟一个换行。
3.字符数组的存放方式
在一维数组的末尾都会有一个空字符 ,表示存放字符串的结尾;空字符 在使用gets或scanf输入字符串时会自动添加在输入字符串的后面
2.5.6 string.h头文件
1.strlen()
2.strcmp()
返回两个字符串大小的比较结果,比较原则是按照字典序
strcmp(字符数组1,字符数组2)
①如果字符数组1<字符数组2,则返回一个负整数
②如果字符数组1 == 字符数组2,则返回0
③如果字符数组1>字符数组2,则返回一个正整数
3.strcpy()
strcpy函数可以吧一个字符串复制给另一个字符串
strcpy(字符数组1,字符数组2)
是把字符数组2复制给字符数组1,这里的复制包括结束符
4.strcat()
strcat()可以把一个字符串接到另一个字符串后面
strcat(字符数组1,字符数组2)
是把字符数组2接到字符数组1后面
5.sscanf与sprintf
sscanf与sprintf是处理字符串问题的利器(sscanf可以理解为string+scanf,sprintf可以理解为string+printf。均在stdio.h头文件下)
scanf("%d",&n)
printf("%d",n)
可以写为
scanf(screen,"%d,&n);是把screen的内容以%d的格式传输到n中(从左至右)
sprintf(screen,"%d",n);是把n以“%d的格式传输到screen上(从右至左)
sscanf与sprintf与上面的格式相同,只不过是将screen换为字符数组
char str[100];
sscanf(str,"%d",&n):把字符数组str内容以%d的格式写到n中(从左至右
sprintf(str,"%d",n):把n以%d的格式写到字符数组中(从右至左)
复杂:
sscanf(str,"%d:%lf,%s",&n,&db,str)
sprintf(str,"%d:%.2f,%s",n,db,str2)
2.6.3 以数组作为函数参数
函数的参数可以是数组,且数组作为参数时,参数中数组的第一维不需要填写长度,日过世二维数组,那么第二维需要填写长度,实际调用也只需要填写数组名,数组作为参数时,在函数中对数组元素的修改就等同于是对原数组元素的修改,数组可以作为参数,但是不允许作为返回类型出现
2.7.2 指针变量
指针是一个unsigned类型的整数
指针变量用来存放指针(或者可以理解为地址),这个关系就和int型变量用来存放int型常量相同。可以把地址当做常量,然后专门定义了一种指针变量来存放她,但是指针变量和普通变量有区别,它在某种数据类型后加*来表示这是一个指针变量
int* p;
double* p;
char* p;
*的位置在数据类型之后或者是变量名之前都是可以的
如果一次有好几个同种类型的指针变量要同时定义,星号只会结合于第一个变量名。
int* p1,p2;则只有p1是int*型的,而p2是int型的;
如果要让后面定义的变量也是指针变量,需要在后面的每个变量名之前都加上星号;
如刚才所说,指针变量存放的是地址,而&是取地址运算符,因此给指针变量赋值的方式一般是把变量的地址取出来,然后赋值给对应类型的指针变量
int a;
int *p = &a;
上面的代码也可以写成:
int a;
int* p;
p = &a
int是指针变量的类型,而后面的p才是变量名,用来存储地址,因此 地址&a是赋值给p而不是p的。要知道星号是类型的一部分就不会出错
那么对于一个指针变量存放的地址,如何得到地址所指的元素呢?其实还是用星号。假设定义了int p=&a,那么指针变量p就存放了a的地址。为了通过p来获得变量a,可以吧星号视为一把开启房间的钥匙,将其加在p前面,这样 *p就可以把房间打开,然后获得a的值
既然p保存的是地址,*p是地址中存放的元素,那么如果对 *p进行赋值,也可以起到改变那个保存的元素的功能,
另外,指针变量也可以进行加减法,其中减法的结果就是两个地址偏移的距离。对一个int*类型的指针变量p来说,p+1是指p所指的int型变量的下一个int型变量地址,这个所指的下一个是指跨越了一整个int型;除此之外,指针变量支持自增和自减操作,因此p++等同于p=p+1;指针变量一本用于数组中
对指针变量来说,把其存储的地址的类型称为基类型,例如定义为int* p的指针变量,int就是它的基类型。基类型必须和指针变量存储的地址类型相同,也就是说,上面定义的指针变量p,不能够存放double类型或char类型的数据的地址,而必须是int型数据的地址。
2.7.3 指针与数组
数组名称也可作为数据的首地址使用,有a==&a[0]成立
在上述代码中,a作为数组a的首地址&a[0]被赋值给指针变量p,因此输出*p其实就是输出a[0];
a+i等同于&a[i],但是也应该注意,a+i其实只是地址,如果想要访问其中的元素a[i],需要加上*号。
2.7.4 使用指针变量作为函数参数
指针类型作为函数参数的类型,这时视为吧变量的地址传入函数。如果在函数中对这个地址中元素进行改变,原先的数据就会确实被改变
2.7.4 引用
引用不产生副本,而是给原变量起了个别名,对引用变量的操作就是对原变量的操作
引用:在函数的参数类型后面加&,
由于引用是产生变量的别名,因此常量不可使用引用
2.8结构体的使用
2.8.2 访问结构体内的元素
访问结构体内的元素有两种方法:"."操作和“->"操作"
struct studentInfo{
int id;
char name[20];
studentInfo* next;
}stu,*p;
访问stu中变量:
stu.id
stu.name
stu.next
而访问指针变量p中元素写法如下:
(*p).id;
(*p).name;
(*p).next;
或者
p->id;
p->name;
p->next;
2.8.3 结构体的初始化
使用构造函数来初始化结构体,构造函数特点:不需要写函数类型,且函数名与结构体名相同。
struct studentInfo{
int id;
char gender;
//默认生成的构造函数
studentInfo(){}
};
如何初始化参数:
struct studentInfo{
int id;
char gender;
//下面的参数用以对结构体内部变量进行赋值
studentInfo(int _id,char _gender){
//赋值
id = _id;
gender = _gender;
}
//构造函数也可以简化为一行
studentInfo(int _id,char _gender):id(_id),gender(_gender){}
};
注意,如果自己重新定义了构造函数,则不能不经初始化就定义结构体变量,这时候可以把“studentInfo(){}"手动加上,这意味着,只要参数个数和类型不完全相同,就可以定义任意多个构造函数,以适应不同的初始化场合。
2.9 补充
2.9.1 cin与cou
cin与cou是C++中的输入与输出函数,需要添加头文件#include<iostream>和using namespace std才能使用。
如果想读入一整行,则需使用getline函数:
char str;
cin.getline(str,100)
如果是string容器,则
string str;
getline(cin,str);
cout
如果想要控制double型的精度,例如输出小数点后几位,则需添加” #include< iomanip > “头文件
cout<<setiosflags(ios::fixed)<<setprecision(2)<<123.4567<<endl;
事实上,对考试而言并不推荐使用cin和cout来进行输入输出,因为他们在输入输出大量数据的情况下表现得非常糟糕。只有在十分必要的时候才使用cin和cout。
2.9.2 浮点数的比较
由于计算机采用有限位的二进制编码,因此浮点数在计算机中的存储并不总是精确的
2.10 黑盒测试
2.10.2 多点测试
1.while ....EOF型
如果题目没有给定输入的结束条件,那么久默认读到文件末尾
scanf函数返回值为其成功读入的参数个数,语句scanf("%d",&n),返回值为1;
只有在读取文件时到达文件末尾导致无法读取的现象,才会产生读入失败。这个时候,scanf函数会返回-1而不是0,且C语言中使用EOF(End Of File)来代表-1,于是就有了下边这种写法:
while(scanf("%d",&n != EOF)){
..........
}
如果读入字符串,则有scanf("%s",str),与gets(str)两种方式可用,对应的输入写法如下:
while(scanf("%s",str) != EOF){
....
}
while(gets(str) != NULL){
...
}
2.while...break型
题目中要去输入的数据满足某个条件时停止输入。
有两种写法:一种是在while...EOF内部进行判断
或者把退出条件判断放到while语句中
3.while(T--)型
题目总会给出测试数据的组数,然后才给出相应数量组数的输入数据