虽然面试的时候,都会叫你不使用c库函数,自己完成某某函数的编写,但是库函数毕竟更让人信赖,我们没有任何理由怀疑库函数而使用自己的版本。不过当做练习,自己还是可以实现一下的。这里记录一下5th c primer附录中的可能用到的库函数。
- size_t strlen (const char *s)返回字符串中字符的个数,不包括结束空字符(\0)。
eg:
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> int main(void) { char *p="abc"; char a[]={'a','b','\0'}; printf("%I64u %I64u\n",strlen(p),strlen(a)); return 0; }
- char *strstr(const char *s1, const char *s2);
返回一个指针,它指向s1中第一次出现s2中字符序列的位置(不包含结束空字符),如果没有匹配则返回NULL。
eg:
#include <stdio.h> #include <string.h> int main() { char *p1="abcdefg"; char *p2="defg"; char *p3="zxcvb"; char * temp; if((temp=strstr(p1,p2))!=NULL) { printf("%s\n",temp); } else { printf("p2 not found!\n"); } if((temp=strstr(p1,p3))!=NULL) { printf("%s\n",temp); } else { printf("p3 not found!\n"); } return 0; }
- size_t strspn(const char *s1, const char *s2);
返回s1中完全由s2中字符组成的最大起始段长度
给出字符串s1, 以及指定规则字符串 s2,返回字符串s1中起始部分连续在s2字符串中的字符的个数(有n个字符在则返回n)。
eg:
#include <stdio.h> #include <string.h> int main() { char *p1="0123456789"; char *p2="222"; char *p3="2012"; char *p4="2014"; char *p5="2015"; printf("%I64u %I64u %I64u %I64u\n",strspn(p2,p1),strspn(p3,p1),strspn(p4,p1),strspn(p5,p1)); return 0; }
linux源码中使用的为:strspn(nextWALFileName, "0123456789ABCDEF") == 24
wal日志文件名字为24位0-F字符组成tli+logid+segid("%08X%08X%08X", tli, log, seg),那么给出一个文件名,如何判断其是否符合上述规则?就可以使用strspn函数。
- char *strrchr(char *string, int c);
在string指向的字符串中搜索c(转换成char)的最后一次出现,函数返回指向最后一个出现c的指针,如果没有找到则返回NULL.
eg:
#include<stdio.h> #include <string.h> #include <stdarg.h> int main() { char arr[]="aaaabqbccc"; char *s; s=strrchr(arr,'b'); if(s!=NULL) { printf("found %c at %s\n",*s,s); } s=strrchr(arr,'w'); if(s==NULL) { printf("ont find !\n"); } return(0); }
- void *memchr(const void *s, int c, size_t n);
The memchr function locates the first occurrence of c (converted to an unsigned
char) in the initial n characters (each interpreted as unsigned char) of the object
pointed to by s. The implementation shall behave as if it reads the characters sequentially
and stops as soon as a matching character is found.
Returns:
The memchr function returns a pointer to the located character, or a null pointer if the
character does not occur in the object.
#include <stdio.h> #include <string.h> int main(void) { int i; char *ret_s; char *s="aaabc"; ret_s=memchr(s,'b',5); for(i=0;i<strlen(s);i++) { if(s[i]==*ret_s) break; } printf("%c在第%d个位置出现。\n",*ret_s,i+1); return 0; }
数组下标从零开始的,实际位置加了1打印,这里数组下标为3,其实是第4个。
- int memcmp(const void *s1, const void *s2, size_t n);
比较s1和s2所指向对象的前n个字符,如果都相等,返回0,出现第一个不等的地方,如果s1指向的数大于s2指向的数,返回大于0的数,如果小于,返回小于0的数。
对于这个库函数你是否表示费解,首先,有strcmp和strncmp库函数了,看到memcmp的函数声明是void*,我以为是可以比较任意类型的,比如int,float和double,那这个函数和strcnmp是不是重复了呢?
二者都可以用于字符串的比较,但是二者是有比较大的差异的,因为strncmp是按照字节(byte-wise)比较的,并且比较的过程中会检查是否出现了"\0"结束符,一旦任意一个字符串指针前进过程中遇到结束符,将终止比较。而memcmp函数是用于比较两个内存块的内容是否相等。如果要比较的对象中包含一些由于边界对齐需求而填入结构对象中的空格、联合 (union)结束的额外空格、字符串所分配的空间未使用完的部分引起的“holes”的话,最好使用memcmp来完成。这些“holes”(漏洞)的内容是不确定的,在执行byte-wise比较时结果也是不明确的。
memcmp是可以比较int,float,double,这和我预期吻合,不然它用void *干什么嘛!O(∩_∩)O哈哈~
虽然c标准说的是字符,但是测试非字符也行,这样才符合void *的声明的本意。
未完待续....