参考书籍:
计算机考研复试上机指导全书.天勤计算机考研系列.孙肇博 张飞飞.2014.01
C语言库函数
stdio.h
- sscanf()
从已知字符串buffer中获取与指定格式相符的数据,函数原型如下:
示例:int sscanf(const char *buffer, const char *format, ...);
输出结果:#include <stdio.h> int main() { char buf[] = "2019,w:c:b"; int a; char b,c,d; sscanf(buf,"%d,%c:%c:%c",&a,&b,&c,&d); printf("%d_%c_%c_%c",a,b,c,d); return 0; }
此函数可以用来将字符串类型表示的数据,转换为其他类型。2019_w_c_b
- sprintf()
将数据按照一定格式写入字符串,函数原型如下:
示例:int sprintf(char *buffer, const char *format, ...);
计算已知的两小数之和,并将结果的第一位小数输出
输出结果:#include <stdio.h> int main() { char buf[10]; double a = 1.23456, b = 1.23456; sprintf(buf,"%f",a+b); int i = 0; while(buf[i++] != '.'); printf("%s\n",buf); printf("%c",buf[i]); return 0; }
此函数中的buffer,包含”\0“,因此在设置数组时,数组长度要加一。2.469120 4
- ungetc()
把字符 char(一个无符号字符)推入到指定的流 stream 中,使它成为下一个被读取到的字符。函数原型如下:
示例:int ungetc(int char, FILE *stream);
输出结果:#include <stdio.h> int main() { char ch; int num; while((ch = getchar()) != '\n'){ if(ch == ' ')//过滤空格 continue; ungetc(ch,stdin);//将获取的字符ch退回到stdin流 scanf("%d",&num);//从stdin中读取数据,以int类型存入num变量 printf("_%d_ ",num); } return 0; }
该函数的作用,我比较认同以下这个说法:20 15 14 17 _20_ _15_ _14_ _17_
当从流中读出字符,但不是所需内容时,为了不改流的内容,需要回写入流中。写回后再读,仍会读出来。1
注意:
ungetc 不能连续多次调用。两次 ungetc 调用之间必须至少有一次读操作或者文件指针移动操作(fseek,rewind 等 ) ,ungetc 只影响输入流,而不影响与输入流关联的外存文件。 - freopen()
用于重定向输入输出流。该函数可以在不改变代码原貌的情况下改变输入输出环境,但使用时应当保证流是可靠的。函数原型如下:
示例:FILE *freopen(const char *fname, const char *mode, FILE *stream);
in.txt文件内容:#include <stdio.h> int main() { freopen("in.txt","r",stdin);//输入重定向,输入数据将从当前目录下的in.txt文件中读取 char ch; while((ch = getchar()) != EOF){ printf("%c",ch); } fclose(stdin);//关闭重定向输入 return 0; }
输出结果:123456wertyui
stdlib.h
- atof()
把用字符串表示的浮点数(或整数)转换为double型的数据。函数原型如下:
示例:double atof(const char *str);
输出结果:#include <stdio.h> #include <stdlib.h> int main() { char *str1 = "11.62"; char *str2 = "-11.62"; char *str3 = "11.62e-2"; char *str4 = "11.62abc1.26"; char *str5 = "a11.62"; double a,b,c,d,e; a = atof(str1); b = atof(str2); c = atof(str3); d = atof(str4); e = atof(str5); printf("%lf\n%lf\n%lf\n%lf\n%lf",a,b,c,d,e); return 0; }
注意:待转换的字符串必须是有效的整数或浮点数(正负均可)开头才能转换成功。上例中str5不是以有效数字开头,因此无法转换。11.620000 -11.620000 0.116200 11.620000 0.000000
- malloc()和free()
malloc()申请系统内存空间,申请成功返回新开辟内存空间的首地址,申请失败返回NULL。
free()释放内存空间。二者函数原型如下:
示例:void *malloc(size_t size); void free(void *ptr);
#include <stdio.h> #include <stdlib.h> int main() { struct sqlist{ int data; struct sqlist *next; }; sqlist *p; p = (sqlist *)malloc(sizeof(sqlist));//对返回值一定要进行强制类型转换,函数参数为申请的内存空间大小 //做一些操作…… free(p); return 0; }
- qsort()
快速排序,后面提及排序时具体讲解。
string.h
-
strlen()
获取字符串长度,不包括”\0“。unsigned int strlen(char *str);
示例:
#include <stdio.h> #include <string.h> int main() { char c[] = "welcome"; printf("%d",strlen(c)); return 0; }
输出结果:
7
注:strlen()是一个函数,需要进行函数调用;而sizeof()是单目运算符,在编译时计算缓冲区的长度,因此 sizeof ()不能用来返回动态分配的内存空间的大小。
实现strlen()函数功能:见”C语言:三种方法模拟实现strlen函数“2
-
strcmp()
从左往右比较str1和str2两个字符串对应位置的ASCII码值的大小。当值不同时,或遇到结束符时,返回结果。当str1 < str2时,返回负数;当str1 = str2时,返回0;当str1 > str2时,返回正数。只能用于字符串的比较,不能用于各种类型的数组比较,函数原型如下:int strcmp(const char *str1, const char *str2);
示例:
#include <stdio.h> #include <string.h> int main() { char *a = "acm"; char *b = "block"; char *c = "code"; printf("%d\n",strcmp(c,b)); printf("%d\n",strcmp(a,a)); printf("%d",strcmp(a,c)); return 0; }
输出结果:
1 0 -1
一种实现strcmp()函数功能的函数:
#include <stdio.h> int strcmp_self(const char *str1, const char *str2){ //函数传入参数为const char* ,属于有符号数 while(*str1 && *str2 && (*str1 == *str2)){ str1++; str2++; } if(*(unsigned char *)str1 > *(unsigned char *)str2) //由于该函数参数为有符号数,但字符串的ASCII码无负值 //若不转换,比较的时候会出现错误 //因此要使用unsigned char*强制转换为无符号数 return 1; else if(*(unsigned char *)str1 < *(unsigned char *)str2) return -1; else return 0; } int main() { char *a = "acm"; char *b = "block"; char *c = "code"; printf("%d\n",strcmp_self(c,b)); printf("%d\n",strcmp_self(a,a)); printf("%d",strcmp_self(a,c)); return 0; return 0; }
运行结果同上。
-
strcpy()
将以from为首地址的字符串连同’\0’,复制到以to为首地址的存储空间,只能拷贝字符串,不能用于各种类型的数组复制,原型如下:char *strcpy(char *to, const char *from);
函数实现:
#include <stdio.h> #include <assert.h> char *strcpy_self(char *to, const char *from){ assert((to != NULL) && (from != NULL)); char *ret = to; while((*ret++ = *from++) != '\0'); return to; } int main() { char a[6] = "good"; char b[6] = "bad"; //此处未使用指针形式,大家也请注意 //通过char *指针修改字符串常量中的字符会导致Segment fault错误 //原因是char *a = "good",good的存储位置是只读的内存地址 //不允许执行以下的strcpy()操作 printf("%s\t%s\n",a,b); strcpy_self(a,b); printf("%s\t%s\t",a,b); return 0; }
输出结果:
good bad bad bad
与strcpy()相似的有一个strncpy()的函数,该函数功能类似,只不过strncpy拷贝的是字符,最后一个’\0’没有拷贝,所以拷贝的时候需要对串进行清零处理,在最后加‘\0’,一定要养成好习惯。同时,使用strncpy()时,一定要防止内存重叠。其实现如下,将以src为首地址的字符串中的前n个字符拷贝到dest所指的数组中,并返回数组首地址:
#include <stdio.h> #include <assert.h> char *strncpy_self(char *dest,const char *src,int n) { assert((dest!=NULL)&&(src!=NULL)); char *cp=dest; while(n&&(*cp++=*src++)!='\0') { n--; } if(n) { while(--n) *cp++='\0'; } return dest; } int main() { char a[6] = "good"; char b[6] = "bad"; printf("%s\t%s\n",a,b); strncpy_self(a,b,2); printf("%s\t%s\t",a,b); return 0; }
-
strcat()
将以str2为首地址的字符串(包括’\0’)追加到以str1为首地址的字符串后面(删除*str1后面的’\0’),其函数原型如下:char *strcat(char *str1,const char *str2);
我一般不使用strcat(),容易把自己搞糊涂,弄不清楚字符串内容最终成为了什么,或者造成内存溢出等错误,故习惯直接在主函数中写一遍:
#include <cstdio> int main() { char a[15] = "good"; char b[15] = "bad"; printf("%s\t%s\n",a,b); //函数实现将字符数组 b 的内容追加到字符数组 a //数组 a 一定要足够大,足以放下追加的内容 int i = 0, j = 0; while(a[i++]); i--; while(b[j]){ a[i++] = b[j++]; } a[i] = '\0';//补充结束符 printf("%s\t%s\t",a,b); return 0; }
输出结果:
good bad goodbad bad ```
-
strstr()
判断字符串*str2是否是*str1的子串,返回一个指针,指向字符串*str2在字符串*str1中出现的首位置,否则返回NULL。函数原型如下:const char *strstr(const char *str1,const char *str2);
函数实现:
#include <stdio.h> #include <assert.h> const char *strstr_self(const char *str1,const char *str2){ const char *p1; const char *p2; if(!str1 || !str2) { return NULL; } //遍历str1字符串 while(*str1) { //遍历子串 p1 = str1; p2 = str2; do { if(!*p2) //到了str2的结束位置,返回str1的位置 return str1; }while(*p1++ == *p2++); str1++; } return NULL; } int main() { char a[15] = "good"; char b[15] = "ood"; printf("%s\t%s\n",a,b); const char *c = strstr_self(a,b); printf("%s",c); return 0; }
-
strtok()
用*str2中字符将*str1字符串分割,返回指针,指向分割下来的字符串首地址,若无分割下来的字符串,返回NULL。函数原型如下:char *strtok(char *str1,const char *str2);
示例:
#include <stdio.h> #include <string.h> int main() { char a[] = "see you tomorrow"; char b[] = " "; printf("%s\t%s\n",a,b); char *res = NULL; res = strtok(a,b); while(res != NULL){ //注意,第一次调用strtok()函数时,第一个参数时str1 //但是之后调用时,第一个参数要改为NULL printf("%s\n",res); res = strtok(NULL,b); } return 0; }
输出结果:
see you tomorrow see you tomorrow
-
memset()
将一段内存置为某个值,**常用!**函数原型为:void *memset(void *buffer, int ch, size_t count);
示例:
#include <stdio.h> #include <string.h> int main() { char a[] = "see you tomorrow"; printf("%s\n",a); memset(a,'b',6); //将字符串数组 a 的前6个字符置为字符'b' printf("%s\n",a); return 0; }
输出结果:
see you tomorrow bbbbbbu tomorrow
math.h
见下篇