C风格字符串----字符串的常见问题
本文包含字符串包含问题(isSubstr)、字符串转化为整数(atoi)、统计词频问题(Wordcount)、字符串反转(Reverse)。字符串去除空格等
一:字符串包含问题(isSubstr)
思路:本程序采用最简单的方法;
1、遍历源字符串,当子字符串的首字符与遍历到的字符相同时,就遍历字符串。
2、遍历子字符串时,如果遇到不相等,跳出子循环,源字符串的位置++;
3、若子循环遍历的长度恰好等于子字符串,那么原串包含子串,返回true。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include "assert.h" 5 6 //时间复杂度为O(lensub*(lens-lensub+1)) 7 int isSub(const char *str, const char*strsub) 8 { 9 assert(str != NULL && strsub != NULL); 10 11 int lens =strlen(str); 12 int lensub = strlen( strsub); 13 //若原串的长度不及子串的长度,则直接返回 14 if( lens < lensub) 15 return 0; 16 17 int i,j ;//自增量 18 for( i= 0; i <=lens- lensub; ++i)//循环次数 19 { 20 for( j =0; j < lensub; ++j) 21 if( str[i+j] != strsub[j]) 22 break; 23 if( j == lensub) 24 return 1; 25 } 26 return 0; 27 } 28 29 //测试用例最好多考虑几种情况 30 int main(int argc, char const *argv[]) 31 { 32 char s[] = "helloworld"; 33 char sub[] = "wo"; 34 35 printf("%d\n", isSub(s, sub)); 36 return 0; 37 }
二:字符串转化为整数(atoi)
思路:依次遍历字符串,主要的执行语句:sum = sum*10 +'ch'-'0'
注意:
0、判断传入的参数是否为空;
1、返回值的长度问题,本程序返回值用 long long类型;
2、字符串的第一个字符有可能是‘+’,‘-’,因此要判断正负值问题;
3、转换时,如果遇到非法字符,则直接返回0;
1 #include <stdio.h> 2 #include <iostream> 3 #include <string> 4 #include <limits> 5 using namespace std; 6 7 long long aToi(const char *str) 8 { 9 if(str == NULL) 10 return 0; 11 long long num = 0; 12 13 const char *digit = str; 14 int flag =0; //标记正负 15 if( *digit == '-') //首位元素值得情况 16 flag = 1; 17 else if( *digit == '+') 18 flag =0; 19 else if( *digit >='0' && *digit <='9') 20 num = *digit - '0'; 21 else 22 return 0; 23 digit ++; 24 25 while( *digit != '\0') 26 { 27 if( *digit >='0' && *digit <='9') 28 { 29 num = num*10 + *digit - '0'; 30 if( num > std::numeric_limits<int>::max()) 31 { 32 num = 0 ; 33 return num; 34 } 35 digit ++; 36 }else 37 { 38 num = 0 ; 39 return num; 40 } 41 } 42 43 if( flag == 1) 44 return 0-num; 45 return num; 46 } 47 48 int main(int argc, char const *argv[]) 49 { 50 char s[]="254436"; //正常 51 printf("%lld\n",aToi(s)); 52 53 char t[]="+254436"; //正常 54 printf("%lld\n",aToi(t)); 55 56 char t1[]="-254436"; //正常 57 printf("%lld\n",aToi(t1)); 58 59 char t2[]="2544323436"; //溢出问题 -0 60 printf("%lld\n",aToi(t2)); 61 62 char s1[]="25i436"; //非法字符 63 printf("%lld\n",aToi(s1)); 64 65 char s2[]="";//空 66 printf("%lld\n",aToi(s2)); 67 68 char s3[]=" ";//非法字符 69 printf("%lld\n",aToi(s3)); 70 return 0; 71 }
三:统计词频问题(Wordcount)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <assert.h> 4 5 int WordCount( const char *str) 6 { 7 assert( str != NULL); 8 9 const char *strb = str; 10 const char *stre = str; 11 12 int count =0; 13 while( *strb != '\0') 14 { 15 while( *strb ==' ') //排除前面的空格 16 strb ++; 17 if( *strb == '\0')//如果全部空格,直接退出 18 break; 19 20 stre = strb; //此时*strb一定不是空格,故count++ 21 count ++; 22 while( *stre !=' ' && *stre != '\0')// stre开始往后移, 23 stre++; 24 strb = stre; 25 } 26 return count ; 27 } 28 29 int main(int argc, char const *argv[]) 30 { 31 char s[] = " hello, this is a C program!! "; 32 printf("%d\n", WordCount(s)); 33 34 char s1[] = " "; //全是空格 35 printf("%d\n", WordCount(s1)); 36 return 0; 37 }
四:字符串反转(Reverse)、、
思路:
1、先将源字符串反转一遍;
2、再将单个单词反转,即可。
3、反转单词时,跳过空格。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include "assert.h" 5 6 void ReverseSub(char *left, char *right) 7 { 8 assert( left != NULL && right != NULL); 9 while( left < right) 10 { 11 char tmp = *left; 12 *left = *right; 13 *right = tmp; 14 ++left; 15 --right; 16 } 17 } 18 19 char *Reverse(char *str) 20 { 21 if( str == NULL) 22 return ; 23 if( strlen(str) == 1) 24 return; 25 char *ptrb = str; 26 char *ptre = str; 27 //走到末尾 28 while( *ptre != '\0') 29 ++ptre; 30 31 ReverseSub(ptrb, --ptre); //去掉'\0' 32 33 ptrb = ptre = str; 34 while( *ptrb != '\0') //一个字符一个字符的走 35 { 36 if( *ptrb == ' ') //走完前面的空格 37 { 38 ++ptrb; 39 ++ptre; 40 continue; 41 } 42 //反转单词 43 else if( *ptre == ' ' || *ptre == '\0') //此时*ptrb是一个字符 44 { 45 ReverseSub(ptrb, --ptre); 46 ptrb = ++ptre; 47 } 48 else 49 ptre ++; 50 } 51 return str; 52 } 53 54 int main(int argc, char const *argv[]) 55 { 56 char str[] = " hello, world, thank you! "; 57 printf("original:%s\n", str); 58 printf("reversed:%s\n",Reverse(str)); 59 60 char str1[] = " "; 61 printf("original:%s\n", str1); 62 printf("reversed:%s\n",Reverse(str1)); 63 return 0; 64 }
五:字符串去除空格
1、先去除头部空格;
2、再去除尾部空格;
3、最后去除中间空格
一)去除中间空格做法:当遇到空格时,直接跳过;
二)这样,我们跳过的空格数的取值可能为0、1、2·····
三)判断当前非空格字符的前两个字符是否为空格;
若都为空格,我们写入一个空格;
若只是一个空格,直接写入串中;
对于不是空格的字符,直接写入串中即可。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include "assert.h" 5 6 char *trimSpace( char * str) 7 { 8 if( str == NULL) 9 return; 10 11 int i = 0; //用于写字符 12 char j = 0;//用于遍历字符 13 14 while( str[j] == ' ') //移除前面的空格 15 j++; 16 17 int lens = strlen( str ); 18 while( str[--lens] == ' ') ; //移除后面的空格 19 str[++lens] = '\0'; //封装 20 21 while( str[j] != '\0') 22 { 23 //移除中间的空格 24 while( str[j] == ' ') 25 j++; 26 //连续两个空格,表明需要移除 27 if( str[j-1]==' ' && str[j-2] ==' ' && i!= 0 ) //考虑情况:头部连续超过两个空格,若没有i!=0;接下来的语句就会写一个空格 28 str[i++] = ' '; 29 str[i++] = str[j++]; 30 } 31 str[i] = '\0'; 32 return str; 33 } 34 35 int main(int argc, char const *argv[]) 36 { 37 char str[] = " hel l0 "; 38 printf("original:%s\n", str); 39 printf("trimSpaced:%s\n",trimSpace(str)); 40 41 return 0; 42 }
六:移位包含问题:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> //移位包含问题。解决方法: //一:对于原串s1,可连接s1与自身得到s1s1,遍历s1s1查看是否包含另外一个穿 //二:在指针指向s1末尾元素时,下一步重新回到s1头元素 int shift_contain_str(const char *const Src, const char *const Des) { assert(Src != NULL && Des != NULL); int lenS = strlen( Src); int lenD = strlen( Des); if( lenS < lenD) return 0; int i = 0;//遍历字符串 for ( i = 0; i < lenS; ++i) { int k = i; int j; for (j= 0; j < lenD; ++j) { if(Src[k++%lenS] != Des[j]) break; } if( k - i == lenD)//k -i 代表 内层for循环执行的次数 return 1; } return 0; } int main(int argc, char const *argv[]) { int ret; char Src[]= "hello"; char Des[] ="ol"; char Des1[] = "elloh"; ret = shift_contain_str(Src, Des); printf("ret: %d\n", ret); printf("ret:%d\n",shift_contain_str(Src, Des1)); return 0; }