C语言笔记

数据

1. 1e-3:aeb类型,即a*(10^b);

2. int rand(void)函数:

位于stdlib,h;

返回一个0~RAN_MAX的值伪随机数,若随机数种子相同,则返回的随机数序列相同;

RAN_MAX的值为int类型的最大值;

默认随机数种子为1,可用void srand(int)在rand()之前设置随机数种子,一般用time(NULL) 当前时间的毫秒                            数作为参数。

可用取余操作%来限制随机数的范围;

3. %取余的操作数必须为整型(即整数,正负皆可);取余操作的结果与第一个操作数的正负性相同;

4. 字符常量: '/a';a可为八、十六进制;

5.递增操作a++,当变量a使用完毕不再需要时即执行+1而不会等到所有语句都执行完,如while(T--),判断完成后即完成-1;a-->0,即使a不满足条件,在判断之后还是会执行a--!!!!


输入输出

1. %格式控制符,后接d等,若没有则忽略;%%表示输出字符%;

2. %*c : *空读一个数据,%*c为空读一个字符,读取但不赋值;

3. getchar()函数: 返回值为所输字符的ASCII码,直到用户输入回车才结束;

4.整数部分若实际数值比规定位数多,则按实际数值输出;若少,则空格补位,空格位置视是否有符号;浮点数补零。

5.getchar()函数:行缓冲输入方式。将输入的结果放在输入缓冲区队列,直至输入EOF或者换行符为结束,getchar()从输入缓冲区内读一个字符,故两个连续的getchar要在同一行输入,否则第二个getchar()得到的值是换行符;

6. 连续的scanf当心将换行符赋给%c : 可用getchar()吃掉换行符;%c前留空格可无视所有空白字符:换行、制表、空格;

7.scanf()可以指定位宽,但不能指定输入浮点数的精度,返回值为成功读取的类型的数量;不能包含换行符。

   short对应%hd。

8.输出double和float都是用%f,但double输入格式为%lf。因为printf时,float会被转换成double。

9.gets函数会一直接收输入(包括空格)直到换行,所以如果数据中有空格,最好用gets来获取。另外,如果gets函数前还有其他输入函数,要用getchar去吃掉缓冲区内的换行符,否则会直接略过gets函数。且,不能定义指针p再gets(p),因为p可能指向任何非法地址。


条件语句

1.优先级:算数运算符优先级高于逻辑运算符,==和!=优先级在逻辑运算符中最低;

               (一元运算符) 逻辑非->算术运算符->逻辑运算符->逻辑与->逻辑或

2.结合性:逻辑运算符、逻辑与、逻辑或的结合性都为从左到右;

一元运算符(逻辑非)都为从右到左;

3.短路特性:逻辑与、逻辑或,若由左操作数已经知道运算结果,则不再计算右操作数。

4.唯一三元运算符 ? :    max=a>b?a:b;

5.switch:case,break,default


溢出

1.一般不用相减来判断大小,因为可能第一个操作数小于第二个操作数,而结果溢出为正;

2.浮点数运算既可以上溢也可以下溢;

3.要使用数据类型大小时,最好用sizeof(),可提高可移植性;


舍入(截断):针对不同数据类型之间的转换

int->float:不会溢出但可能被舍入;


精度损失

float:有效数字6~7位,精度位数包含整数部分和小数部分

double:有效数字16位

32位系统下,long->float:损失第7位以后的准确性(不含第7位)

十进制小数与二进制小数非一一对应,所有二进制小数都可以找到一个精确的十进制小数,反之则不行,故,当十进制小数转换为二进制小数不能精确表示时,就取近似值;当该近似值再转换为十进制小数时,已经与原小数不同;

两个浮点数,一很大一很小,进行运算时可能发生舍入运算,即无视小的浮点数,结果仍未大的浮点数;


测试

白盒测试/结构测试

黑盒测试/功能测试


导论

程序=算法+数据结构

软件=程序+文档


循环

exit(0)在stdlib.h中,强制终止程序的运行返回到操作系统;

break和continue;continue:无视continue之后的语句,for直接跳转到增,while跳到条件判断;

goto:跳出多重循环使用 goto error; error:       多种情况中的相同错误类型

务必注意switch语句中有无break!!!!


错误类型:

编译错误:语法错误

链接错误:缺少包含的文件

运行时错误:逻辑错误,除零、非法内存访问


函数

1.若函数类型缺省,则默认为整型;

