true是所有非0数,包括负数。只有0才是false
在强制类型转换的过程中,是直接截掉而不是四舍五入。(比如b=1.8,(int)b是1),输出"%.2f"这种是四舍五入的(四舍六入五成双)
define是完全替换,因此define定义的时候最好加好全部括号。
位运算符的优先级没有算数运算符高。
位运算符左移是变大(按照二进制) eg:a=3 a<<2 a左移两位,变成3*2^2=12
赋值的过程中 a=b=5,这种是a和b都被赋值为5,多位同时赋值。
字符串数组 char str[100]这类的,输入的时候用%s,不用&,
double的输入用%lf,输出用%f,float都是%f。注意double一定要%lf,注意!不然可能不会报错但是读取无效
long long的输入输出都是%lld
特殊数据类型,比如12:30:08这种数据,需要读取里面的三个数字,那么scanf("%d:%d:%d",&a,&b,&c),会在输入数据中自动跳过这些内容。
scanf在%c下可以读取到空格和换行,但如果scanf("%c %c",&a,&b).b可能无法读取空格
printf("%4d",a),这个是保证a的输出占用4位字符,也就相当于,右对齐(位数不满从右边开始占位,满了以后可以正常占位输出的,比如给4位实际上5位,那么就是从头开始五位)
如果是printf("%04d",a)是将a不满四位的地方用0占位,注意只能是0,其他字符或者数字这样弄无效果
printf("%.2f",a),保留两位小数,这个是四舍六入五成双,round是真正的四舍五入。【这个存疑,测试结果不太一样,可以暂时当四舍五入看】
四舍六入五成双:x小于4舍掉,x大于6进位,如果是5(且为最后一位),前一位是奇数进位,如果是偶数不进位舍掉。如果5后面还有数字,那么是一定进位的
getchar()和purchar()分别是读取字符,读取:x=getchar(),输出purchar(x);
typedef可以给数据类型重命名 比如 typedef long long LL;后面就都可以用LL来表示了
部分math函数:
fabs(double x),取绝对值,floor(double x)是向下取整,ceil(double x)是向上取整,pow(double r,double p)是r的p次方,都是double
abs也是绝对值,abs是求整数绝对值的。注意abs和fabs是不可混用的
sqrt(double x)是开平方,log(double x)以e为底的对数,如果要算别的用换底公式
如果使用switch case语句,没有break后面的语句都执行,从判定成功的case开始,每一个case都执行
注意switch (表达式){case 值:句子;break;case值:句子;break;}
整体用一个大括号包起来,一般底下补一个default的对应情况,单case下面的不用包起来。
do{}while()是先执行一次,再去判断。
for如果第一次赋值就不符合判定,直接退出循环。
break是跳出循环,continue是本回合忽略后面语句,直接进入下一轮循环执行
如果数组赋初值 int a[10]={0},这种是所有都赋值0,别的都是只对单个生效的
数组大于1e6要开在主函数外面不然有可能异常退出。
memset的头文件是string.h,fill的头文件是algorithm,注意!memset(a,0,sizeof(a)),memset只用来赋值0或者-1,其他的用fill,fill是(a,a+x,val),从a[0]到a[x-1]被赋值为val,因为是开区间。所以a[x]没有。memset更快,所以这两个数还是尽量用memset
字符数组初始化可以用字符串赋值,其他情况不允许。允许用{‘a’,'b','c','0'}这种赋值。
判断字符数组的长度len=strlen(a),如果是字符串len=a.length(),不可混用。
如果已经初始给字符数组赋值,但是后面用%s读取,那么在strlen或者%s输出的时候只会输出读取的值。但要是单输出a[x],x在初始赋值范围内,但是还大于后面%s的长度,那时候会发现里面是有值的,是最开始赋值的那个字符哦。
如果原来初始赋值短,那么%s以后仍然可以按照%s的输出全输出出来哦。
gets和puts以换行符为标准。识别但是不吸收,所以如果真的要用的话,在下一行读取之前用getchar吸收一下回车。
注意%s遇到空格会停,gets可以读取的哦
上面这两个的原因是。scanf和gets会自动添加 ,如果你在读取以后,在前面加 ,那么%s或者puts再输出,或者使用strlen(strlen不计算 当前位置哦),结果都会发生改变。
同时因为' '的存在,没办法给“abc”这种赋值到char a[3],最少也得a[4]
如果字符串数组里面每一个是单独赋值,最好在后面手动添加' ';(大部分情况不加也行,但是好像看到过一些情况是有问题的)
string.h头文件下面的内容
strlen是求字符数组里面' '前面的长度,strcmp(a,b)是判断a是否比b的字典序大(注意,这个如果a>b只保证结果大于0,不一定就是1,相等为0,小于为负)
关于字典序:在两个字符序列都是非空的时候先比,然后遇到空了就是非空的大,不是比长度 比如aaaa就小于aab
strcpy(a,b)是把b的内容复制给a,strcat(a,b)是把b接在a的后面。
注意这两个,即使a开的数组不够大也没关系,复制和拼接都是可以的,会产生新的' ',strlen也会变。
函数参数如果是数组,一维数组可以不写长度,二维的第二维必须要写。而且在传数据的时候第二维长度要对上 void change(int b[][5])这种
函数传参可以改变数组真实的值,如果是一维数组,传参允许长度不对应,并且即使给原本不在定义长度范围内的赋值,也是有效的,你在外面再访问也ok。
指针是unsigned类型的整数。
int *p1,p2;只有p1是指针类型的。赋值的时候 int *p=&a;如果不在初始化的时候,就p=&a就可以。要访问地址对应数据就*p就可以。
指针p+1是移动一个对应基类型的占位。(int*p里面int就是基类型。)指针支持p++,p--这种。
数组名就是数组的首地址 a=&a[0]。注意,在计算的过程中如果p-q,这时候出来的结果是地址字节距离/基类型占用字节长度。int &a[1]-&a[0]结果是1不是4哦。
如果函数传指针,那么传入的可以看作是变量地,这种情况变量的真实值会被修改 void change(*p) int a 调用的时候 int *p=&a change(p)或者change(&a)
注意理解,函数定义的int*p是告诉是指针,不是取值什么的。
这里面函数不能直接用地址,不然又成单向值传递了,要用*p访问对应地址的真实数据。改掉该地址的数据才是有效的。
指针定义的时候尽量要初始化。
对引用的操作就是对原变量的操作,所以如果函数里面void change(int &a){}这种,有修改效果的。这种外面用的时候就change(a)就行哦。
在结构体 struct student {int age;student*next;};现在定义 student *p,stu[200],a,p访问里面的元素 p->age,p->next或者(*p).age,其他两个都是stu[1].age,a.age这种。->是给本身是指针的用的,不是看结构体里面是啥。
结构体的构造函数不用写返回值类型,函数名与结构体名完全一致。如果自己写了构建函数,一定要补上空的情况。
student(){} student(int idnum){id=idnum} student(int idnum,int agenum):id(idnum),age(agenum){}三种方法 允许只给结构体里面部分内容赋值。