字符串查找、错误信息、字符分类函数
创始人
2024-05-10 19:31:20
0

1、寻找子串strstr

char* my_strstr(const char* str1, const char* str2)
{assert(str1 && str2);const char* cp = str1;const char* s1 = str1;const char* s2 = str2;while (*cp){s2 = str2;s1 = cp;while (*s1!='\0' && *s2!='\0' && * s1 == *s2){s1++;s2++;}if (*s2 == '\0'){return cp;}cp++;}return NULL;
}
int main()
{char arr1[] = "abbbcdef";char arr2[] = "bbc";char *ret=my_strstr(arr1, arr2);if (ret == NULL){printf("不是子串\n");}else{printf("%s\n", ret);}
}

用cp标记每次查找的起始位置,s1每次从cp开始,s2从str2开始*s1=='\0'即找不到,*s2=='\0'即找到。cp为\0即在str1中无法找到子串。

2、字符串切割strtok

 1、每调用一次,在需要切割的函数里找 作为分隔符的任一字符,找到后置为\0 

2、第一次调用,需要传入这个字符串作为扫描的起始位置。完成调用,置为\0的位置会被记录,下次自动从\0的后一个位置开始扫描,因此后续调用传入NULL即可。

3、调用如果找到str的\0,本次调用还返回之前\0+1,但是后续所有的调用返回的都是NULL

利用while循环实现,循环前要先调用并打印一次。

巧妙利用for循环可以实现唯一一次初始化的特点,契合strtok函数的特点。

注意:strtok函数中涉及到对\0位置的标记和保存,在函数中保存而能在函数外使用,说明这个保存的指针类型应该用static关键字来修饰,即将这个变量附加一个静态属性,让它在函数外仍不被销毁,从而保存修改的\0的位置,进而下次使用strtok函数时直接调用。

同时,arr2字符串是一个常量字符串,内存是不可被改变的。第一个参数虽然可以传指针,但我们要考虑空间内存布局,用delim替换\0改变原字符串时,用指针指向这个字符串时,实际上指向的是字符串常量。

此处引用博主  Shemesz  提供的Linux下进程的内存布局图。

#include
#include
#include
// \0qq\0    com\0  next_start指向的是第一个q
//           @.\0
//     123456@qq.com.
char* my_strtok(char* str, const char* delim)
{static char* next_start = NULL;//第一次是NULL,后面的都不是NULLif (next_start != NULL){str = next_start;}if(str==NULL && next_start == NULL){return NULL;}char* s = str;//  str == 1  q   cconst char* t = NULL;while (*s){t = delim;while (*t){if (*s == *t){next_start = s + 1;if (s == str)//第一个元素就是要删除的,直接跳过,从下一个元素开始查找要删除的{str = next_start;break;}else{*s = '\0';return str;}}else{t++;}}s++;}//  s  t  都指向\0next_start = NULL;return str;
}
int main()
{//字符串切割strtokchar arr1[] = "123456@qq.com";char arr2[] = "@.";char* ch = NULL;for (ch = my_strtok(arr1, arr2); ch != NULL; ch = my_strtok(NULL, arr2)){printf("%s\n", ch);}
}

原码实现。其中两个循环内部与strstr函数寻找子串并返回找到的地址相似。

两个循环走完后都没有返回,说明已经查找不到要切割的字符,因此返回最后一部分字符串。

再次调用my_strtok函数,经判断后返回NULL。

3、错误信息翻译官strerror

C语言的库函数在运行时如果发生一些错误,就会将错误码存放在一个全局变量errno中。错误码是一些数字,我们可以用strerror将错误码“翻译”成错误信息。 

0  没有错误

1  操作不被允许,没有权限

2  没有文件或文件夹

3  没有这个进程

4  函数调用被中断

5  输入输出错误 

以上是几个错误码对应错误信息的例子。但实际上,程序产生错误后把错误码存入errno中,我们可以直接打印errno。

前面调用库函数失败后,errno内的值更新为刚刚的错误码,然后才能被strerror翻译出来。

4、翻译并打印perror

 在打印错误信息前,先打印你自定义的信息。 

perror可认为是printf+strerror

当我们想打印错误信息时使用perror更方便,但是不想打印时就要使用strerror了。

头文件是stdio.h也是输出  使用errno 包含 errno.h  strerror是string.h

5、字符分类/判断/转换函数

1、分类、判断

iscntrl任何控制字符
isspace空白字符:空格‘ ’,换页‘\f’,换行'\n',回车‘\r’,制表符'\t'或者垂直制表符'\v'
isdigit十进制数字 0~9
isxdigit十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F
islower小写字母a~z
isupper大写字母A~Z
isalpha字母a~z或A~Z
isalnum字母或者数字,a~z,A~Z,0~9
ispunct标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph任何图形字符
isprint任何可打印字符,包括图形字符和空白字符

本质上内存中存的是字符的ASCLL码值,通过传入字符或其ASCLL码值判断是不是相应字符。

例如,islower判断是否是小写字母。返回int  0则不是,非0则是。

这一类函数本质上是相同的,可以灵活使用,忘记了就可以查一下再熟悉。 

3、转换

tolower  toupper

传入小写字符/或其ASCLL,返回其大写的字符/ASCLL

int main()
{char arr[] = "I Have An Apple";int i = 0;while (arr[i]){if (isupper(arr[i])){printf("%c", tolower(arr[i]));}else{printf("%c", arr[i]);}++i;}	char arr[] = "I Have An Apple";//  是否实际改变数组内容   函数本身只是返回一个值  //  这是因为  传入的arr[i]为值传递,本身也改不了while (arr[i]){if (isupper(arr[i])){arr[i] = tolower(arr[i]);}printf("%c", arr[i]);++i;}return 0;
}

 以上都是针对字符的函数。

相关内容

热门资讯

政策“组合拳”持续显效 房地产... 从降低购房门槛到减轻房贷利息负担,从出台“好房子”规范标准到加快消化存量商品房……今年以来,多部门联...
周琦19+20孙铭徽29+8 ... 6月8日,全运会男篮资格赛A组,四川93-86力克山东。 全场数据: 四川,孙铭徽15中9,三分3...
美国非洲司令部司令炒作:中国正... 【文/观察者网 熊超然】中国和非洲国家之间开展正常军事合作,竟让一些美国人又“跳脚”了起来。 据香...
许其亮同志生平照片 2017年10月26日,习近平同志出席军队领导干部会议时与许其亮同志合影留念。新华社发 2000年...
家门口的“法律顾问”,东莞市侨... 近日,东莞市侨联法律服务站(谢岗分点)揭牌启用。服务站由谢岗镇侨联、谢岗司法分局、谢岗新阶联及广东连...
安徽泾县通报游客被打:涉事3人... 6月8日,安徽泾县联合调查组发布情况通报。全文如下: 6月6日,游客蔡某通过网络反映其6月1日到泾县...
因合同款欠付,中成股份孙公司起... 6月6日晚间,中成股份(000151)发布公告,因合同欠款事宜,公司控股子公司新加坡亚德有限公司下属...
中国学者遭美方起诉走私危险菌种... 中国驻芝加哥总领馆发言人就中国学者被起诉走私危险菌种事表示,已就美方执法部门未能履行中美领事条约规定...