C 字符串类型例题讲解与实现字符串库函数
1、实现C语言中strupr和strlwr函数
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<string.h> void str_upr(char *p) { int i; int len = strlen(p); for (i = 0; i < len - 1; i++) if (p[i] >= 'a'&&p[i] <= 'z') p[i] = p[i] - 'a' + 'A'; //p[i] -= 32; 在ASCII表里小写字母的值比对应大写字母的值大32 } void str_lwr(char *p) { int i; int len = strlen(p); for (i = 0; i < len - 1; i++) if (p[i] >= 'A'&&p[i] <= 'Z') p[i] = p[i] + 'a' - 'A';//p[i] += 32; } void main() { char str[128] = { "MSpaint" }; puts(str); str_upr(str); puts(str); str_lwr(str); puts(str); system("pause"); }
2、实现C语言中strrev函数
函数原型:char *strrev(char *str); 用于字符串的逆置。
函数功能:把字符串s的所有字符的顺序颠倒过来(不包括空字符NULL)。
函数说明:返回指向颠倒顺序后的字符串指针。
#include<stdio.h> #include<stdlib.h> #include<string.h> void str_rev(char *p) { char tmp; int len = strlen(p); for (int i = 0; i < len / 2; i++) { tmp = p[i]; p[i] = p[len - 1 - i]; p[len - 1 - i] = tmp; } } void main() { char str[10] = "ABCDEFG"; puts(str); str_rev(str); puts(str); system("pause"); }
3、实现C语言中strset函数
函数原型:extern char *strset(char *str, char character)
参数说明:str为源字符串,character为一个字符。
函数功能:将字符串str中所有的字符都设置成为指定的字符character。
返回说明:返回所有字符都设置为character后的字符串的指针。
#include<stdio.h> #include<stdlib.h> #include<string.h> void str_set(char *str, char ch) { while (*str != '\0') { *str = ch; str++; } } void main() { char str[128] = "Hello world!!!"; puts(str); str_set(str, 'Y'); puts(str); system("pause"); }
4、实现C语言中memset函数
函数原型:原型:extern void *memset(void *ptr, int value, size_t num)
函数功能:将ptr所指的内存区域的前num个字节都设置为value的ASCII值,然后返回指向ptr的指针。
函数说明:参数value虽声明为int,但必须是unsigned char,该函数使用unsigned char(一个字节8位)转换填充内存块,所以范围在0 到255 之间。无论value多大只有后八位二进制有效,而后八位二进制的范围在(0~255)中。而对字符数组操作时则取后八位赋值给字符数组,后八位值作为ASCII码。
#include<stdio.h> #include<stdlib.h> #include<string.h> void *mem_set(void *ptr, int value, int num) { unsigned char *px = (unsigned char *)ptr; if (ptr == NULL) return px; while (num > 0) //num-- { //*ptr++ = (unsigned char)value; *px = (unsigned char)value; //把int类型的value转换成unsigned char类型,意味着截去c的高24位,只保留低8位 px++; num--; } return ptr; } void main() { char str[] = "God bless you"; int a[6] = { 1,2,3,4,5,6 }; mem_set(str, '&', 9);
puts(str);
mem_set(a, 2, 32); for (int i = 0; i < 6; i++) printf("%d ", a[i]); system("pause"); }
数组str是字符型的,字符型占据内存大小是1Byte,而memset函数也是以字节为单位进行赋值的,所以你输出没有问题。 不加单引号,就是以此数字填充一个字节。数字输出的就是ASCII值对应的控制字符。加单引号' '就是以字符的ASCII值去填充一个字节。输出的就是字符。
如果用memset(a,2,sizeof(a)),就是对a指向的内存的24个字节进行赋值,每个都用数2去填充,转为二进制后,2就是0000 0010,占一个字节。一个int元素是4字节,合一起是0000 0010,0000 0010,0000 0010,0000 0010,转化成十进制就是33686018,就完成了对一个int元素的赋值了。
如果用memset(a,'H', sizeof(dx)),以字符' '形式初始化,先将字符' '转为ASCII值,例如'H'的ASCII值为72,转为二进制后就是0100 1000占一个字节,一个int元素4字节,合一起就是0100 1000,0100 1000,0100 1000,0100 1000,转化为10进制就是1212696648
5、实现C语言中strcat函数
函数原型: char *strcat(char *dest, const char *src)
函数功能:把src所指向的字符串(包括"\0")复制到dest所指向的字符串后面(删除*dest末尾的"\0")。
注意:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。返回指向dest的指针。
#include<stdio.h> #include<stdlib.h> #include<string.h> char *str_cat(char *dest, char *src) { if (dest == NULL || src == NULL) return NULL; else { char *p = dest; while (*dest != '\0') dest++; while (*src != '\0') //(*dest++ = *src++) != '\0' { *dest = *src; dest++; src++; } *dest = '\0'; return p; } } void main() { char dest[64] = "Hello "; char src[16] = "C++ user"; str_cat(dest, src); puts(dest); system("pause"); }
6、实现C语言中strncat函数
函数原型:char * strncat(char *dest, const char *src, size_t n)
函数功能:把src所指字符串的前n个字符添加到dest所指字符串的结尾处,并覆盖dest所指字符串结尾的'\0',字符追加完成后,再追加'\0'。
函数说明:src和dest所指内存区域不可以重叠,并且dest必须有足够的空间来容纳src的字符串,返回指向dest的指针。
#include<stdio.h> #include<stdlib.h> #include<assert.h> char *str_ncat(char *dest, char *src, int num) { if ((NULL == dest) || (NULL == src)) return NULL; char *p = dest; int i = 0; while (*dest != '\0') dest++; while (i < num && *src != '\0') { *dest++ = *src++; i++; } *dest = '\0'; return p; } void main() { char str1[32] = "Hello "; char str2[10] = "Mrs.Yang"; char *p = " And Dr.cheng"; puts(str_ncat(str1, str2, sizeof(str2))); puts(str_ncat(str1, p, 13)); system("pause"); }
7、实现C语言中strchr函数
函数原型:char *strchr(const char *str, int c)
函数功能:在参数 str 所指向的字符串中搜索第一次出现字符 c(一个无符号字符)的位置。
函数说明:该函数返回在字符串 str 中第一次出现字符 c 的位置,如果未找到该字符则返回 NULL。
#include<stdio.h> #include<stdlib.h> #include<string.h> char *str_chr(char *dest, char ch) { if (dest == NULL) return NULL; while (*dest != '\0') { if (*dest == ch) return dest; dest++; } return NULL; } void main() { char str[32] = "Github"; char ch = 'h'; char *p = str_chr(str, ch); if (p == NULL) printf("Not found"); else printf("%c %p", *p, &p); system("pause"); }
8、实现C语言中strcmp函数
函数原型:extern int strcmp(const char *s1,const char *s2)
函数说明:用于比较两个字符串并根据比较结果返回整数。若str1 = str2,则返回零;若str1 > str2,则返回正数;若str1 < str2,则返回负数
#include<stdio.h> #include<stdlib.h> #include<string.h> int str_cmp(char *str1, char *str2) { int i; for (i = 0; str1[i] == str2[i] && str1[i] != '\0'; i++); //跳过两个字符串相同部分 if (str1[i] == '\0'&&str2[i] == '\0') return 0; else if (str1[i] > str2[i]) return 1; else return -1; } int str_cmp_(char *s, char *t) { while (*s == *t && *s != '\0') { s++; t++; } return *s - *t; //返回第一对不同字符的ASCII差值 } void main() { char str1[16] = "Las Vegas"; char str2[16] = "Macao"; printf("%d", str_cmp(str1, str2)); system("pause"); }
9、实现C语言中strcpy函数
原型原型:char *strcpy(char* dest, const char *src)
函数说明:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间;src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
#include<stdio.h> #include<stdlib.h> #include<string.h> char *str_cpy(char *strDest, const char *strSrc) { if ((NULL == strDest) || (NULL == strSrc)) return 0; char *p = strDest; //可以返回函数内部定义的指针,但是不能返回函数内部定义的数组 while (*strSrc != '\0') { *strDest = *strSrc; strDest++; strSrc++; } *strDest = '\0'; //while ((*strDest++ = *strSrc++) != '\0');'\0'已复制 //赋值表达式返回左操作数,所以在赋值'\0'后,循环停止 return p; } void main() { char str1[16]; char str2[8] = "Viva"; char *str3 = "Las Vegas"; str_cpy(str1, str2); puts(str1); puts(str_cpy(str1, str3)); system("pause"); }
10、实现C语言中strncpy函数
函数原型:char *strncpy(char *dest, const char *src, int n)
函数功能:把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回被复制后的dest。
函数说明:复制字符串src中的内容(字符,数字、汉字....)到字符串dest中,复制多少由n的值决定。如果src的前n个字符不含NULL字符,则结果不会以NULL字符结束。如果n<src的长度,只是将src的前n个字符复制到dest的前n个字符,结果dest不包括'\0',需要手动添加一个'\0'。如果src的长度小于n个字节,则以NULL填充dest直到复制完n个字节。src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符长度+'\0'。
#include<stdio.h> #include<stdlib.h> #include<assert.h> char *str_ncpy(char *strDest, char *strSrc, int num) { if ((NULL == strDest) || (NULL == strSrc)) return 0; char *p = strDest; int i = 0; while (i < num && *strSrc != '\0') { *strDest++ = *strSrc++; i++; } *strDest = '\0'; return p; } void main() { char str1[16]; char str2[8] = "Please"; char *pc = "Sit down"; str_ncpy(str1, str2, 6); puts(str1); puts(str_ncpy(str1, pc, 10)); system("pause"); }
11、实现C语言中strlen函数
函数原型:extern unsigned int strlen(char *string)
函数功能:计算给定的字符串长度,直到碰到第一个字符串结束符'\0'为止,然后返回计数器值(长度不包含'\0'),char*做参数,且必须是以'\0'结尾的。
#include<stdio.h> #include<stdlib.h> #include<assert.h> int str_len(char *str) { int len = 0; while (*str++ != '\0') //计数器 len++; return len; } int str_len1(char *p) { const char *pt = p; while (*p++ != '\0'); //指针相减 return (p - pt - 1); } int str_len3(char *str) { if (*str == '\0') return 0; else return 1 + str_len3(str + 1); //递归 } int str_len4(char *str) { return assert(str), !(*str) ? 0 : 1 + str_len4(str + 1); //逗号运算符和条件表达式 } void main() { char str[16] = "Viva Las Vegas"; char *ps = "Sit down"; printf("%d %d", str_len(str), str_len(ps)); system("pause"); }
12、实现C语言中strstr
函数原型:extern char *strstr(char *str1, const char *str2)
函数说明:若str2是str1的子串,则返回str2在str1的首次出现的地址;如果str2不是str1的子串,则返回NULL。
#include<stdio.h> #include<stdlib.h> #include<string.h> char *str_str(char *str, const char *sub) { char *p = str; if (NULL == str || NULL == sub) return NULL; int M = strlen(str); int N = strlen(sub); int i, j, flag; for (i = 0; i <= M - N; i++) { flag = 1; for (j = 0; j < N; j++) if (str[i + j] != sub[j]) { flag = 0; break; } if (flag == 1) return (p + i); //返回找到的地址 } return NULL; } void main() { char str[32] = "Hooollp"; char sub[10] = "ol"; char *p = str_str(str, sub); if (NULL == p) printf("没有找到"); else printf("地址%p 在str中第%d个位置", p, (p - str)); system("pause"); }
while循环
#include<stdio.h> #include<stdlib.h> #include<string.h> char * my_strstr(const char *str, const char *sub) { if (NULL == str || NULL == sub) return NULL; char *cur = (char *)str; while (*cur != '\0') { char *temp_str = cur;//记录母串起始地址 char *temp_substr = (char *)sub;//记录子串起始地址 while (*temp_str++ == *temp_substr++) { printf("%c ", *temp_str);//为测试用 此时%c是递增后的字符 if (*temp_substr == '\0') //退出此时my_strstr函数 { return cur; } } cur++;//母串递增 } return NULL; } void main(int argc, char *argv[]) { char *string = "adcabcdef!"; char *substring = "abc"; char *ret = my_strstr(string, substring); if (ret == NULL) printf("不存在\n"); else printf("\n%s\n", ret); system("pause"); }
14.在字符串s1中查找串s2最右(最后)出现的位置,并返回一个指向该位置的指针。
#include<stdio.h> #include<stdlib.h> #include<string.h> char *my_strrstr(char const *str, char *const sub) { register char *last = NULL; register char *current = NULL; if (*sub != '\0') { current = strstr(str, sub); //查找s2在s1中第一次出现的位置 } if (current == NULL) return NULL; while (current != NULL) { last = current; current = strstr(last + 1, sub); } return last; } main() { char *str = "China is great in the Asia iniiininyy"; char *sub = "in"; char *p = my_strrstr(str, sub); if (p == NULL) printf("没有找到符合的子串哦!!"); else printf("%s", p); system("pause"); }
15.实现C语言的memcpy函数
函数原型:void *memcpy(void *destin, void *source, unsigned n)
功能:从源source所指的内存地址的起始位置开始拷贝n个字节到目标destin所指的内存地址的起始位置中。该函数返回一个指向目标存储区destin的指针。
应用说明:如果目标数组destin本身已有数据,执行memcpy()后,将覆盖原有数据(最多覆盖n)。source和destin都不一定是数组,任意的可读写的空间均可。
memcpy按照字节来拷贝,所以可以拷贝任何数据类型,不管什么类型都是二进制数据。
void * mem_cpy(void *Dest, void *Src,int count) { if (NULL == Dest || NULL == Src || count <= 0) return NULL; char *dest = (char *)Dest; char *src = (char *)Src; while(count--) *dest++ = *src++; }
16.字符串逆转
void invert(char *str) //字符数组逆序输出 { int len = strlen(str); for (int i = 0; i < len / 2; i++) { int tmp = str[i]; str[i] = str[len - 1 - i]; str[len - 1 - i] = tmp; } }
while循环
void invert_2(char *str) { if (NULL == str) exit(1);//exit(0)正常退出 非0异常退出 int len = strlen(str); int begin = 0; int end = len - 1; while (begin < end) { char temp = str[begin]; str[begin] = str[end]; str[end] = str[temp]; ++begin; --end; } }
指针循环
void invert_3(char *str) { if (NULL == str) exit(1); int len = strlen(str); char *pBegin = str; char *pEnd = str + (len - 1); while (pBegin < pEnd) { char temp = *pBegin; *pBegin = *pEnd; *pEnd = temp; pBegin++; pEnd--; } }
17.统计substr所指子字符串在str所指字符串中出现的次数。
int fun(char * str, char * sub) { int i, j, k, num = 0; for (i = 0; str[i] != '\0'; i++) for (j = i, k = 0; sub[k] == str[j]; k++, j++) { if (sub[k + 1] == '\0') { num++; break; } } return num; }
18.函数fun功能:将str所指字符串的正序和反序进行连接,形成一个新串放在temp数组中。
void fun(char * str, char * tmp) { int size = strlen(str); int i; for (i = 0; i < size; i++) tmp[i] = str[i]; for (i = 0; i < size; i++) tmp[size + i] = str[size - 1 - i]; tmp[2 * size] = '\0'; }
19.函数fun功能:将一个表示整数的数字字符串转换为一个十进制整数。
int fun(char * str) { int i = 0, flag = 1, Res = 0; int size = strlen(str); if (*str == '-') { str++; i++; flag = -1; } if (*str == '+') { str++; i++; } for (; i < size; i++) { Res = Res * 10 + (*str - '0'); str++; } return Res * flag; }
20.函数fun功能:将str所指字符串中除下标为奇数同时ASCII值为奇数的字符之外,其余所有字符都删除,串中剩余字符形成一个新串放在tmp所指的数组中。
char * fun(char * str, char * tmp) { int size = strlen(str); int i = 0, j = 0; for (; i < size; i++) { if (i % 2 != 0 && str[i] % 2 != 0) { tmp[j] = str[i]; j++; } } tmp[j] = '\0'; return tmp; }
21.去掉字符串中的空格
#include<stdio.h> #include<stdlib.h> #include<assert.h> char * trimSpace1(char *inbuf, char * outbuf) { assert(inbuf != NULL); assert(outbuf != NULL); while (*inbuf != '\0') { while (*inbuf != '\0' && *inbuf != ' ') { *outbuf = *inbuf; inbuf++; outbuf++; } inbuf++; } *outbuf = '\0'; return outbuf; } char * trimSpace2(char *inbuf, char * outbuf) { assert(inbuf != NULL); assert(outbuf != NULL); while (*inbuf++ != '\0') { if (*inbuf == ' ') continue; else { *outbuf = *inbuf; outbuf++; } } return outbuf; } int main(void) { char *str = " X - B_ o m b s! "; char *tmp = (char *)malloc(sizeof(char *) * 1024); trimSpace1(str, tmp); printf("%s\n", tmp); system("pause"); }
22.删除字符串中的某个字符,保留源字符串,把删除后的字符串存入一个新的字符串中。
char *fun(char *str, char *buf,char ch) { char *p = str; int i = 0; while (*p != '\0') { if (*p != ch) { buf[i] = *p; i++; } p++; } return buf; }
23.将字符串插到某个位置。
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<string.h> char *fun(char *strSrc, char *strFind, char *insert) { char *pstr = strstr(strSrc, strFind); int size = strlen(strFind); if (pstr == NULL) printf("Null Not Find"); else { char tmp[48]; strcpy(tmp, pstr + size);//strFind 后的字符串全部拷贝在tmp里 *(pstr + size) = '\0';//放弃后面的字符串 strcat(strSrc, insert); strcat(strSrc, tmp); } return strSrc; } int main(void) { char *allStr = { "Shenzhen is in Guangdong" }; char *findStr = "Shenzhen"; char *insertStr = " And NanShan"; char *pstr = fun(allStr, findStr, insertStr); printf("%s", pstr); system("pause"); }
24.函数fun的功能是:将形参s所指字符串中的所有字母字符顺序前移,其他字符顺序后移处理后新字符串的首地址作为函数值返回
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<string.h> char * fun(char * str) { int size = strlen(str) + 1; char AlphaBuf[28] = { 0 }; // = (char *)malloc(size * sizeof(char)); char OtherBuf[28] = { 0 };// = (char *)malloc(size * sizeof(char)); int i = 0, j = 0, k = 0; for (i = 0; i < size; i++) { if ((str[i] >= 'a') && (str[i] <= 'z') || (str[i] >= 'A') && (str[i] <= 'Z')) { AlphaBuf[j] = str[i]; j++; } else { OtherBuf[k] = str[i]; k++; } } for (i = 0; i < k; i++) { AlphaBuf[j + i] = OtherBuf[i]; //合并 } AlphaBuf[j + k] = '\0'; strcpy(str, AlphaBuf); return str; } void main() { char str[100]; printf("Please input string: "); scanf("%s", str); printf("\nThe result is:%s\n", fun(str)); system("pause"); }
25.两头堵模型 求非空格字符长度
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> #include<stdlib.h> #include <ctype.h> int main(void) { char *string = " 1A2B3C4D5E "; int i = 0; int j = strlen(string) - 1; while (isspace(string[i]) && string[i] != '\0') ++i; while (isspace(string[j]) && string[j] != '\0') --j; int ncount = j - i + 1; printf("%d\n", ncount); system("pause"); }
26.squeeze函数:将字符串s中删除字符c
#include<stdio.h> #include<stdlib.h> void squeeze(char *s, unsigned char ch) { int i, j; for (i = 0, j = 0; s[i]!='\0'; i++) { if (s[i] != ch) s[j++] = s[i]; } s[j] = '\0'; } void main() { char p[] = "Hello World!!!"; char ch = getchar(); squeeze(p, ch); puts(p); system("pause"); }
此处不能用char *p="resource" 是字符串常量对于 char *str = "resource";
把"resource"的值----也就是字符串常量字面值,也就是"resource"的地址,准确来说是起始地址----赋给字符指针str,Linux下,"resource"字符串常量是存放于
只读数据区的,对只读区的数据进行写操作是禁止,具体由相应的操作系统进行判断以及处理。
而对于 char str[] = "resource";str[]是一个字符数组,编译器首先在栈中分配一定的连续空间用于存放“resource”中的字符以及结尾符,
然后把字符串常量的内容,也就是"resource"中的各个字符和结尾符复制到这个栈中的连续空间中。str是数组名,用来表示这个连续栈空间的起始地址,
所以str中存放的是栈地址,这个地址的数据是可写的。
而对于char* str = new char[12];由于重新分配了内存,然后将常量字符串内容拷贝过来,这样str指向的不是只读数据区,也就可以修改了。
但是要注意的是,下面的代码也是不行的:
char* p = new char[12]; printf("%p\n", p); p = "resource"; printf("%p", p);
p[6] = 'k'; //报错
或许通过这个例子大家可以更容易的理解这个问题,在编译器调试状态下,可以很容易地看到,刚分配完内存的p的地址与给p赋值后的地址明显不同,
所以经过后一个赋值语句后,p又重新指向了只读内存区,所以又不能修改了!
27.字符串中字符反向排列
void reverse_string(char *str) { char *end_character; for (end_character = str; *end_character != '\0'; end_character++); end_character--;//让end_character设置为指向字符串的最后一个字符 while (str < end_character) { //交换str和end_character指向的字符 char tmp; tmp = *str; *str++ = *end_character; *end_character-- = tmp; } }

浙公网安备 33010602011771号