2.assert()宏,定义在<assert.h>,测试断言,为便于理解可视为函数 void assert(int expression),若括号内的假设内容为真,则继续执行;否则,中断程序并报告错误所在的行。等价于 if() exit(1);但后者在debug版本和release版本都会被执行,而assert宏只在debug版本中执行,而在正式的发布版本中不执行,故前者更好,在release中不会影响程序执行的效率。所以断言不能取代条件语句,只是一个标签,用于debug。一个断言一个条件。

3.先决条件务必进行判断,提高robustness。


编程风格

1.花括号换行;

2.函数定义之间空行;

3.定义变量时,初始化的习惯;对于一些需要注释的变量的定义,一个变量一行便于写注释;

4.二元运算符前后各加一个空格;一元运算符,[],.,->,不加空格;,和;后加空格;

   但在for和if的括号内有时为了追求紧凑型,二元运算符前后会不加空格;

   关键字如for,while等后加空格;

5.形参列表太长可进行缩进,如:

 if ((veryLongVar1 >= veryLongVar2)
      &&(veryLongVar3 >= veryLongVar4))
 {
	DoSomething();
 }
for (very_longer_initialization;
     very_longer_condition;
     very_longer_update)
{
     	DoSomething();
}
6.标识符的命名

共性规则:

有意义的单词;避免数字编号;全局变量和局部变量不重名;不以大小写区分不同标识符;

Linux/Unix风格:小写单词加下划线

Windows风格:大小写单词

Windows应用程序中的命名规则:匈牙利标记法

[限定范围的前缀]+[数据类型前缀]+[有意义的英文单词]

静态变量 s_,static, ch,char

动态变量 g_,global, i ,int

默认情况为局部变量 f ,float

p ,point

->简化:

限定范围和数据类型无视,无特殊意义的循环变量直接定义成i,j,k等单字母变量;

变量名小写字母开头,第二个单词开始首字母大写,形容词+名词形式;newTime;

函数名大写字母开头,之后每个单词首字母大写,动词+名词形式;GetMax()

宏和const常量标识符全大写,用下划线分割单词;

注释格式:修改代码的同时也要注意修改注释或加注释,修改时间、修改人;

重要文件的首部:文件名+功能说明+[作者]+[版本声明]+[日期]

自定义函数的接口;功能,入口参数,出口参数,返回值;


递归

普通递归:函数返回之后还要再做一次运算。

尾递归tail recursion:无需再一级一级返回,最后一个函数的结果即可得出要求的结果。


变量的作用域

