大家好,欢迎来到IT知识分享网。
目录
int data[ ] = {1,2,3,4,5};和整型数组一个道理,char str[ ] = {‘h’,’e’,’l’,’l’,’0′};
因为本函数可以无限读取,易发生溢出。如果溢出,多出来的字符将被写入到堆栈中,这就覆盖了堆栈原先的内容,破坏一个或多个不相关变量的值
char *strcpy(char* dest, const char *src);strcpy(p,”zhonglibo122233″);//字符串拷贝函数
gets用法只能够在Linux下使用无法再Windows下使用
第九个assert字符串函数来断言跟if-else一样的道理
第1个、初识字符-第一个字符数组
常见字符,字符数组的 定义的几种方式和输出方式
- 定义的几种格式
- 和整型一样
int data[ ] = {1,2,3,4,5};和整型数组一个道理,char str[ ] = {‘h’,’e’,’l’,’l’,’0′};是字符串变量
- 改进char str[ ] = “hello”;是字符串常量,不予许被修改
- 一般用char *p =“hello”
- 第3和第4的区别:3是字符串变量可以被修改,4是字符串常量,不予许被修改。
#include <stdio.h> int main() { int data[] = {1,2,3,4,5};//整形数组初始化 char c = 'c';//一个字符写法 char cdata [] = {'h','e','l','l','o'};//字符数组定义 char cdata2[] = "World";//最常用的方式 char *pchar = "Project";//指针方式定义 char *p;//野指针,并没有明确的内存指向,危险 *p = 'a'; cdata2[3] = 'm'; printf("%s",cdata2);//最好用的输出 putchar('\n'); puts(cdata2); //*pchar = 'm'; puts("end"); /*for(int i = 0;i<5;i++){ printf("%d ",data[i]); } putchar('\n'); for(int i = 0;i<5;i++){ printf("%c ",cdata[i]); } putchar('\n'); for(int i = 0;i<5;i++){ printf("%c ",cdata2[i]); } putchar('\n'); for(int i = 0;i<5;i++){ printf("%c ",*(pchar+i));//指针方式输出 }*/ return 0; }
第2个、和整型数组在存储上的区别
- 和整型数组在存储上的区别
3、多了结束标志‘\0’
#include <stdio.h> #include <string.h> //strcpy strcmp strcat strstr int main() { //字符串和字符数组的区别; int data[] = {1,2,3,4,5};//整形数组初始化 //请计算数组data的元素个数 char cdata [] = {'h','e','l','l','o'};//字符数组定义,字符串的结束标志'\0' char cdata2[] = "hello";//最常用的方式 int len = sizeof(data)/sizeof(data[0]);//int 整形 printf("len = %d\n",len); len = sizeof(cdata2)/sizeof(cdata2[0]);//char 型 printf("len = %d\n",len); len = sizeof(cdata)/sizeof(cdata[0]); printf("len = %d\n",len); printf("%s\n",cdata); return 0; }
第3个、sizeof和strlen的区别
C语言中的
sizeof和strlen是两个常用的函数,用于获取变量的大小和字符串的长度。它们有以下区别:
sizeof是一个运算符,用于获取变量或数据类型的字节大小。它返回值的类型是size_t。sizeof可以用于任何数据类型,包括基本数据类型(如int、float等)和自定义数据类型(如结构体、数组等)。对于数组,sizeof返回整个数组的字节大小;而对于指针,sizeof返回指针本身的字节大小,而不是指针指向的对象的大小。strlen是一个库函数,用于获取字符串的长度,即不包括字符串末尾的空字符\0的字符个数。它返回值的类型是size_t。strlen只能用于字符串数组(字符数组)或字符指针(指向字符串的指针)。- 需要注意的是,
strlen函数要求字符串必须以空字符结尾,否则可能导致不可预测的结果或内存访问错误。
int arr[5]; size_t size1 = sizeof(arr); // 返回整个数组的字节大小 size_t size2 = sizeof(int); // 返回int类型的字节大小 char str1[] = "Hello"; char *str2 = "World"; size_t len1 = strlen(str1); // 返回字符串"Hello"的长度 size_t len2 = strlen(str2); // 返回字符串"World"的长度
#include <stdio.h> #include <string.h> void test() { } //strcpy strcmp strcat strstr int main() { char cdata[128] = "hello";//'\0'; void (*ptest) (); ptest = test; printf("sizeof: = %lu\n",sizeof(cdata));//关键字sizeof是计算整个类型大小 printf("strlen: = %lu\n",strlen(cdata));//strlen是计算字符串长度一定要记得区分使用 //计算有效字节的大小 char *p = "hello"; //常量 //p是一个char *,sizeof来计算的时候,得出是计算多少个字节来表示一个地址 printf("sizeof:p = %lu\n",sizeof(p)); printf("sizeof:char * = %lu\n",sizeof(char *)); printf("sizeof:int * = %lu\n",sizeof(int *)); printf("sizeof: test = %lu\n",sizeof(test)); printf("sizeof: ptest = %lu\n",sizeof(ptest)); printf("sizeof:char = %lu\n",sizeof(char)); printf("strlen: = %lu\n",strlen(p)); return 0; }
第4个malloc动态开辟内存空间
- malloc,函数原型 void *malloc(size_t size),C 库函数 void *malloc(size_t size) 分配所需的内存空间,并返回一个指向它的指针。realloc
- realloc,函数原型 void *realloc(void *ptr, size_t size)扩容,C 库函数 void *realloc(void *ptr, size_t size) 尝试重新调整之前调用 malloc 或 calloc 所分配的 ptr 所指向的内存块的大小。
- free
C 库函数 void free(void *ptr) 释放之前调用 calloc、malloc 或 realloc 所分配的内存空间。释放,防止内存泄露,防止悬挂指针,野指针的一种
- memset(p,’0′,12);用于清理字符串空间,函数原型 void *memset(void *str, int c, size_t n)
- 输出字符串
puts()
printf(“%s”,p);
- 获取字符串
scanf(“%s”,p)
gets
char * gets ( char * str );
因为本函数可以无限读取,易发生溢出。如果溢出,多出来的字符将被写入到堆栈中,这就覆盖了堆栈原先的内容,破坏一个或多个不相关变量的值
- 计算长度strlen
- 拷贝
strcpy
char *strcpy(char* dest, const char *src);strcpy(p,”zhonglibo”);//字符串拷贝函数
#include <stdio.h> #include <stdlib.h> #include <string.h> //char *strcpy(char* dest, const char *src);//函数原型 int main() { char *p;//野指针 p = (char *) malloc(1);//p有了自己的内存空间和具体的指向 *p = 'c';//指向一个字符串,这种操作不可取 free(p);//free释放空间 p = NULL;//不用就让他NULL防止悬挂,释放,防止内存泄露,也是野指针的一种 p = (char *)malloc(12);//开辟字符串空间 if(p == NULL){ printf("malloc error\n"); exit(-1);//用于单片机开发很吃内存空间的判断 } memset(p,'0',12);//用于清理字符串空间 printf("扩容地址:%x\n",p);//扩容前地址 int len = strlen("zhonglibo1029");//计算长度 int newLen = len - 12 + 1;//长度 - 12 + 1,加一是斜杆0; realloc(p,newLen);//扩容地址 printf("扩容地址后:%x\n",p); strcpy(p,"zhonglibo");//字符串拷贝函数 puts(p);//输出自己的字符串 puts("end");//打印查看是否会执行,会不会段错误 //printf("%c\n",*p); return 0; }
第五个gets、strcpy、strncpy、
gets用法只能够在Linux下使用无法再Windows下使用
#include <stdio.h> int main() { char *p = "zhonglibo handsome";//定义指针一个字符串 char str[128] = {'\0'};//定义一个字符数组初始化为0 puts(p);//puts输出 printf("%s\n",p);//printf()输出字符串 puts("请输入一个字符串"); //scanf("%s",str); gets(str); puts(str); return 0; }
1、5-funcsl.c:12:2: warning:函数’ gets ‘的隐式声明[-Wimp .c]
licit-function-declaration)得到(str);
2、5-funcsl.c:(.text+0x74):警告:’ gets’函数是危险的
不会被使用。
strcpy 、strncpy
#include <stdio.h> #include <string.h> int main() { char s1[32] = "helloworld"; char s2[32] = {0}; strcpy(s2,s1);//把s1拷贝到s2,把后面拷贝到前面,//把s1拷贝到s2中 printf("%s\n",s2);//输出s2 char s3[32] = "helloworld"; char s4[32] = ""; strcpy(s4,s3);//会拷贝\0导致覆盖无法拷贝后面数字 printf("%s\n",s4); char s5[32] = "";//重新定义一个数字字符 strncpy(s5,s3,10);//s5重新拷贝并指定10个 //printf("%s\n",s5); //s5[10] = '\0'; // 手动添加终止符 printf("%s\n",s5); return 0; }
第6个strncat-字符串拼接
#include <stdio.h> #include <string.h> int main() { char s1[32] = "hello"; char s2[32] = "world"; strcat(s1,s2);//strcat函数拼接 //strncat(s1,s2,2); printf("%s\n",s1);//把s2字符串接到s1, strncat(s1,s2,2);//指定字符串拼接 printf("%s\n",s1);//把s2字符串接到s1, return 0; }
字符段拼接详解-自己实现字符串拷贝函数
这个程序演示了三种不同的字符串拼接方法。
1. `myStrcat` 函数使用了两个指针来进行字符串拼接。首先使用 `assert` 函数确保传入的目标字符串和源字符串不为空。然后,指针 `des` 指向目标字符串的末尾,通过移动指针找到末尾位置。然后,在一个循环中,将源字符串 `src` 的字符逐个复制到目标字符串 `des` 所指的位置,直到遇到空字符为止。最后,在源字符串的末尾添加一个空字符,并返回目标字符串的起始指针。
2. `myStrcat2` 函数使用了库函数 `strcpy` 和 `strlen` 来进行字符串拼接。首先通过 `strlen` 函数找到目标字符串 `des` 的末尾位置,然后使用 `strcpy` 函数将源字符串 `src` 的内容复制到目标字符串 `des` 的末尾。最后返回目标字符串的起始指针。
3. `myStrcat3` 函数与 `myStrcat` 的实现方式类似,不同之处在于使用了不同的循环结构。首先使用一个循环找到目标字符串 `des` 的末尾位置,然后通过另一个循环将源字符串 `src` 的内容逐个复制到目标字符串的末尾。最后,在源字符串的末尾添加一个空字符,并返回目标字符串的起始指针。
在 `main` 函数中,我们声明了一个字符数组 `str` 用于存储目标字符串,同时声明了一个字符指针 `p` 并指向字符串 ” handsome”。然后,通过调用 `myStrcat3` 函数,将字符串 `p` 拼接到 `str` 之后。最后,使用 `puts` 函数将拼接后的字符串输出到屏幕上。
注释部分可以根据需要取消注释以测试其他的拼接方法。
#include <stdio.h> #include <string.h> #include <stdlib.h> // 第一个字符串复制函数,基本版 char* myStrcpy(char *des, char *src) { if (des == NULL || src == NULL) { return NULL; // 若源或目标字符串指针为空,则返回NULL } char *bak = des; // 保存目标字符串的起始地址 while (*src != '\0') { // 循环直到源字符串末尾 *des = *src; // 复制字符从源到目标 des++; // 目标地址递增 src++; // 源地址递增 } *des = '\0'; // 在目标字符串的末尾添加终止字符'\0' return bak; // 返回目标字符串的起始地址 } // 第二个字符串复制函数,优化版 char* myStrcpy2(char *des, char *src) { if (des == NULL || src == NULL) { return NULL; // 若源或目标字符串指针为空,则返回NULL } char *bak = des; // 保存目标字符串的起始地址 while (*src != '\0') { // 循环直到源字符串末尾 *des++ = *src++; // 复制字符从源到目标,并同时递增指针 } *des = '\0'; // 在目标字符串的末尾添加终止字符'\0' return bak; // 返回目标字符串的起始地址 } // 第三个字符串复制函数,修正后的正确版本 char* myStrcpy3(char *des, char *src) { if (des == NULL || src == NULL) { return NULL; // 若源或目标字符串指针为空,则返回NULL } char *bak = des; // 保存目标字符串的起始地址 while ((*des++ = *src++)); // 复制字符直到'\0',赋值表达式的结果为复制的字符,循环直到字符为'\0' return bak; // 返回目标字符串的起始地址 } char* myStrncpy(char *des, char *src, int count) { if (des == NULL || src == NULL) { return NULL; // 若源或目标字符串指针为空,则返回NULL } char *bak = des; // 保存目标字符串的起始地址 while (*src != '\0' && count > 0) { // 复制字符直到源字符串末尾或已复制指定数量的字符 *des++ = *src++; count--; // 每复制一个字符,计数器减1 } if (count > 0) { while (count > 0) { // 如果目标数组还有空间,则填充'\0' *des++ = '\0'; count--; } return des; } *des = '\0'; // 添加终止字符'\0' return bak; // 返回目标字符串的起始地址 } int main() { char str[128] = {'\0'}; // 初始化一个足够大的字符数组来存储复制的字符串 char *p = "zhonglibo handsome"; // 源字符串 myStrncpy(str, p, 6); // 使用myStrncpy复制前6个字符 puts(str); // 输出复制的字符串 return 0; // 程序正常结束 }
第7个strncat-字符串函数来比较字符串的大小关系
这段代码主要是演示了字符数组之间的比较操作。代码中使用了
strcmp()函数来比较字符串的大小关系。首先,声明了三个字符数组变量
char s1[32]、char s2[32]、char s3[32],分别存储了字符串”helloworld”、“helloboy”和”helloboy”。接下来,通过
strcmp()函数进行字符串比较。strcmp()函数会根据ASCII码对s1和s2进行比较,返回一个整数值。如果该值大于0,则表示s1大于s2;如果该值等于0,则表示s1等于s2。在代码中,通过
strcmp(s1, s2)进行比较,由于”s1″的ASCII码大于”s2″的ASCII码,所以输出了”helloworld > helloboy”。然后,通过
strcmp(s2, s3)进行比较,由于”s2″和”s3″的内容完全相同,所以输出了”helloboy = helloboy”。最后,程序返回0,表示正常结束执行。
#include <stdio.h> #include <string.h> int main() { char s1[32] = "helloworld"; char s2[32] = "helloboy"; if(strcmp(s1,s2) > 0) { printf("%s > %s\n",s1,s2); } char s3[32] = "helloboy"; if(strcmp(s2,s3) == 0){ printf("%s = %s\n",s2,s3); } return 0; }
第8个strchr-strrchr字符串函数来查找对应字符
这段代码演示了如何使用`strchr()`和`strrchr()`函数在字符串中查找特定字符的位置。
首先,声明了两个字符数组变量`char s1[32]`和`char s2[32]`,分别存储了字符串”helloworld”和”helloboy”。
接下来,通过`strchr(s1, ‘w’)`函数查找字符串中第一次出现字符’w’的位置,并使用`printf()`函数打印出结果。`strchr()`函数返回一个指向字符’w’的指针,如果找不到该字符,则返回NULL。所以在这段代码中,输出的结果是”welloworld”,因为找到了字符’w’,指针指向该位置。
然后,通过`strchr(s1, ‘l’)`函数查找字符串中第一次出现字符’l’的位置,并使用`printf()`函数打印出结果。`strchr()`函数返回一个指向字符’l’的指针。在这段代码中,输出的结果是”lelloworld”,因为找到了第一个字符’l’,指针指向该位置。
最后,通过`strrchr(s1, ‘l’)`函数查找字符串中最后一次出现字符’l’的位置,并使用`printf()`函数打印出结果。`strrchr()`函数返回一个指向字符’l’的指针。在这段代码中,输出的结果是”ld”,因为找到了最后一个字符’l’,指针指向该位置。
最后,程序返回0,表示正常结束执行。
#include <stdio.h> #include <string.h> int main() { char s1[32] = "helloworld"; char s2[32] = "helloboy"; printf("%s\n", strchr(s1,'w')); printf("%s\n", strchr(s1,'l')); printf("%s\n", strrchr(s1,'l')); return 0; }
第9个assert字符串函数来断言跟if-else一样的道理
这段代码演示了字符串拷贝函数`myStrcpy()`和`myStrncpy()`的实现,并进行了一些测试。
首先,代码使用了`assert()`断言来确保传入的目标字符串和源字符串不为NULL。这是一种运行时的检查机制,如果条件为假(即0),则会打印错误信息并终止程序运行。
接下来,定义了三个字符串拷贝函数`myStrcpy()`、`myStrcpy2()`和`myStrcpy3()`,它们的功能都是将源字符串拷贝到目标字符串中,并返回目标字符串的起始地址。
接下来,定义了字符串拷贝函数`myStrncpy()`,它还额外接受一个整数`count`参数,表示最多拷贝的字符个数。如果源字符串的长度大于`count`,则只拷贝前`count`个字符,如果源字符串的长度小于`count`,则在目标字符串末尾补充`\0`直到拷贝了`count`个字符。
在`main()`函数中进行了一些测试。首先定义了一个字符数组`str[128]`,并初始化为空字符。然后使用赋值语句`b=a`来判断`a`是否等于字符`’m’`,如果相等,则输出”ok”。接下来,定义了一个指向常量字符串的指针`p`,并调用`myStrcpy()`函数将常量字符串拷贝到字符数组`str`中。最后,使用`puts()`函数打印出拷贝后的字符串。
最后,程序返回0,表示正常结束执行。
#include <stdio.h> #include <string.h> #include <assert.h> char* myStrcpy(char *des, char *src) { //assert 的作用是现计算表达式 expression ,如果其值为假(即为0), //那么它先向 stderr 打印一条出错信息,然后通过调用 abort 来终止程序运行 assert(des != NULL && src != NULL);//断言, char *bak = des; while( *src != '\0'){ *des = *src; des++; src++; } *des = '\0'; return bak; } char* myStrcpy2(char *des, char *src) { if(des == NULL || src == NULL){ return NULL; } char *bak = des; while( *src != '\0'){ *des++ = *src++; } *des = '\0'; return bak; } char* myStrcpy3(char *des, char *src) { if(des == NULL || src == NULL){ return NULL; } char *bak = des; while( (*des++ = *src++) != '\0'); *des = '\0'; return bak; } char* myStrncpy(char *des, char *src, int count) { if(des == NULL || src == NULL){ return NULL; } char *bak = des; while( *src != '\0' && count>0){ *des++ = *src++; count--; } if(count > 0){ while(count > 0){ count--; *des++ = '\0'; } return des; } *des = '\0'; return bak; } int main() { char str[128] = {'\0'}; //char *pstr = NULL; char a = 'm'; char b; if((b=a) == 'm'){ printf("ok\n"); } char *p = "zhonglibo handsome"; myStrcpy(str, p); puts(str); return 0; }
9.1断言失败
言(assert)在程序开发过程中通常用来检查程序的假设条件是否成立。当断言失败时,它会打印一条出错信息,并终止程序的执行。
在这段代码中,断言的作用是检查传入的目标字符串指针
des和源字符串指针src是否为NULL,即是否为空指针。如果有任意一个指针为NULL,那么断言失败,会导致程序终止执行。在
main()函数中,定义了一个字符数组str[128]并初始化为空字符。然后定义了一个字符指针pstr并将其初始化为NULL。接下来定义了一个字符变量a并赋值为字符'm',然后定义了另一个字符变量b。通过(b=a) == 'm'的判断条件,判断a是否等于字符'm',如果相等,则输出”ok”。然后,定义了一个指向常量字符串的指针
p,该字符串是”zhonglibo handsome”。接下来调用myStrcpy()函数,但在调用过程中,传递给该函数的目标字符串指针pstr为NULL,这将导致断言失败。当断言失败时,通常会打印一条出错信息到 stderr(标准错误输出),然后终止程序的执行。在这段代码中,由于断言失败,所以不会输出”ok”,而是会在控制台打印出错误信息。
#include <stdio.h> #include <assert.h> char* myStrcpy(char *des, char *src) { //assert 的作用是现计算表达式 expression ,如果其值为假(即为0), //那么它先向 stderr 打印一条出错信息,然后通过调用 abort 来终止程序运行 assert(des != NULL && src != NULL);//断言, char *bak = des; while( *src != '\0'){ *des = *src; des++; src++; } *des = '\0'; return bak; } char* myStrcpy2(char *des, char *src) { if(des == NULL || src == NULL){ return NULL; } char *bak = des; while( *src != '\0'){ *des++ = *src++; } *des = '\0'; return bak; } char* myStrcpy3(char *des, char *src) { if(des == NULL || src == NULL){ return NULL; } char *bak = des; while( (*des++ = *src++) != '\0'); *des = '\0'; return bak; } char* myStrncpy(char *des, char *src, int count) { if(des == NULL || src == NULL){ return NULL; } char *bak = des; while( *src != '\0' && count>0){ *des++ = *src++; count--; } if(count > 0){ while(count > 0){ count--; *des++ = '\0'; } return des; } *des = '\0'; return bak; } int main() { char str[128] = {'\0'}; char *pstr = NULL; char a = 'm'; char b; if((b=a) == 'm'){ printf("ok\n"); } char *p = "zhonglibo handsome"; myStrcpy(pstr, p); puts(str); return 0; }
第10个字符串比较strcmp使用和实现
- 这些是头文件的引用,包括了
stdio.h(标准输入输出)、string.h(字符串操作)、assert.h(断言)。- 这部分定义了自定义的字符串比较函数
myStrcmp。函数接受两个字符指针参数str1和str2,用于比较两个字符串的大小关系。代码中的实现逻辑如下:- 定义变量
ret并初始化为 0,用于存储比较结果。- 定义变量
n_str1和n_str2并初始化为 0,用于存储累加字符串中各个字符的 ASCII 值。- 保存传入的指针参数
str1和str2到临时指针bakStr1和bakStr2。- 在一个循环中逐个比较两个字符串中对应位置的字符是否相等,直到遇到其中一个字符串的末尾或者遇到不相等的字符为止。
- 如果其中一个字符串没有遍历完,则重新从头遍历两个字符串,累加各个字符的 ASCII 值到
n_str1和n_str2。- 计算
n_str1和n_str2的差值并赋值给ret。- 如果
ret小于 0,则将ret设置为 -1,表示第一个字符串小于第二个字符串。- 如果
ret大于 0,则将ret设置为 1,表示第一个字符串大于第二个字符串。- 在
main函数中:- 定义了两个字符指针
p1和p2,分别指向两个字符串 “zhonmnlibod” 和 “zhonglizbod”。- 调用自定义的字符串比较函数
myStrcmp,将两个字符串作为参数传入,比较它们的大小- https://www.cnblogs.com/elesos/archive/2012/11/08/2759790.html
#include <stdio.h> #include <string.h> #include <assert.h> int myStrcmp(char *str1, char *str2) { int ret = 0; int n_str1 = 0; int n_str2 = 0; char *bakStr1 = str1; char *bakStr2 = str2; while( *str1 && *str2 && (*str1 == *str2)){ str1++; str2++; } if(*str1 || *str2){ str1 = bakStr1; str2 = bakStr2; while(*str1){ n_str1 += *str1; str1++; } while(*str2){ n_str2 += *str2; str2++; } } ret = n_str1 - n_str2; if(ret < 0){ ret = -1; } if(ret > 0){ ret = 1; } return ret; } int main() { char *p1 = "zhonmnlibod"; char *p2 = "zhonglizbod"; int ret = myStrcmp(p1,p2); if(ret == 0){ puts("两个字符串一样"); } printf("RET = %d\n",ret); return 0; }
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/110223.html










