最近又稍微过了一些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)转义字符
\n 换行 \t tab \0代表空字符NULL
(3)字符串常量
字符串常量可以作为初值赋给字符串数组,并使用%s的格式输出
char str[25] = "hello world!"
print("%s",str)
4.布尔型
bool型在C++中可以直接用,但是在c语言中必须添加stdbool.h头文件才可以使用;
整型常量在赋值给布尔型变量是都会自动转换为true(非零)和false(零)
(新类型名)变量名
宏定义: #define 标识符 常量
例如:#define pi 3.14
const: const 数据类型 变量名 = 常量;
例如:const double pi = 3.14
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格式是可以读入空格和换行的
数据类型 | 格式符 |
---|---|
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函数。
getchar用来输入单个字符,putchar用来输出单个字符
getchar可以接收空格和换行
typedef可以给一个复杂的数据类型起一个别名
例如 typedef long long LL;
在接下来就可以使用LL代替longlong
C语言中没有对任意底数求对数的函数,必须使用换底公式
特别提醒:如果数组较大(大概?级别),则需将其定义在主函数外边,否则会使程序异常退出,原因是函数内部申请的局部变量来自系统栈,允许申请的空间较小;而函数外面的全局变量来自静态存储区,允许申请的空间较大。
给数组的每一个元素赋相同的值有两种方法:memset函数和fill函数
memset函数的格式为:memset(数组名,值,sizeof(数组名))
需要添加string.h头文件
建议初学者使用memset赋值0或-1,因为其按字节赋值,即对每个字节赋同样的值,如果要对数组赋其他数字,请使用fill函数
字符数组可通过直接赋值字符串来初始化,但仅限于初始化,程序其他位置不允许这样直接赋值整个字符串
%c能够识别空格和换行并将其输入,而%s通过空格或换行来识别一个字符串的结束
gets用输入一行字符串,识别换行符\n作为输入结束,因此scanf完一个整数后,如果使用gets,需要先使用getchar接收整数后的换行符
puts用来输出一行字符串,即将一位数组在界面上输出,并紧跟一个换行。
在一维数组的末尾都会有一个空字符\0,表示存放字符串的结尾;空字符\0在使用gets或scanf输入字符串时会自动添加在输入字符串的后面
返回两个字符串大小的比较结果,比较原则是按照字典序
strcmp(字符数组1,字符数组2)
①如果字符数组1<字符数组2,则返回一个负整数
②如果字符数组1 == 字符数组2,则返回0
③如果字符数组1>字符数组2,则返回一个正整数
strcpy函数可以吧一个字符串复制给另一个字符串
strcpy(字符数组1,字符数组2)
是把字符数组2复制给字符数组1,这里的复制包括结束符\0
strcat()可以把一个字符串接到另一个字符串后面
strcat(字符数组1,字符数组2)
是把字符数组2接到字符数组1后面
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)
函数的参数可以是数组,且数组作为参数时,参数中数组的第一维不需要填写长度,日过世二维数组,那么第二维需要填写长度,实际调用也只需要填写数组名,数组作为参数时,在函数中对数组元素的修改就等同于是对原数组元素的修改,数组可以作为参数,但是不允许作为返回类型出现
指针是一个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型数据的地址。
数组名称也可作为数据的首地址使用,有a==&a[0]成立
在上述代码中,a作为数组a的首地址&a[0]被赋值给指针变量p,因此输出*p其实就是输出a[0];
a+i等同于&a[i],但是也应该注意,a+i其实只是地址,如果想要访问其中的元素a[i],需要加上*号。
指针类型作为函数参数的类型,这时视为吧变量的地址传入函数。如果在函数中对这个地址中元素进行改变,原先的数据就会确实被改变
引用不产生副本,而是给原变量起了个别名,对引用变量的操作就是对原变量的操作
引用:在函数的参数类型后面加&,
由于引用是产生变量的别名,因此常量不可使用引用
访问结构体内的元素有两种方法:"."操作和“->"操作"
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;
使用构造函数来初始化结构体,构造函数特点:不需要写函数类型,且函数名与结构体名相同。
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(){}"手动加上,这意味着,只要参数个数和类型不完全相同,就可以定义任意多个构造函数,以适应不同的初始化场合。
cin与cou是C++中的输入与输出函数,需要添加头文件#include<iostream>和using namespace std才能使用。
如果想读入一整行,则需使用getline函数:
char str;
cin.getline(str,100)
如果是string容器,则
string str;
getline(cin,str);
如果想要控制double型的精度,例如输出小数点后几位,则需添加” #include< iomanip > “头文件
cout<<setiosflags(ios::fixed)<<setprecision(2)<<123.4567<<endl;
事实上,对考试而言并不推荐使用cin和cout来进行输入输出,因为他们在输入输出大量数据的情况下表现得非常糟糕。只有在十分必要的时候才使用cin和cout。
由于计算机采用有限位的二进制编码,因此浮点数在计算机中的存储并不总是精确的
如果题目没有给定输入的结束条件,那么久默认读到文件末尾
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){
...
}
题目中要去输入的数据满足某个条件时停止输入。
有两种写法:一种是在while...EOF内部进行判断
或者把退出条件判断放到while语句中
题目总会给出测试数据的组数,然后才给出相应数量组数的输入数据
原文:https://www.cnblogs.com/ttzz/p/12153237.html