1.局部变量(在动态存储区中分配内存

块内定义的局部变量,作用域只在块内;如果块是for语句,则for(;;;)括号内不属于块内;

2.全局变量(在静态存储区中分配内存

从定义的位置到程序结束;

全局变量在定义时,若未初始化,会被编译器自动初始化为0

3.同名时

局部变量隐藏全局变量。

作用域小的局部变量隐藏作用域大的局部变量

4.auto自动局部变量和static静态局部变量

生命周期不同,本质为内存分配区域不一样

static静态局部变量,静态存储区分配内存,只被初始化一次,作用域不变,生命周期为整个程序;

auto自动变量的生命周期和作用域一致;

  全局的static和auto,作用域不同;



数组

1.memset函数,在string.h头文件中。memset(a,0,sizeof(a)),将数组置零。

2.memcpy(b,a,sizeof(a));将数组a的内容赋值给b,要求数组a和数组b大小一样。

3.二维数组定义初始化时,第一个下标可省,第二个下标不可省。初始化时可用花括号指定出缺省的行数。

4.二维数组与指针:

a[2][3],a为二维数组首地址,也为第0行地址

a+i为第i行地址、第i行首元素的地址

*(a+i)为第i行首元素的地址

*(a+i)+j第i行第j列元素的地址。

*(*(a+i)+j)i行j列元素的值,等价于a[i][j]


main()函数:

完整形式: int main(int argc, char * argv())

argc : 命令行参数的数量(包括程序名本身)

argv :字符指针数组,每个元素指向一个参数;故,argv[0]指向程序名。


文件:数据的集合;

文件的分类:

按文件的逻辑结构:无结构与有结构,见收藏。

文件的打开:

FILE *fopen( const char *filename, const char *mode);

// 返回指向此文件的指针,若打开失败(文件损坏或不存在),则返回NULL;

如: 

FILE *fp;

fp = fopen("test,txt", "r" ) ;  // 文件名可包含路径,也可以不,不包含则表示其为当前目录下的文件。

  // "D:\\project\\test.txt"

if(fp) // 必须检查是否正确打开。

模式:

r      以只读方式打开文件,该文件必须存在。        
r+    以读/写方式打开文件,该文件必须存在。        
rt+   以读/写方式打开一个文本文件,允许读和写。        
rb+  以读/写方式打开一个二进制文件,只允许读/写数据。       
w     打开只写文件,若文件存在则长度清为0,即该文件内容消失,若不存在则创建该文件。               
w+   打开可读/写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。       
wt+  以读/写方式打开或建立一个文本文件,允许读写。       
wb   以只写方式打开或新建一个二进制文件,只允许写数据。         
wb+ 以读/写方式打开或建立一个二进制文件,允许读和写。       
a         以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留(EOF符保留)。
a+        以附加方式打开可读/写的文件。若文件不存在,则会建立该文件,如果文件存在,则写入的数据会被加到文件尾后,即文件原先的内容会被保留(原来的EOF符 不保留)。
at+   以读/写方式打开一个文本文件,允许读或在文本末追加数据。      
ab+  以读/写方式打开一个二进制文件,允许读或在文件末追加数据。      


文件的关闭:

int fclose ( FILE *fp ); // 成功返回0,失败返回非零值;

按格式读写文件:

int fscanf ( FILE * stream, const format , [argument...] ); // 文件指针;格式化字符串;输入列表

   // fscanf(stdin,...)等价于scanf();

     按格式写文件:

int fprintf ( FILE * stream,  const *format , [argument] );

// fprintf(stdout,...)等价于printf()

将文件指针置回首部:

fseek(FILE * stream,)

按字符读写文件:

int putc( int c , FILE * fp );

int fputc(int c, FILE *fp ); //向fp中写入一个字符

int getc( FILR *fp ) ;

int fgetc(FILR *fp );`// 从fp中读出一个字符并将位置指针指向下一个字符;若读成功,则返回该字符,否则  返回EOF通常为-1;即返回EOF可能读取错误也可以能读到文件尾部。

判断是否到达文件尾:

int feof(FILE *fp); // 到达文件末尾则返回非零值,不到则返回0;while(!feof(FILE *fp));

返回文件指针的位置:

long ftell ( FILE * fp) ;

判断是否读取出错:

int ferror(FILR * fp ) ; // 出错则返回非0值,否则返回0;


按行读写文件:

int fputs (char * s, FILR *fp ) ; //失败返回0;不同于puts。不会自动添加换行符。

char * fgets( char *s , int n, FILR * fp) ; //n为缓冲区大小,即最多读取n-1个字符;都会在字符串末尾添加'\0',但如果文件中的此行以换行符结束,则会将换行符也读入到字符串末尾再添加'\0';读取成功返回字符串首地址,失败或到末尾则返回EOF;gets不保留'\n',用\0取代;fgets保留且也添加\0

                用fgets( buf, sizeof(buf), stdin)取代gets(buf)

按数据块读写文件:

数据块是一个抽象概念,可以是一个数组,也可以是数组的一个元素;可以是一个结构体;

读:

size_t fread ( void *buffer , size_t size , size_t count , FILE * stream); 

// buffer:从文件指针所指向的文件中读取数据块并存储到buffer指向的内存;即数据块首地址。

   size : 每个数据块的大小,单位为字节;

   count : 读入数据块的个数

   返回实际读入的数据块个数,正确时大小等于count;到达文件末尾或出现错误则不等于count;


写:

size_t fwrite ( const void * buffer , size_ t size, size_t count, FILE * stream ) ;

// 将buffer所指向的内存中的数据块写入fp所指的文件,buffer时数据块的首地址;

   size为每个数据块的大小;count为数据块的数量;返回实际写入的数据块的个数,成功则等于count;

文件的随机读写:

函数:

void rewind( FILE * fp ) ; // 使文件位置指针重新指向文件的开始位置。

long ftell ( FILE * fp );// 返回当前指针所指位置的偏移量

    int fseek ( FILE *fp , long offset , int fromwhere ) ; 

//改变文件位置指针,实现随机读写。 

注意offset必须为long类型,若为其他类型须强制转换,常量则后缀加L。

   fromwhere有三个值SEEK_SET或0,表示文件开始的位置。

   SEEK_CUR或1,表示文件的当前位置。

   SEEK_END或2,表示文件的末尾位置。


动态内存分配:

分配:

void * malloc(unsigned int size);  //分配size大小的内存空间

      void * calloc( unsigned int num, unsigned int size ) ; // 分配num个size大小的内存空间;与malloc不同,会将    分配的地址初始化为0。

      void * realloc( void *p, unsigned int size);  // 改变原来分配的存储空间的大小;将p所指向的存储空间的大小    改为size个字节,返回值为新分配的存储空间的首地址。

      void *使用时需使用强制类型转换(Type*)

      释放:

void free(void * p ); // 释放由malloc和calloc申请的内存块,p为指向这块内存的指针;free时系统将此  块内存标记为未占用,可被重新分配。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值