头文件<stdio.h> :
一, printf(输出函数)
2.可以限定小数位数 用%.nf(n为一个数字)来限定
限定字符串长度同理用%.nf
3.你不想打印时(即打印空格)
这样子是可以的printf(" ");
4.printf里头打印表达式是一个很好用的技巧
不要只会去想把一个结果放到一个参数里去
当这个结果是多变的时这个参数就很难去定义了
二,
scanf(输入函数)
1.在变量前要取地址“&”(指针,数组本身就有地址)
&这个事情老是忘记
注意:scanf输入字符时遇到空格会结束
2.在格式上一定要保持好对映 你vs那边是啥 在输入时就要怎么对映
注意 : scanf的占位符那边是不能乱搞东西的。不然啥都输入不了.
老是犯这种错误
3.在用%c时打印不会跳过空格
%c只打印一个因为检查到有空格(又不自动跳过)所以会打出一个空格
4.在有scanf的情况下对应的变量初始化时没有什么作用的(仅符合语法)
ex char ch=0;这就没啥用 ( 因为后面要再进行手动输入赋值)
5.注意scanf不需要在百分号后换行
不然下一行依然是输入
6.若要用scanf进行一个多组输入
使用while(sacnf("%d ", &d)!=EOF)
调试中输入三个ctrl+z后循环结束
7.误区sacnf与指针
这里p是指针变量,为何不要解引用输入呢
有没有一种可能scanf就是要对着地址输入哈哈
三,
gets(补充scanf遇到空格就结束的缺点)
char * gets(char * ptr)
特点: gets用于输入一串字符(gets遇到换行符\n才终止)
返回值:若读到了字符则返回char*类型,若没读到字符则返回null
因此,类比得出它的多组输入方法:
对比:getchar是一个一个字符读的,而gets是一串字符串
四,fopen(打开文件函数)
FILE * fopen ( const char * filename, const char * mode );
参数一:filename,文件名
参数二:打开方式
特别的: 该函数返回 FILE指针类型,要相对应的变量接收
该函数返回一个 FILE 指针。否则返回 NULL,且设置全局变量 errno 来标识错误。
易错:不要把文件的路径搞错了,创造错了(一般是鼠标右击去创造文件)
五,perror(打印错误信息函数);
void perror ( const char * str );
用法:在第一个参数之后再打印一个冒号和空格,直接打印错误码信息(strerror)
这个函数一般配合malloc使用.
头文件<string.h>:
一, strlen(计算string函数)
size_t strlen ( const char * str );
作用: 计算字符串长度(strlen的宗旨是死命找\0);
注意:strlen的参数是指针型的所以不要传一个非地址的参数,否则系统会崩掉
注意:strlen一遇到遇到\0会歇菜的(ex:strlen(I love you)=1 有空格在搞怪 )
但是,strlen没有遇到\0之前,是不会停下来的(这也是strlen容易越界访问
的原因)其实这是scanf遇到空格自动停止的锅,用gets函数解决即可。
注意:在字符串中时strlen不记录\0,但signof计算\0,应为\0本来就占一个字符是字符
串数组中的一部分( char str[3] = { "abc" } , 这样初始化是错的str数组放
不下)
注意: sizeof(数组名) 数组名表示整个数组 ,的前提条件是“( )”里面只有数组
ex:sizeof( arr + 0 ) , 这里的arr表示首元素地址
二,strcpy(string copy ,拷贝函数 )
char * strcpy ( char * destination, const char * source );
作用将字符串source拷贝到destination
注意:源字符串必须要以 \0 结尾
目标空间足够(不然可能越界)且可修改
返回char*类型的是destination的原地址其实是为了原地址不变
strcpy会把‘\0’复制过去,因为“\0”看起来destination被完全覆盖而已
变式:strncpy( strncpy n copy )函数就是加了一个参数拷贝n个字符过去
(更精准)
三,strcat (Strings Catenate(横向链接),追加函数 )
char * strcpy ( char * destination, const char * source );
注意:两个字符都要 \0 结尾
目标空间足够大且可以修改
最好不要自己追加自己(只有一种字符串可能造成\0丢失)
返回char * 类型的原因同上
变式:strncat(Strings n Catenate(横向链接) )函数, n的作用同上
不同点是strncat在追加结束后会自动补加一个 \0
因此自己追加自己用这个函数
四,strcmp(string cmpare , 比较函数)
int strcmp ( const char * str1, const char * str2 );
作用:比较两个字符串的大小
比较方式 :{
对应字符串的ASCII值的大小比较 (并不是比较字符串长度)
什么叫做对应? Ex :str 1 = ”abcdef“
str 2 = " abp "
a = a ,b = b, p>c ∴ str 2 > str 1
}
返回值:
a>b return 的value > 0
a=b return 的value = 0
a>b return 的value < 0
这个和qsort函数的返回值好像,所以 ,qsort函数和strcmp函数是一队好搭档
变式:strncmp , 原理同上
六,strstr( 查找 函数 )
char * strstr ( const char * str1, const char * str2 );
value:返回str2第一次在str1出现的位置.
七,strtok(拥有分隔特殊标记的函数)
char * strtok ( char * str, const char * delimiters(自定义分隔符) );
作用:strtok函数回查找str字符串中的分隔符,用\0结尾并且返回该分隔符的地址
所以第一次找到分隔符后若成功返回空指针
为了避免死循环(让strtok找下一个分隔符),循环第二次进入函数是要传这
个返回的空指针的地址(从这个已经被改为\0的分隔符开始往下找)
即传入( NULL , const char * delimiters(自定义分隔符) );
注意:一个字符串中可能包含多个分隔符(192.168.3.111)所以可能要用循环搭配
strtok函数
注意:strtok函数回改变被操作的字符串因此一般strtok使用函数之前要创建临时拷
贝
注意:分隔符他是一个字符(char型),但是函数需要传地址(即char * 类型)
所以把分隔符定义为char * 类型的
char * 的字符串不是这样写的 ,这只是一个分隔符
八,strerror(错误码函数)
char * strerror ( int errnum );
错误码函数参数是int类型的原因:
程序启动时系统全局变量:errno的值为零,表示没有错误
当发生错误时错误码的数字为非零数每个错误码(1,2,3,4,5,6)都有对应
的错误提示 这时strerror函数返回char * 类型
注意:每个错误码对应的信息已被系统定义 :使用时包含 errno.h
注意:常错:这个全局变量是errno 不是 error
九,memcpy( memory copy )内存拷贝函数
void * memcpy ( void * destination, const void * source, size_t num );
作用:从源头source开始向后复制n个字节(即参数num的单位)到目的地destnation
注意:使用memcpy时 两个参数不能有重叠(因为是一个一个数据搞过去,重叠可能
导致数据丢失)
memcpy在拷贝数据的时候用的比较多
有些memcpy能无bug仍然能完成是因为“库”中实现的太好了,但是最好不要用
memcpy拷贝重叠参数,我们引出了memmove函数
十,memmove函数(memory move)内存移动函数
作用:一般的memmove 函数可以说是memory的上位替代品。
十一,memset函数( memory set ) 内存设置函数
void * memset ( void * ptr, int value, size_t num );
作用:将内存中的东西(第一个参数)以字节为单位设置成想要的内容(第二个参
数)
非char类型怎么用这个东西的我不是很清楚
十二,memcmp函数( memory cmpare )内存比较函数
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
比较长度:两个参数指针指向的位置开始到向后的num字符
头文件< stdlib.h>:
一,rand(生成随机值的函数)
int rand (void);
1,随机数的范围是0~32767(可以用求模运算符调整)
2,rand是伪随机数种子植默认为=1
3, 是令一个数接收这个随机值 ,而不是直接就把rand()当成随机数
ex int x =rand( ) 不是int rand( )【这是函数不是数】
二,srand(定义种子值的函数): 包含头文件 “<stdlib.h>”
void srand (unsigned int seed);
srand常用的是:srand((unsigned int)time(null) )){这是要强制转化类型}
1.要让种子值变化,但变化不是随机的变化
ex时间这种有规律的变化
2.srand是unsigned int 类型所以要经常用“()”进行强制转化
3.这个设定种子值一定要在rand的前面
srand((unsigned int)time(NULL));
int x = rand() % 100;
注意:rand函数和srand函数一定要同时使用才能得到真正的随机数
三, system函数
int system (const char* command);
在system();字符指针型参数的不同其也作用不同
1.“cls”时清屏指令。
四,qsort函数
void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
注意: ( size_t :是无符号整形 )
作用:是以快速排序排列任意的类型(qsort函数的内部),qsort函数可以用来替换排序
1. 参数base是数组名,因为要排列任意类型因此由void * 指针类型接收数组的参数
2. 参数num是待排列数组的元素个数
3. 参数size是数组中每个元素的大小 ex:sizeof(arr[0]),sizeof(int)
size元素大小(宽度)的定义太重要了,在qsort内部,获取任意类型地址,
任意类型交换(ex,char类型交换)都要用宽度来实现
注意:谈到任意这两个字:char类型就有话要说了,只有char类型"+1才是+1,+n才
是+n”
4. 参数int (*compar)(const void*,const void*)是一个函数指针变量类型
因为要排列任意类型因此由void * 指针类型接收 ,数组内元素的参数
这个函数指针变量类型会指向一个自定义函数,通过这个自定义函数的返回值来决定 是否要进行排序( qsort 函数默认是升序,想要降序通过改变a,b的位置把函数的value值倒置就可以了 )
5.qsort函数排序结构体,应当明确排序标准(ex以name排序,以age排序)
若如此做那么传的函数地址也就不一样了
a>b return 的value > 0
a=b return 的value = 0
a>b return 的value < 0
然后把value传入qsort函数内部去决定是否进行交换
注意:qsort函数的参数都和数组有关系所以,要用qsort排序无论是什么类型必须得是数组才行
五,malloc(自己开辟空间)函数
void * malloc (size_t size);
作用:开辟size大小字节的参数
开辟:
1.成功,返回一个指向该空间的地址。
2.失败,返回空指针。(所以为了安全起见,要检查malloc的返回值)
注意:malloc返回的是void * 类型所以在用自定义指针变量接收返回值时需要
强制类型转化 ex : int * p = ( int*) malloc ( 20 * sizeof(int) );
图:看,联动perror函数异常返回值。
六,calloc(malloc的变式)函数
void* malloc (size_t size);
作用:为num个大小为size的元素开辟一块空间
特别的:在开辟完这个空间后会自动把它们初始化为零
七,realloc(repeat alloc ) 重新分配函数
void* realloc (void* ptr, size_t size);
参数:
ptr是要调整的地址(只能是动态函数申请的内存)
size是调整之后的空间大小
value:
1.调整失败返回NULL
2.调整成功,且后面内存够用,直接扩大返回原地址
3.调整成功,但后面内存不够用,重新找一个足够的大空间
把旧数据拷贝到新的空间,并释放旧空间,返回新空间起始地址
八 ,free(动态内存释放)函数
作用范围:动态函数申请的内存 (我犯过一个大错误,图)
为什么要存在这个函数:动态函数申请的内存,系统以后都用不了,在指向这个内
存的变量被销毁后,这些动态函数申请的内存就浪费了,
这就是:内存泄漏 ,机器的内存将会越来越小。
所以:malloc/calloc/realloc 和free 总是一起出现的
注意:
p的内存使用权已经还给系统,p存的值已经被置成随机值,但是p还是指向原地
址(要防止p以后可能成为野指针)
相关知识:不要以为牵扯了地址就是传址调用 ,图一为传值调用(形参实参均
为char *类型) ,图二为传址调用(二级指针)。
小结 : 一般带了&符号的肯定是传址调用了(数组是一个例外,它不带也是传地调用)
图二漏了一个&操作符,应该是test(&a)
九, exit(暴力结束程序 )函数
void exit(int x)
参数: 当x为零,则正常退出,若不为零则异常退出
作用: 暴力退出结束程序
十,abs(绝对值)函数
int abs (int n);
作用:求n的绝对值。
头文件<math.h>:
一,pow(求N次方)函数
double pow (double a, double b);
value: a的b次方
注意:由于pow函数返回double类型,因此它经常要强制类型转化
二,sqrt(算术平方根)函数
double sqrt (double x)
sqrt函数只有开根号的作用,因此只有一个参数
三,floor(抹零)函数
double floor (double x)
value:floor函数会返回不超过x的最大整数,因此floor函数(x+0.5)用在要四舍五入
的场景
穿插知识: 强制类型转化,也可以有 x+0.5的作用.
四,fmax(返回最大值)函数
double fmax (double x , double y);
float fmaxf (float x , float y);
long double fmaxl (long double x, long double y);
作用:返回x和y中的最大值
注意:变量为int时注意强制类型转化。
头文件<windows.h>:
一,Sleep(放慢)函数
unsigned int sleep(unsigned int seconds);
作用 :表示让程序暂停单位ms(s要大写)
头文件<time.h>:
一,time(在程序中经常作为种子):包含头文件 “<time.h>“
1.关于time的指针请看书(复杂)
二,clock(计算时间)函数
clock_t clock(void)
作用:计算程序现在所用时间
用法:clock / CLOCKS_PER_SEC单位是秒( #define CLOCKS_PER_SEC 1000 )
默认单位是毫秒。
注意:由于clock函数返回陌生的类型所以,在使用时经常强制类型转化
注意:要计算某个语句的函数,用两个clock把他俩夹起来即可,最后两个时间相减
头文件<assert.h>:
一 , assert(断言函数)
宏assert(){ 宏是用来替换的 }
assert会被真假值替换(有点像if语句)
assert也要乱用,一般用于大判断
笔记不好做看书(深入指针一)
作用范围:在window操作系统下,assert只在debug版本起作用
(若在dubug { #define NDEBUG } assert也会失效 )
在linux操作系统下,assert还会在realse版本起作用
注意:
和循环不同,assert为真才不报错,循环为假才退出
别写循环写多了把assert忘了
头文件<ctype.h>:
一, islower(判断小写字母)函数
int islower ( int c )
返回值:是:返回非零,不是:返回零。
二, isupper(判断大写字母)函数
int isupper ( int c )
返回值:是:返回非零,不是:返回零。
三,isspace(判断空格)函数
int isspace ( int c )
返回值:上同
作用: 可以用来删除多余空格
例:
四, isdigit(判断是否是10进制数字)函数
int isdigit ( int c );
返回值上同:
相关知识:
ASCII值与整数值的转化:
打印 :要打印ASCII码值还是整数关键看占位符是%c,还是%d
转换公式: 整数 + ‘0’ = 字符