标签:简单 获取 缓冲区 return mic 字符串处理 strong 算法 strcmp
1. 字符串输入
(1)gets stdio.h
不安全的函数
char buf[20] = {0}; gets(buf);
从标准输入获取一个字符串到s,遇到换行符就结束(不包括换行符,并在最后添加‘\0‘,然后存到s)
(2)fgets stdio.h
更安全的字符串输入
最多读入size-1个字符串,还留了位置给‘\0‘
fgets会将换行符读入 因此行8有必要
返回值就是s指向缓冲区的地址
1 #include <stdio.h> 2 #include <string.h> 3 4 int main () 5 { 6 char buf[20] = {0}; 7 char *s = fgets(buf,20,stdin); 8 buf[strlen(buf)-1] = ‘\0‘; 9 printf("**%s**",s); 10 return 0; 11 }
(3)fgetc stdio.h
读取一个字符,返回一个unsigned char
1 char c = fgetc(stdin); //输入 ‘a‘ 2 printf("**%c %d**",c,c); //输入 ‘a‘ 97
(4)getchar stdio.h
2. 字符串输出
(1)fputs
将s所指字符串输出到stream,不在最后添加换行符
(2)puts
输出s所指向的字符串到标准输出,并自动添加一个换行符
1 char buf[20] = {"**abc**"}; 2 puts(buf);
gets不保存换行符,puts自动添加换行符
fgets保存换行符,fputs不自动添加换行符
(3)fgetc stdio.h
输出一个字符到stream
3. 字符串处理函数 <string.h> ANSI C
(1)字符串长度
返回不包括结尾的‘\0‘的字符串长度,单位字节
简单实现v1:
1 size_t my_strlen(const char *s) 2 { 3 assert(s != NULL); 4 size_t len = 0; 5 while(*(s++) != ‘\0‘) { 6 ++len; 7 } 8 return len; 9 }
简单实现v2:
1 size_t my_strlen(const char *s) 2 { 3 assert(s != NULL); 4 const char *pstr = s; 5 while(*(pstr++) != ‘\0‘); 6 return pstr-s-1; 7 }
(2)字符串追加
strcat的实现:
1 char *my_strcat(char *dest,const char *src) 2 { 3 assert((dest != NULL) && (src != NULL)); 4 char *tmp = dest; 5 while(*tmp != ‘\0‘) { 6 ++tmp; 7 } 8 while((*tmp++ = *src++) != ‘\0‘); 9 return dest; 10 }
strncat:从src追加字符到dest后面,直到追加了 n个字符(n个字符不包括需要追加的‘\0‘,因此src需要再能容纳n+1个字符的空间)或者src结束了为止
情况①:追加了n个字符,而src很长因此没到src的结尾‘\0‘处
情况②:追加了n个字符,刚好src到了结尾‘\0‘处,即src有n个字符再加一个‘\0‘字符
情况③:只追加了少于n个字符,src就到结尾了,对于这种情况,需要记得在dest结尾添加‘\0‘ 行10~12
1 char *my_strncat(char *dest,const char *src,size_t n) 2 { 3 assert((dest != NULL) && (src != NULL)); 4 int num = 0; 5 char *tmp = dest; 6 while(*tmp != ‘\0‘) { 7 ++tmp; 8 } 9 while((num++<n)&&(*tmp++ = *src++) != ‘\0‘); 10 if(*(tmp-1) != ‘\0‘) { 11 *tmp = ‘\0‘; 12 } 13 return dest; 14 }
(3)字符串比较大小
①strcmp:按ASCII比较大小("abc" < "abcd")
1 int my_strcmp(const char* s1,const char* s2) 2 { 3 assert(s1 != NULL && s2 != NULL); 4 while(*s1 == *s2) { 5 if(*s1 == ‘\0‘) { 6 return 0; 7 } 8 ++s1; 9 ++s2; 10 } 11 return ((*s1>*s2)?1:-1); 12 }
②glibc 2.23的strcmp实现
感觉还没有上面的直观
1 int my_strcmp2(const char *s1,const char *s2) 2 { 3 assert(s1 != NULL && s2 != NULL); 4 const unsigned char *p1 = (const unsigned char *)s1; 5 const unsigned char *p2 = (const unsigned char *)s2; 6 unsigned char c1,c2; 7 do { 8 c1 = (unsigned char)*(p1++); 9 c2 = (unsigned char)*(p2++); 10 if(c1 == ‘\0‘ || c2 == ‘\0‘) { 11 return c1 - c2; 12 } 13 }while(c1 == c2); 14 return (c1-c2); 15 }
③strncmp
v1:类似①的写法,在while里加入条件
1 int my_strncmp(const char *s1,const char *s2,size_t size) 2 { 3 assert(s1 != NULL && s2 != NULL && size > 0); 4 while((*s1 == *s2)&&(--size > 0)) { //--size的原因,在这里只比较size-1个字符,最后一个字符在最后的renturn里比较 5 if(*s1 == ‘\0‘) { 6 return 0; 7 } 8 ++s1; 9 ++s2; 10 } 11 //要么是*s1!=*s2,要么是size到0了 12 return (*s1 - *s2); 13 }
v2:感觉差不多,可能有bug
1 int my_strncmp2(const char *s1,const char *s2,size_t size) 2 { 3 assert(s1 != NULL && s2 != NULL && size > 0); 4 while(--size>0) { 5 if(*s1 == ‘\0‘ || *s1 != *s2) { 6 return (*s1 - *s2); 7 } 8 ++s1; 9 ++s2; 10 } 11 return (*s1 - *s2); 12 }
(4)字符串复制
①strcpy
类似于strcat,只是少了找dest结尾‘\0‘的环节,直接从dest一开始存储
1 char *my_strcpy(char *dest,const char *src) 2 { 3 assert((dest != NULL) && (src != NULL)); 4 char *tmp = dest; 5 while((*tmp++ = *src++) != ‘\0‘); 6 return dest; 7 }
glibc里面:直接调用memcpy(dest,src,strlen(src)+1)
②strncpy
一样,类似strncat,少了找dest结尾的环节
1 char *my_strncpy(char *dest,const char *src,size_t n) 2 { 3 assert((dest != NULL) && (src != NULL)); 4 int num = 0; 5 char *tmp = dest; 6 while((num++<n)&&(*tmp++ = *src++) != ‘\0‘); 7 if(*(tmp-1) != ‘\0‘) { 8 *tmp = ‘\0‘; 9 } 10 return dest; 11 }
glibc先调用memset将dest后面设为‘\0‘,再调用memcpy复制src字符过去
(5)字符串查找
①查找字符在字符串中第一次出现的位置
②查找字符在字符串中最后一次出现的位置
③查找字符串在字符串中第一次出现的位置------(KMP匹配算法)
④查找字符串中任意一个字符在另一个字符串中第一次出现的位置
4. stdio里的字符串操作
(1)输出到字符串(实际是字符数组)
类似C++的string流里面的ostringstream类(可将各种格式如整型数字、浮点写到字符串保存)
(2)从字符串读
类似C++的string流里面的istringstream类(可将字符串里的格式化数据如整型数字、浮点等读出来存到整型、浮点型变量,即实现字符串转数字)
简单例子:
1 char buf[20] = {"123 3.14"}; 2 int a = 0; 3 double b = 0.0; 4 sscanf(buf,"%d %lf",&a,&b); 5 printf("a:%d\nb:%lf\n",a,b); //输出 123 3.140000
tips:printf、scanf还有输出到文件流、从文件流读的相应的函数(C++有ifstream从文件流读、有ofstream向文件流写)
5. stdlib里面的字符串操作
(1)字符串转数字
6. 其它
标签:简单 获取 缓冲区 return mic 字符串处理 strong 算法 strcmp
原文地址:https://www.cnblogs.com/taoXiang/p/12521543.html