[day03]两头堵挖字符串、字符串反转、一级指针(char )易错模型分析、作业换一种做法、const简单讲解、二维指针三种内存模型、怎么理解(多级)指针做函数参数、两个辅助指针变量挖字符串
1.两头堵
自己写的两头堵挖字符串 |
#include <stdio.h> //一般情况下不要修改输入内存块的值 int trimSpace(const char *inbuf, char *outbuf) { int ret = 0; char *bgnp = inbuf; char *endp = inbuf + strlen(inbuf) - 1; char *outbuftmp = outbuf; if (inbuf == NULL || outbuf == NULL) { ret = -1; printf("func trimSpace() err: %d\n", ret); return ret; } while (*bgnp != '\0' && *bgnp == ' ') bgnp ++; while (*endp == ' ' && endp != inbuf) endp --; while (*bgnp != '\0' && bgnp != endp) *outbuftmp ++ = *bgnp ++; *outbuftmp = '\0'; return ret; } int main(void) { char *inbuf = " abcd11111abcd2222abcdqqqqq "; char outbuf[50]; int ret = 0; ret = trimSpace(inbuf, outbuf); if (ret != 0) { printf("func trimSpace: %d\n", ret); return ret; } printf("%s\n", outbuf); return 0; } |
Ps:一般不要处理输入的字符串,将修改后的字符串单独用一个参数传进去 我不知道为什么去空格要用这种方法,用另一种不是更好么?这个字符串之间还有空格你就不处理么? |
2.字符串反转
字符串反转 |
#include <stdio.h> int reverseStr(const char *inbuf, char *outbuf) { int ret = 0; strncpy(outbuf, inbuf, strlen(inbuf)+1); char *bgnp = outbuf; char *endp = outbuf + strlen(outbuf) - 1; char tmp; //char *tmp; if (inbuf == NULL || outbuf == NULL) { ret = -1; printf("func trimSpace() err: %d\n", ret); return ret; } while (bgnp != endp) { tmp = *bgnp; *bgnp = *endp; *endp = tmp; // tmp = bgnp; // bgnp = endp; // endp = tmp; bgnp ++; endp --; } return ret; } int main(void) { char *inbuf = "abcdefg"; char outbuf[50]; int ret = 0; ret = reverseStr(inbuf, outbuf); if (ret != 0) { printf("func trimSpace: %d\n", ret); return ret; } printf("%s\n", outbuf); return 0; } |
Ps:注意企图通过交换指针交换是不现实的。 1 // tmp = bgnp; 2 3 // bgnp = endp; 4 5 // endp = tmp; 因为会导致循环根本就不执行(bgnp<endp),以及导致循环一直死循环(bgn!=endp)。 |
3.一级指针(char *)易错模型分析
1.越界 语法级别的越界 |
1 char buf[3] = "abc"; |
2. 不断修改内存指针变量 |
分析:a++导致a的位置变了,然后释放就不是在头部释放,导致错误发生。 |
void copy_str_err(char *from, char *to) { char *fromtmp = from; for (; *from!='\0'; from++, to++) { *to = *from; } *to = '\0'; printf("to:%s", to); printf("from:%s", from); } |
分析:和上面一样,移动了头部指针,最后你想把该你打印出来是不可能的。 结论:一般不要去动头部指针,弄一个临时指针指向头部。 |
3.返回一个临时区的数据 |
char *str_cnct(char *x, char* y) /*简化算法*/ { char str3[80]; char *z=str3; /*指针z指向数组str3*/ while(*z++=*x++); z--; /*去掉串尾结束标志*/ while(*z++=*y++); z=str3; /*将str3地址赋给指针变量z*/ return(z); } |
4.作业换一种做法
使用strstr函数和strchr做这道题,key=value的分割,通过key查出value |
#include <stdio.h> //一般情况下不要修改输入内存块的值 int trimSpace(const char *inbuf, char *outbuf) { int ret = 0; char *bgnp = inbuf; char *endp = inbuf + strlen(inbuf) - 1; char *outbuftmp = outbuf; if (inbuf == NULL || outbuf == NULL) { ret = -1; printf("func trimSpace() err: %d\n", ret); return ret; } while (*bgnp != '\0' && *bgnp == ' ') bgnp ++; while (*endp == ' ' && endp != inbuf) endp --; while (*bgnp != '\0' && bgnp <= endp)/*注意这里=也必须能赋值,不然就少一个字符*/ *outbuftmp ++ = *bgnp ++; *outbuftmp = '\0'; return ret; } int getValueByKey(char *keyvaluebuf /*in*/, char *keybuf /*in*/, char *valuebuf /*in out*/, int * valuebuflen /*in out*/) { int ret = 0; char tmpvalue[1024]; //1.查找key字符串存不存在 char *tmp = strstr(keyvaluebuf, keybuf); if (tmp == NULL) { ret = -1; printf("func strstr() err: %d\n", ret); return ret; } //2.查找=存在不存在 tmp = strchr(keyvaluebuf, '='); if (tmp == NULL) { ret = -1; printf("func strchr() err: %d\n", ret); return ret; } //3.去空格,分割 ret = trimSpace(++tmp, tmpvalue); if (ret != 0) { printf("func trimSpace() err: %d\n", ret); return ret; } *valuebuflen = strlen(tmpvalue); printf("tmpvalue:%s\n", tmpvalue); memcpy(valuebuf, tmpvalue, (*valuebuflen)+1); return ret; } int main(void) { int ret = 0; char keyvaluebuf[] = "ORACLE_name = itcast "; char *keybuf = "ORACLE_name"; char valuebuf[1024]; int valuebuflen = 0; ret = getValueByKey(keyvaluebuf /*in*/,keybuf /*in*/, valuebuf /*in out*/, &valuebuflen /*in out*/); if (ret != 0) { printf("func getValueByKey() err: %d\n", ret); return ret; } printf("keyvaluebuf:%s\n", keyvaluebuf); printf("keybuf:%s\n", keybuf); printf("valuebuf:%s\n", valuebuf); printf("valuebuflen:%d\n", valuebuflen); return 0; } |
5.const简单讲解
const |
1 const int a = 10; 2 3 int const b = 11; //两者作用一样 |
1 const int *c;//const修饰指针指向的那块内存区域,那块内存区域的内容不能修改 2 3 int *const d=0xaa11;//const放在*右边,表示修饰d,d是指针变量。//常量指针 4 5 d=0xaa22; //错误 6 7 const char* const e;//两者都不能变 |
ps:指针变量和它所指向的内存空间是两个不同的概念去理解const是放在*左边还是右边 |
6.二维指针三种内存模型
二维指针第一种内存模型 主函数char *arr[10]= {….}; 函数参数使用char **arr; 交换字符串使用的指针交换。 |
/* 二级指针第一种内存模型 */ #include <stdio.h> #include <stdlib.h> #include <string.h> int printArray(const char **arr, const int iNum) { int i; for (i = 0; i<iNum; i++) { printf("%s\n", arr[i]); } return 0; } int sortArray(const char **arr, const int iNum) { int i, j; char *tmp = NULL; for (i = 0; i<iNum; i++) { for (j = i+1; j<iNum; j++) { if (strcmp(arr[i], arr[j]) > 0) { tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } } } return 0; } int main(void) { //指针数组,数组里面存放的地址 char *arr[10] = { "bbbb", "cccc", "aaaa", "1111" }; printf("排序前:\n"); printArray(arr, 4); sortArray(arr, 4); printf("排序后:\n"); printArray(arr, 4); system("pause"); return 0; } |
二维指针第二种内存模型 主函数char arr[10][50]= {….}; 函数参数使用char arr[10][50]; 交换字符串使用的strcpy拷贝交换。 |
/* 二级指针第二种内存模型 */ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> //int printArray(const char arr[][50], const int iNum) //int printArray(const char (*arr)[50], const int iNum) int printArray(const char arr[10][50], const int iNum) { int i; for (i = 0; i<iNum; i++) { printf("%s\n", arr[i]); } return 0; } // 使用数组指针,参考day04 //int sortArray(char (*arr) [50], const int iNum) //int sortArray(char arr[][50], const int iNum) int sortArray(char arr[10][50], const int iNum) { int i, j; char tmp[50]; for (i = 0; i<iNum; i++) { for (j = i+1; j<iNum; j++) { if (strcmp(arr[i], arr[j]) > 0) { strcpy(tmp, arr[i]); strcpy(arr[i], arr[j]); strcpy(arr[j], tmp); } } } return 0; } |
二维指针第三种内存模型 主函数char **arr = (char **)malloc(10*sizeof(char *)); 函数参数使用char **arr; 交换字符串使用的strcpy拷贝交换。 |
/* 二级指针第三种内存模型 */ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> int printArray(const char **arr, const int iNum) { int i; for (i = 0; i<iNum; i++) { printf("%s\n", arr[i]); } return 0; } int sortArray(const char **arr, const int iNum) { int i, j; char tmp[50]; for (i = 0; i<iNum; i++) { for (j = i+1; j<iNum; j++) { if (strcmp(arr[i], arr[j]) > 0) { strcpy(tmp, arr[i]); strcpy(arr[i], arr[j]); strcpy(arr[j], tmp); } } } return 0; } int main(void) { int i; //自己构造一种内存 char **arr = (char **)malloc(10 * sizeof(char *)); //构造十个指向char*的指针空间 //接下来去构造那十个内存空间 for (i = 0; i<10; i++) { arr[i] = (char *)malloc(50 * sizeof(char)); // 构造存放五十个字符的空间 sprintf(arr[i], "%d%d%d", 10 - i, 10 - i, 10 - i); } printf("排序前:\n"); printArray(arr, 10); sortArray(arr, 10); printf("排序后:\n"); printArray(arr, 10); system("pause"); return 0; } |
二级指针三种内存模型图 |
7.怎么理解(多级)指针做函数参数
两个角度 |
第一个角度:站在C/C++编译器的角度,对形参,如果是指针类型,编译器只会把它当作一个指针变量来看,只会分配四个字节的内存。 第二个角度:我们只有在使用指针所指向的内存空间的时候,我们采取关心内存是一维还是二维的。 |
8.两个辅助指针变量挖字符串
以','分割,将结果存到二维数组 |
#include <stdio.h> int splitString(const char *src, const char c, char buf[10][30], int *ncount) { int ret = 0; char *bgnp = src; char *endp = NULL; int i = 0; int count = 0; if (src == NULL || buf == NULL || ncount == NULL) { ret = -1; printf("func spitString() err: %d\n", ret); return ret; } while (i < 10 && *bgnp != '\0') { endp = strchr(bgnp, c); if (endp == NULL) { ret = -1; printf("func strchr() err: %d\n", ret); return ret; } memcpy(buf[i], bgnp, endp - bgnp); buf[i][endp - bgnp] = '\0'; count++; bgnp = endp + 1; i++; } *ncount = count; return ret; } int main(void) { char *p = "abcdef,acccd,eeee,aaaa,e3eeeee,sssss,"; char c = ','; char buf[10][30]; int ncount; int i; int ret = 0; ret = splitString(p, c, buf, &ncount); if (ret != 0) { printf("func spitString() err: %d\n", ret); return ret; } for (i=0; i<ncount; i++) { printf("%s\n", buf[i]); } return 0; } |
注:对于栈上分配的内存空间,如果你在if里面去定义一个char buf[1000];编译器默认就给你分配好了内存空间,不会说等你执行if成立的时候才给你分配,你可以通过在if条件里面char *p=malloc(100)来分配,此时编译器在没执行if之前只会给你四个字节,只有当你if满足的时候才会给你分配那100个字节的内存空间。 |
附加思路:该代码提供的是字符串末尾也有’,’,如果别人给你传一个结尾没有’,’的字符串,你可以在处理函数中判断然后定义一个临时字符串拷贝它的内容并附加一个’,’。 |