C语言详细分析常见字符串函数与模拟实现
一. strlen(求长度)
size_t strlen ( const char * str )
函数的返回值类型为size_t,为无符号数,且strlen返回值为字符串中‘\0’前的字符个数。
猜猜这个程序的输出
if (strlen("abc") - strlen("abcdef")) { printf(">"); } else { printf("<"); }
没错,是 >
因为strlen的返回值为无符号数,-3变成了一个很大的正整数。
二. strcpy(拷贝)
char* strcpy (char * destination, const char * source)
使用时,源字符串必须以\0结尾,并且'\0'也会拷过去
strcpy:"我不管你放不放得下,我就拷。"
目标地址必须够大且可修改,不然的话,虽然可以放进去,但是程序会崩溃
strcpy的模拟实现
char* my_strcpy(char* dest,const char* source) { assert(dest && source); char* ret = dest; while (*dest++ = *source++); return ret; }
三.strcat(追加)
char * strcat ( char * destination , const char * souce)
源字符串必须有'\0',目标字符串也得有'\0'
追加后,目标空间的'\0'无了,源字符串的'\0'添加上
目标地址必须够大且可修改
strcat的模拟实现
char* my_strcat(char* dest,char* source) { assert(dest && source); char* ret = dest; while (*dest) { dest++; } while (*dest++ = *source++); return ret; }
四.strcmp
int strcmp(const char* string1, const char * string2)
strcmp函数比较的不是字符串的函数长度`
而是比较字符串中对应位置上的字符的大小,如果相同,就比较下一对字符,知道不同,或者遇到'\0'.
若相同则返回0,若大于则返回大于零的数。若小于则返回小于零的数
strcmp的模拟实现
int my_strcmp(const char* str, const char* qtr) { assert(str && qtr); while (*str == *qtr) { if (*str == '\0') return 0; str++; qtr++; } if (*str > *qtr) return 1; else return -1; }
五.strncpy
char * strncpy ( char * dest, const char * source , size_t count)
作用是将源字符串的前count个字符拷贝到目标字符串
char a[] = "abcd"; char b[] = "qwer"; strncpy(a,b,1);
如以上修改后字符串为qbcd
strncpy的模拟实现
#define _CRT_SECURE_NO_WARNINGS 1 #include<string.h> #include<stdlib.h> #include<stdio.h> void my_strncat(char*dest,char*src,size_t n) { int t = strlen(dest); int f = strlen(src); for (int i = 0; i < n; i++) { *(dest + i) = *src; src++; } } int main() { int n; scanf("%d", &n); char src[50], dest[50]; strcpy(dest, "NICE"); strcpy(src, "SHOOT"); my_strncat(dest,src,n); printf("%s", dest); }
六.strncat
char * strncat ( char * dest , const char * source ,size_t count)
作用是将源字符串的前count个字符追加到dest后面、
并且会在结尾加上‘\0’
char arr1[]="abcdef\0xx"; char arr2[]="qwer"; strncat(arr1,arr2,2);
修改后为abcdefqw
strncat的模拟实现
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<string.h> #include<assert.h> void my_strncpy(char* str, char* qtr, int size) { assert(str && qtr); int t = strlen(str); for (int i = 0; i < size ; i++) { *(str + t + i) = *qtr; qtr++; } *(str + t + size) = '\0'; } int main() { char src[50], dest[50]; strcpy(src, "A nice"); strcpy(dest, " BOYYYYYYY"); int n = 0; scanf("%d", &n); my_strncpy(src, dest, n); printf("%s", src); }
七.strncmp
int strncm ( const char * str , const char * qtr , size_t num )
指定比较前num个字符,其他同strcmp一样
八.strstr
const char * strstr ( const char * str1, const char * str2 );
char * strstr ( char * str1, const char * str2 );
用于查找子串,返回第一次找到的地址
九.strtok
char * strtok ( char * str , const char * sep)
参数sep是由分隔符组成的一个字符串
str为一个字符串,包含sep中零个或者多个分隔符.
strtok会找到str中第一个分隔符,并把其替换成'\0',返回一个指向这个分隔符的指针
若第一个参数为'\0'',则从上一波保存的位置向后查找另一个分隔符
若字符串中不存在更多的分隔符,则返回NULL指针
char a[] = "A@nice.boy"; char sep[] = "@."; printf("%s", strtok(a, sep)); printf("%s", strtok(NULL, sep));
如以上结果为Anice
char a[] = "A@nice.boy"; const char sep[] = "@."; char arr[30]; char* str = NULL; strcpy(arr, a); for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep)) { printf("%s", str); }
以上输出为Aniceboy
十.strerror
char * strerror (int errnum )
errno是一个全局变量,记录最后的错误代码,程序刚刚启动的时候,errno 被设置为 0;程序在运行过程中,任何一个函数发生错误都有可能修改 errno 的值,让其变为一个非零值,用以告知用户发生了特定类型的错误。
十一.memcpy
void * memcpy ( void* dest , const void * source ,size_t count)
作用是将源字符串的前count个字节拷贝到dest上
int a1[20] = {1,2,3,4,5,6,7,8}; int a2[5] = {0}; memcpy(a1,a2,20);
执行后,a1数组前五个元素变成0
memcpy的模拟实现:
由于memcpy的拷贝是一个字节一个字节进行的
可用以下代码模拟实现
void* my_memcpy(void* dest, const void* source, size_t count) { assert(source && dest); void* ret = dest; while (count--) { *(char*)dest = *(char*)source; source=(char*)source+1; dest=(char*)dest+1; } return ret; }
十二.memmove
void * memmove (void * dest ,const void * source ,size_t count)
可以实现重叠内存拷贝
模拟实现:
void* my_memmove(void* dest, const void* source, size_t count) { if (dest < source) { while(count--) { *(char*)dest = *(char*)source; dest = (char*)dest + 1; source = (char*)source + 1; } } else { while (count--) { *((char*)dest + count )= *((char*)source + count); } } }
十三.memcmp
void * memcpy ( void * str , const void * qtr , size_t count)
比较str和qtr的前count个字节,注意是一个字节一个字节比较
这就很有意思了
请看以下代码
int a[5] = { 1,2,3,4,5 }; int b[5] = { 1,2,3,4,0x11223305}; memcmp(a,b,16);
很明显数组的前十六个字节相同,会返回0,但如果是前十七个呢
这是因为
5存储为 05 00 00 00
0x11223305为 05 33 22 11
十四.memset
void * memset ( void * dest , int c ,size_t count)
作用是将前count个字节改成参数c
int a[]={0,0x22222222}; memset(a,1,8);
如以上a数组变为0x01010101,0x0101010101
栏 目:C代码
下一篇:C语言实现控制台版贪吃蛇游戏
本文标题:C语言详细分析常见字符串函数与模拟实现
本文地址:http://www.codeinn.net/misctech/212384.html