目录
1.4. strcmp 比较字符串,一般用来判断两个字符串是否相等
1.5. 长度受限制的字符串函数strncpy、strncat、strncmp
1.7. strtok 用特定字符集合(可以有多个)来分割字符串
3.4 memset函数:将某一块内存中的内容全部设置为指定的值
C语言中本身是没有字符串类型的,字符串通常存放在常量字符串或者字符数组中,字符串常量使用于那些对他不做修改的字符串函数。
下面对字符串相关的函数进行介绍。
1. 字符串相关函数
1.1. strlen 字符串长度
- 字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。
- 参数指向的字符串必须要以 '\0' 结束。
- 注意函数的返回值为size_t,是无符号数( 易错 )
//模拟实现strlen函数
//方法一:计数器方式
int my_strlen(const char * str)
{
int count = 0;
while(*str)
{
count++;
str++;
}
return count;
}
//方法二:不能创建临时变量计数器
int my_strlen(const char * str)
{
if(*str == '\0')
return 0;
else
return 1+my_strlen(str+1);
}
//方法三:指针-指针的方式
int my_strlen(char *s)
{
char *p = s;
while(*p != ‘\0’ )
p++;
return p-s;
}
1.2. strcpy 拷贝字符串
- 源字符串必须以 '\0' 结束。
- 会将源字符串中的 '\0' 拷贝到目标空间。
- 目标空间必须足够大,以确保能存放源字符串。
- 目标空间必须可变。
//模拟实现
char *my_strcpy(char *dest, const char*src)
{
char *ret = dest;
assert(dest != NULL);
assert(src != NULL);
while((*dest++ = *src++))
{ ; }
return ret;
}
char arr1[] = "hello";
char arr2[] = "zzzz";
strcpy(arr1, arr2);//返回类型为arr1的首地址
printf("%s\n",arr1);
1.3. strcat 追加字符串
char * strcat ( char * destination, const char * source );
//模拟实现strcat
char *my_strcat(char *dest, const char*src)
{
char *ret = dest;
//while(*dest)
//{
// dest++;
//}//找到\0
dest += strlen(dest);
//while(*src)
//{
// *dest = *src;
// dest++; src++;
//}
while((*dest++ = *src++))
{}
return ret;
}
int main(){
char arr1[30] = "hello ";
char arr2[] = "bit";
//strcat(arr1, arr2);
//strncat(arr1, arr1, 5);//自己给自己追加
my_strcat(arr1, arr2);
printf("%s", arr1);}
1.4. strcmp 比较字符串,一般用来判断两个字符串是否相等
int strcmp ( const char * str1, const char * str2 );
- 第一个字符串大于第二个字符串,则返回大于0的数字
- 第一个字符串等于第二个字符串,则返回0
- 第一个字符串小于第二个字符串,则返回小于0的数字
- ***注意***:比较的是字符的ascll码,第一个相等就比较后一个;
//模拟实现strcmp
int my_strcmp (const char * src, const char * dest)
{
assert(src != NULL);
assert(dest != NULL);
while(*src == *dest)
{
if(*src == '\0')
return 0;
src++; dest++;
}
/*if ( *src < *dest )
return -1 ;
else if ( *src > *dest )
return 1;*/
return *src - *dest;//这样是返回一个正数或者负数
}
1.5. 长度受限制的字符串函数strncpy、strncat、strncmp
(1)strncpy 拷贝souce中的前num个
char * strncpy ( char * destination, const char * source, size_t num );
(2)strncat 追加souce中的前num个
char * strncat ( char * destination, const char * source, size_t num );
(3)strncmp 比较两个字符串的前num个
int strncmp ( const char * str1, const char * str2, size_t num );
char a1[] = "abcdef";
char a2[] = "abcxyz";
if(strncmp(a1, a2, 3) == 0)
printf("前3个字母相同\n");
1.6. strstr 查找子字符串
char* strstr(const char* str1, const char* str2);
返回子串在原串中的指针位置,找不到则返回NULL
//模拟实现strstr
char* my_strstr(char* p1, char* p2)
{
char* s1 = p1;char* s2 = p2;
char* cur = p1;
assert(p1 && p2);
if(*p2 == '\0')
return p2;
while(*cur){
s1 = cur;
s2 = p2;
while((*s1 != '\0')&&(*s2 != '\0')&& (*s1 == *s2)){
s1++; s2++;
}
if(*s2 == '\0')
return cur;//找到了
cur++;
}
return NULL;//找不到的情况
}
int main(){
char a1[] = "abcdeflib";
char a2[] = "def";
//char* p = strstr(a1, a2);
char* p = my_strstr(a1, a2);//返回子串在原串中的指针位置
//即p指向"abcdeflib"中的d
if(p != NULL)
printf("%d\n", p-a1);
else
printf("not find\n");}
1.7. strtok 用特定字符集合(可以有多个)来分割字符串
- sep参数是个字符串,定义了用作分隔符的字符集合
- 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
- strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
- strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
- strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
- 如果字符串中不存在更多的标记,则返回 NULL 指针。
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");
}
return 0; }
1.8. strerror 报告错误信息
- errno是全局的错误码变量
- 当C语言的库函数执行时发生错误,就会把对应的错误码赋值到errno中;
- 每个错误码对应一个错误信息;
FILE * pFile;
pFile = fopen ("unexist.ent","r");
if (pFile == NULL){
printf("error no : %d\n",errno);
printf ("Error details: %s\n",strerror(errno));
}
else
printf("open success\n");
//errno: Last error number
2. 字符函数
2.1 字符分类函数
islower函数:判断是否为小写字符
isdigit函数:判断是否为数字
2.2 字符转换函数
tolower转小写
toupper转大写
char c1 = tolower('A');
char c2 = toupper('b');
putchar(c1);
putchar(c2);
3. 内存操作函数
3.1 memcpy函数: 内存拷贝
- 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
- 这个函数在遇到 '\0' 的时候并不会停下来。
- 如果source和destination有任何的重叠,复制的结果都是未定义的。
//模拟实现memcpy
void * my_memcpy ( void * dst, const void * src, size_t count)
{
void * ret = dst;
assert(dst);
assert(src);
//copy from lower addresses to higher addresses
while (count)
{
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
count--;
}
return(ret);
}
int a1[] = {1,2,3,4,5};
int a2[5] = {0};
my_memcpy(a2,a1,sizeof(a1));第三个参数为拷贝的大小,以字节为单位;
//a2为1 2 3 4 5
以上涉及重叠元素时不能完成拷贝,因为是一个一个字节拷贝的
3.2 memmove函数:有重叠时完成拷贝
- 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
- 如果源空间和目标空间出现重叠,就得使用memmove函数处理
int a1[] = {1,2,3,4,5,6,7,8,9,10};
int i;
memmove(a1+2, a1, 32);//把a1移动到a1+2的位置上,移动32个字节
for(i=0; i<10; i++)
{printf("%d ",a1[i]);}//输出为1 2 1 2 3 4 5 6 7 8
或者将原数组临时拷贝一份
3.3 memcmp函数:内存比较
按照字节进行比较,比较的是ascll值
char buffer1[] = "DWgaOtP12df0";
char buffer2[] = "DWGAOTP12DF0";
int n;
n=memcmp ( buffer1, buffer2, sizeof(buffer1) );
if (n>0) printf ("'%s' is greater than '%s'.\n",buffer1,buffer2);
else if (n<0) printf ("'%s' is less than '%s'.\n",buffer1,buffer2);
else printf ("'%s' is the same as '%s'.\n",buffer1,buffer2);
3.4 memset函数:将某一块内存中的内容全部设置为指定的值
void *memset(void *s, int ch, size_t n);
char a[10] = {0};
memset(a, '*', 9);//第三个参数以字节为单位;
puts(a);//*********