1.1个空格键=2个\x20的效果,你们发现了吗。
2.C语言中字符和ASCII码是一一对应的。
3.浮点数有有效位数的要求,所以比较两个浮点数是否相等,只需要比较他们的差值是否在一个范围内即可。
4.隐式转换的顺序呢由(char、short)-> int->unsigned->long->double <-(float)
5.C语言中运算符的结核性是其他高级语言所没有的。
6.printf中要出现%,要加两个,形同%%。
7.“/”运算符,左右如果出现负的,那么符号看op1,然后大都采用向零取整的方法。
8.关系运算符中==和!=的优先级最低。
9.一般认为逻辑与&&的优先级大于逻辑或||。
10.判断闰年的条件:能被4整除但不能被100整除,或能被400整除
year%4==0&&year%100!=0||year%400==0
11.a>b?a:b 类似的条件表达式,结合性同赋值运算符一样是右结合的
12.复合赋值运算符右边的表达式应该作为一个整体来看待。 a+=b+c <=> a=a+(b+c)
13.遇到+++时,采用从左到右的最长匹配原则。
14.C中自增自减操作比同效果的赋值运算要快得多,所以可以多用。
15.逗号表达式的优先级最低,且整个逗号表达式的值(一般不求)是最右边一个的值。
16.!p++,!和++优先级相同,且都是右结合。
17.switch后边不能跟浮点型,且多个case语句可共用一组执行语句。
18.c语言中的数值定义之后,要使用必须要进行初始化,不然会是系统分配的随机值。
19.变量的声明,只是类型。而定义则不仅包括声明,还包括内存空间的分配。
20.for语句后边不能加分号;,否则循环执行体部分就成了空语句,
21.写循环时要注意先找寻累加量之间的关系,可以帮助减少循环的层数或者循环变量的使用。
22.注意小细节,例如 sum=sum+i/(i+1.0),此时就必须是1.0,否则该表达式的值就一直为0.
23.语言真的只是工具,重在思想方法!例如最小公倍数求法,用两数相乘再除以最大公约数即可.
24.经典的菱形问题,空格数为n-i, 星星数为2i-1(n为总行数,i为当前行数)
25.在循环的嵌套问题中,内层循环变量往往与外层循环变量相关。
26. if(n%10==0) printf("\n");像这种加一个变量的方法,可以用来控制输出的个数。
27.continue结束内层循环;break由内层循环跳到外层循环(即结束本层)。
28.格式控制中的%md,其中m限制了数据宽度,原数据不够m长,前补空格。%m.nf,效果如前,加负号之后,%-m,就是改成后补空格;%f,小数点后保留6位,第7位四舍五入。
29.%u无符号表示一般是%d有符号十进制的两倍。
30.%m.ns,作用是输出m位字符,从左端截取n位字符,n<m,前补空格。加负号后,后补空格。
31.内存中二进制转化为%o,%x的时候,如果带有符号位,则也作为转化后的一部分进行输出。
32.scanf函数的控制串中,%之间可以是空白符,也可以是字符或字符串。
33.printf("\n"),和putchar('\n')的作用是一样的,一个单引号一个双引号。
34.数组变量和指针变量可以存储字符串。
35.puts()函数的作用是输出字符串并换行,因为它在遇到\0时会自动转化成\n。
36.数组在定义时,不能是常量。
37.调用函数时变量是按照传值的方式传递,形参的改变不会影响实参。
数组是按照传地址的方式传递,形参的改变会影响实参。因为实参形参指向的是同一块存储区.
38.数组逆序设计的两个数字一般是 i 和 n-1-i。 N为数组元素的个数。
39.在交换两个数的值时,可以用的方法有临时变量、异或和加减,但是在当作为参数进行传递时,只有传地址和传指针的方法可以让形参的改变,改变实参的值。其中用异或方法的时候,必须是取地址。
40.在scanf函数中,如果输入的是字符串数组,那么在写的时候就不用加&号了,因为数组的名字本身就代表地址。
41.switch里边不能是浮点型;多个case共用一个执行语句时,只需要 case: 即可,不用加别的。
42.数组的初始化可以使用{}来进行,字符串数组的初始化可以直接使用""字符串即可,可省略大括号;且对于数组的操作一般分为3个部分,初始化,修改值,循环输出。
43.printf与puts没有太大区别;但scanf和gets则区别较大,scanf在遇到空白符、回车时就结束输入,而gets只有在遇到回车时才结束输入。 eg.hello world.
44.在进行字符串的连接、赋值等操作时,一般判断的依据就是结束标志\0.并且别忘记在最后生成的字符串后边添加结束标志。
45.函数的定义中可以调用其它函数,但是c语言不支持函数的嵌套定义。
46.return语句可加括号也可以不加,起作用就是讲表达式的值返回给主调函数。
47.如果要将多个值返回主调函数,用return是无法实现的。
48.形参在调用前没有具体值,在函数调用后才分配内存,调用结束后内存会释放。
49.实参与形参之间是单向传递的值传递。形参实参占用不同的内存单元。
50.引用调用,是把实参的地址赋值给形参,被调函数使用这个地址才存取实际的变量。
51.有参函数的声明中,参数的声明,只需要给出参数额类型即可。然后加上分号。
52.什么时候可以省略函数声明:外部已经声明;被调函数定义在主函数之前;返回值的类型为整形或字符型。
53.C语言的特点之一就是允许函数的递归调用。例如阶乘的运算,斐波那契数列、汉诺塔等。
54.一般的函数都具有外部性质,可以被整个源程序的函数调用。但是如果加上static(并非指存储方式)那么该函数就变成内部函数,只能被本文件的函数调用,而不能被同一源程序其他文件的函数调用。在一个源文件的函数中,调用其他源文件中定义的外部函数通常使用extern来进行说明,在定义时则可省略不写。
55.main函数的参数,main(int argc,char *argv[]).其中参数一指的是命令行参数的个数。往往文件名也算一个。eg;08-12 i am happy!(共4个参数);参数二指的是指向字符串的指针数组,存储的是每个字符串的首地址,另外要注意的是,在命令行中的输入都将作为字符串存储于内存中。如果输入了一个数字,现在要输出,那么要使用%s,而非%d.
56.函数体内部使用的局部变量包括形式参数和函数体内定义的参数。
57.x=rand()*101+100(表示的就是100-200间的数字;rand()表示0-1)
58.变量的作用范围产生冲突时,以小范围的优先。全局变量的使用增加了函数间传递数据的途径,有助解决多个返回值的问题。
59.按照变量的生存期来划分,可分为静态变量(变量类型:static,extern);动态变量(变量类型:auto, register,);auto为默认,register可由编译系统的优化来解决;
60.C语言规定静态局部变量有初始值,int 0,float0.0,char '\0',而自动和寄存器没初始值,是随机值。
61.静态局部变量,程序开始时及分配内存,仍具有局部特性,离开函数,不起作用,但仍然存在!并且由于这个特性,含有该变量的函数不管多少次执行,都保留上一次调用时的值。
#include<stdio.h>
long fac(int a)
{
static long f=1;
f=f*a;
return f;
}
void main()
{
int a,i;
long f;
a=5;
for(i=1;i<=a;i++)
{
f=fac(i);
}
printf("%ld!=%ld\n",a,f);
}
62.静态全局变量只能被某一程序中,定义它的某个文件所独享。
#include <stdio.h>
int n;
int main()
{
n=100;
printf("%d\n",n);
f(5);//输出是50而不是500,说明两个n是互不干涉的,静态局部变量只在定义它的文件内有效。
}
#include<stdio.h>
static int n;
int f(int x)
{
n=10;
n*=x;
printf("%d\n",n);
}
63.对数据的访问分为直接访问和间接访问,直接访问是通过变量实现,变量实际是存储区域的名称;间接访问通过指针实现,指针存储的是数据在内存中的地址。
64.变量a的内存地址就是变量的指针,用另一个变量b来存储该变量a的指针,那么变量b就叫做指针变量。
65.指针变量在使用前必须被初始化,赋值为0的指针变量成为空指针。
66.当用指针变量来排序比较大小时,用临时变量法交换大小,用的一般是地址。及*p1的p1
67.使用函数交换两个指针时,可以交换*p或者p,两者的不同是,前者才可以改变实参的值。可画图分析。
68.定义int a=1,b=10;这样a,b就会依次存储在栈中,且栈是向低地址扩展的一种存储结构,所以定义 int*p=&a;那么p-1实际就是变量b的存储空间的地址。针对这类连续存储空间,使得指针可在数组中进行类似的操作。
69.指针与函数的关系
①指向函数的指针:eg int(*p)(int,int) 其中p存储的是函数的入口地址,赋值时只需要让p=(max)函数名即可。
②返回指针的函数:int*max(int x[], int y[], int *p, int *n),具体使用时 p=max(x,y,&n,&c);其中&n等就是引用的方法,目的是使函数返回多个返回值。
70.void指针用于指向一个抽象类型的数据,在赋值给其他指针变量时需要进行强制类型转换。当然也可以将一个函数赋值为void*型,用时也要转换。
71.数组赋值 for(i=1;i<n;i++) scanf("%d",&array[i]);
72.考虑问题由上到下,层层细化。考虑清楚后,针对循环,要从外到内设计,从里到外实现。
73.二维数组中指针的运算。
特别注意,在二维数组中,输出元素的方法:
①下标访问就直接:array[i][j] //i,j分别表示行列。
②数组名访问:*(*(array+i)+j)
③指针来访问:p=&array[0][0] *(p+3*i+j) //实际就当做一维的来运算
74.指针作为参数传递给函数,分两种情况,一种是指针变量,另一种是数组的指针。即具体分形参实参分别为数组和指针两种情况。
75.一般指针变量具有的操作有自加、自减,或加某个数字等等。
76.经典例统计字母出现次数的例题中:if(*p>='a'&&*p<='z') arr[*p-'a']++; //程序设计的艺术性体现
77.一般指针与字符串相结合的处理,一般的操作就是: char str[10]; char *p; p=str; //因为此时str应为常量,如果涉及字符串每个字符的处理,就应这样做,就可以用p++,来进行处理。
78.指向字符串的指针,或字符串数组,输出时不用控制,可以直接用%s输出,然后printf的参数用指针变量名或者数组名。eg:printf("%s \n".p);
79.指针数组是指数组由指针类型的元素构成。eg: char *seasons={"spring","summer","winter","autum"}; char **p;
应用时 p=seasons+i; seasons[i]已经是指针,那么seasons +i 就是指针的指针,同p同类型,*p=*(seasons +i),即表示seasons[i],表示第i个字符串的首地址,对应用作输出每个字符串。
80.数组指针 int(*p)[10] 表示用p来指向含有10个元素的整形数组。eg: int array[2][3]; int (*p)[3]; 就可以这样赋值 p=array,因为array表示下标为0的那一行,且该行有3个元素符合定义;输出时可用p[i][j]来输出,它等同于*(p+i)[j]==*(p[i]+j)==*(*(p+i)+j)
81.进行位运算时(如a & b,而a为long型,b为int型),系统会将二者按右端对齐。系统会据b的类型进行高位补齐。
82.设置一个低4位全为1,其余全为0的数。 ~ ( ~ 0 << 4 ) ; 实现循环右移:b=a<<(m-n) ; c=a>>n; c=c|b;
83.位段成员的类型必须制定为unsigned或者int类型。
84.ASCII文件,每个字节存放一个ASCII码;二进制文件即数据在内存中的存放形式。
85.文件操作习惯这样的写法:if(in=fopen(infilename,'r'==NUll) ) {printf("can not open the file\n"); exit(0);}
while(!feof(in)) fputc(fgetc(in),out);//实现文件的复制,文本文件。 fclose(in);//文件的关闭操作。
86. 数据块读写函数 fread(f,4,2,fp); 此函数从fp所指向的文件中读入2个4个字节的数据,存储到数组f中。还有fwrite函数,用法类似。
87.因为涉及形参实参的关系,所以在主函数和被调用函数中往往出现相似的赋值和操作!!!
88.格式化读写函数fprintf(),fscanf(),对磁盘文件进行读写,但输入时要把ascii码转换成二进制形式,输出时相反,所以在内存与磁盘频繁交换数据时,尽量避免使用该俩函数,而用fread和fwrite来代替。
89.对磁盘文件读写一个数(整数)putw(10,fp);i = getw(fp);
90.fgets(str,n,fp),作用从指定文件读入一串(n-1个字符,'\0'算上)字符。str为起始地址。
91.fputs(p,fp),作用向指定文件输出一串字符。p可以是字符串,字符串指针,或者字符数组名。
92.注意文件操作中对文件的定位。
①fseek(文件类型指针,位移量,起始点),eg: fseek(fp,10L,0) //将文件指针移动到离开始位置。1为当前位置,2为文件结尾。一般用于二进制文件,一般和fread想配合使用。跟结构体配合使用时常出现 sizeof(struct student_list)
②rewind(fp) //将指针重新定位回文件的开头。
③ftell(fp) //得到流式文件当前的指针位置,正确返回int型值,离开始位置的偏移量;错误返回-1L.
93.错误处理:
①ferror(fp) 返回0表示未出错,返回非0表示出错了。
②clearerr(fp) 使文件错误标志和文件结束标志清0
94.文件结束标志 feof(fp) 如果结束的话返回的值是 真。
95. 随机函数常用的:srand((usigned)time(NULL)); //随机时间播种
96.用这种方法可以创建一个数组。可能是内部实现。
97.用malloc申请的是空闲内存,一般以堆的形式来存储。
98.qsort使用实例:
qsort((void *)intarr, num, sizeof(intarr[0]), sortcmp);
int sortcmp(const void *a,const void *b)
{
return *(int*)a-(int*)b; //,字符的也可这样算,double型数组、结构体用条件运算符,不直接相减}
99.递归和非递归的转换往往只差一层循环而已!eg:二分查找的递归和非递归程序!
100.数组从0开始和从1开始也往往只在判断条件上差一个等号!
101.exit(N),用来传给操作系统N值,作用是结束整个程序,N值可用来表示是否正常退出等等情况。
102.冒泡排序中记得两个参数i,j 其操作分别是N个数,i为pass数=N-1; j为比较次数=N-i;最后的效果是大的沉到下边.交换次数较多。
void bubblesort(int a[], int n)
{
int i,j,t;
for (j=0; j<n‐1; j++)
for(i=0; i<n‐j; i++)
if (a[i]>a[i+1])
{
t=a[i];
a[i]=a[i+1];
a[i+1]=t;
}
return;
}
103.选择排序是每次选出最小的放到前边。起操作是N个数,i为pass数=N-1;具体是j算做标志=n+1; 交换次数较少。
void select_sort(int array[],int n) //形参array是数组名
{
int i,j,k,t;
for(i=0; i<n‐1; i++)
{
k=i; //先设第i个就为最小,程序设计中假设的使用可以极大地方便程序员的编程和代码的优化。eg.if语句中的思维假设。
for(j=i+1; j<n; j++)
if(array[j]<array[k])
k=j; //通过循环,得到k为最小
t=array[k]; //交换a[i]和a[k]
array[k]=array[i];
array[i]=t;
}
return;
}
104.数学公式的计算往往涉及构造一个包含很多参数的函数:eg:
int p(int a, int x[], int b, int y[], int n)
{ int i, s;
for(_i=0,s=0; i<n; i++)
s+=a*x[i]+b*y[i];
return s;
}
105. cpp:不能用赋值语句将一个字符串常量或字符数组直接赋给一个字符数组。字符串的比较和赋值都要用到函数,strcmp 和strcpy. 此外还有 strcat, strlen, strlwr, strupr and so forth. 要想直接赋值的话,倒也可以,就是包含stirng 头文件后,再定义相应的字符串变量就可以了。
106.有些函数不需要调用者,只需要写出即可 eg: strrev(p); 因为这类函数的内部实现机制已经规定好了是反转完毕后,存到原来的数组中去,且并不返回相应内存单元的地址。
107.一种字符串输出方式:
/****************************************************************************/
108.exit(0),exit(1),return释义:
1. return返回函数值,是关键字; exit 是一个函数。
2. return是语言级别的,它表示了调用堆栈的返回;而exit是系统调用级别的,它表示了一个进程的结束。
3. return是函数的退出(返回);exit是进程的退出。
4. return是C语言提供的,exit是操作系统提供的(或者函数库中给出的)。
5. return用于结束一个函数的执行,将函数的执行信息传出供其他调用函数使用;exit函数是退出应用程序,删除进程使用的内存空间,并将应用程序 的一个状态返回给OS,这个状态标识了应用程序的一些运行信息,这个信息和机器和操作系统有关,一般是
6. 非主函数中调用return和exit效果很明显,但是在main函数中调用return和exit的现象就很模糊,多数情况下现象都是一致的。
109.
110.