C语言复习:字符串和一级指针
字符串基本操作
字符数组初始化方法
int main() { //1 {}号法 初始化列表 //数组初始化有2种方法 默认元素个数、指定元素个数 char buf1[] = { 'a', 'b', 'c', 'd', 'e' }; //若没有指定长度,默认数组长度即为参数个数 //若指定长度,指定长度小于参数个数→报错;buf长度多于初始化个数,会自动在后面补充零。 char buf2[6] = { 'a', 'b', 'c', 'd', 'e' }; char buf3[6] = { 'a', 'b', 'c', 'd', 'e' }; //char buf4[5] = {'a', 'b', 'c', 'd', 'e'}; printf("buf3:%s", buf3); system("pause"); } |
//在C语言中使用字符数组来模拟字符串 //C语言中的字符串是以'\0'结束的字符数组 //C语言中的字符串可以分配于栈空间,堆空间或者只读存储区 int main12() { //1 用字符串来初始化数组 char buf2[] = { 'a', 'b','c','d','\0' }; //2 字符串常量初始化一个字符数组 char buf3[] = { "abcde" }; char buf4[] = "abcde"; char buf5[100] = "abcde";
printf(" strlen(buf5) :%d \n", strlen(buf5)); printf(" sizeof(buf4) :%d \n", sizeof(buf5)); printf(" sizeof(buf4) :%d \n", sizeof(buf4)); } |
sizeof与strlen的区别: strlen()求字符串的长度,注意字符串的长度不包含\0 sizeof(类型)字符串类型的大小,包括\0; |
数组法和指针法操作字符串
03 字符串操作:数组法,下标法 字符数组名,是个指针,是个常量指针; 字符数组名,代表字符数组首元素的地址,不代表整个数组的。 如果代表这个数组,那需要数组数据类型的知识! |
//字符串操作方法 数组下标法 指针法 int main() { int i = 0; char buf[100] = "abcde"; char *p = NULL;
//下标法 for (i = 0; i<100; i++) { printf("%c", buf5[i]); } printf("\n");
//指针法1 for (i = 0; i<100; i++) { printf("%c", *(buf5 + i)); } //buf5是个指针,是个常量指针
//指针法2 printf("\n"); p = buf5; for (i = 0; i<100; i++) { printf("%c", *(p + i)); } //buf5是个指针,是个常量指针 } |
推演过程为:i变0+i, 去[]号加*号 //其实本质:指针*p间接寻址,操作内存; //[]:其实是编译器为我们做了*p操作而已 |
3.2字符串做函数参数
深入理解指针的关键是什么? 注意 指针和数组的巨大区别 char *p = "abcdefg"; char *buf = "abcdefg"; 一维字符串内存模型:两种 |
void copy_str01(char *from, char *to) { for (; *from != '\0'; from++, to++) { *to = *from; } *to = '\0'; }
void copy_str02(char *from, char *to) { while (*from != '\0') { *to++ = *from++; } *to = '\0'; }
void copy_str03(char *from, char *to) { while ((*to = *from) != '\0')//不用在后面添加'\0'因为\0已经复制过去了;复制\0之后才判断不满足条件从而退出循环 { to++; from++; } }
void copy_str04(char *from, char *to) { while ((*to++ = *from++) != '\0') { ; } }
int copy_str05_good(const { if (from == NULL || to == NULL) { printf("func copy_str05_good() err. (from==NULL || to==NULL)\n"); return -1; }
while ((*to++ = *from++) != '\0') { ; } return 0; } |
典型错误知多少 |
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); } 语法没问题,但是逻辑有错,错在没有规避"下级的数据不能用于上级"的错误。 |
修改字符常量结果会如何 char *p = "abcdefg"; Modify p[1] = '1'; 段错误! |
04字符串操作易错 |
//你往哪里输入数据 int main() { char buf[2000]; char *p = NULL; p = buf; printf("\n请输入一个字符串:"); scanf("%s", p);//野指针 printf("%s", p);
getchar(); getchar(); return 0; } |
3.3库函数api
快速的上手api是一种能力! |
建立正确的程序运行示意图,(内存四区及函数调用堆栈图)是根本保障!! |
#include #include
int main1() { char buf1[100]; char buf2[200]; strcpy(buf1, "111");//将后面的字符串复制到前面的缓存中 printf("%s", strcat(buf1, "222")); getchar(); return 0; }
int main2() { char *string1 = "1234567890"; char *string2 = "747DC8"; int length; //在字符str1中查找,与str2中任意字符有公共交集的个数 length = strcspn(string1, string2); printf("Character where strings intersect is at position %d\n", length);//len=3
getchar(); return 0; }
//strnset函数: 将字符串的前n个字符设置为指定字符 //测试程序修改如下 int main3() { char string[] = "abcdefghijklmnopqrstuvwxyz"; char letter = 'x'; printf("string before strnset: %s\n", string); strnset(string, letter, 13); printf("string after strnset: %s\n", string); getchar(); return 0; }
int main4() { char *string1 = "abcdefghijklmnopqrstuvwxyz"; char *string2 = "onm"; char *ptr; ptr = strpbrk(string1, string2); //strpbrk()函数检索两个字符串中首个相同字符的位置 if (ptr) printf("strpbrk found first character: %c\n", *ptr); else printf("strpbrk didn't find character in set\n"); getchar(); return 0;
}
int main5() { char input[16] = "abc,d"; char *p; /* strtok places a NULL terminator in front of the token, if found */ p = strtok(input, ","); if (p) printf("%s\n", p); /* A second call to strtok using a NULL as the first parameter returns a pointer to the character following the token */ p = strtok(NULL, ","); if (p) printf("%s\n", p);
getchar(); return 0; }
//典型的状态函数 int main() { char str[] = "now # is the time for all # good men to come to the # aid of their country"; //char delims[] = "#"; char *delims = "#"; char *result = NULL; result = strtok(str, delims); while (result != NULL) { printf("result is \"%s\"\n", result); result = strtok(NULL, delims); } printf("----------==========----------\n"); printf("%s", str);
getchar();
return 0; } |
3.4字符串相关一级指针内存模型
void main()
{
char buf[20]= "aaaa";
char buf2[] = "bbbb";
char *p1 = "111111";
char *p2 = malloc(100); strcpy(p2, "3333");
system("pause");
return ;
}
字符串反转模型
3.6一级指针(char *)易错模型分析
char *(字符串)做函数参数出错模型分析
建立一个思想:是主调函数分配内存,还是被调用函数分配内存; |
void copy_str21(char *from, char *to) {
if (*NULL = '\0' || *to!='\0') { Printf("func copy_str21() err\n"); return; }
for (; *from!='\0'; from++, to++) { *to = *from; } *to = '\0'; } //字符串逆序 int main() { //char p[1024] ={0}; char *p ={0}; p = NULL;
char to[100]; copy_str21(p, to); |
C语言中没有你不知道的,只有你不会调 Java语言中没有你不会调的,只有你不知道 |
不断修改内存指针变量 |
02越界
越界 语法级别的越界 |
char buf[3] = "abc"; |
03不断修改指针变量的值
越界 |
|
void copy_str_err(char *from, char *to) { for (; *from != '\0'; from++, to++) { *to = *from; } *to = '\0'; printf("to:%s", to); printf("from:%s", from); } |
04你向外面传递什么
1、临时str3内存空间 |
// char *str_cnct(x,y) /*简化算法*/ // char *x,*y; 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); } 2、经验要学习 while (*z++ = *x++); z--; /*去掉串尾结束标志*/ |
char *str_cnct(char *x, char* y) /*简化算法*/ { char * str3 = (char *)malloc(80) char *z = str3; /*指针z指向数组str3*/ while (*z++ = *x++); z--; /*去掉串尾结束标志*/ while (*z++ = *y++); z = str3; /*将str3地址赋给指针变量z*/ return(z); } |
char *str_cnct(char *x, char* y) /*简化算法*/ { If(x == NULL) { Return NULL; } char * str3 = (char *)malloc(80) char *z = str3; /*指针z指向数组str3*/ while (*z++ = *x++); z--; /*去掉串尾结束标志*/ while (*z++ = *y++); z = str3; /*将str3地址赋给指针变量z*/ note: return(z);
} Main() { Char *p = str_cnct("abcd", "ddeee"); If(p != NULL) { Free(p); p = NULL }//yezhizhen } |
int getKeyByValude(char *keyvaluebuf, char *keybuf, char *valuebuf, int * valuebuflen) { int result = 0; char *getbuf = new memset(getbuf, 0, sizeof(getbuf));
char *trimbuf = new memset(trimbuf, 0, sizeof(trimbuf));
int destlen = strlen(keyvaluebuf);
if (keybuf == NULL || keyvaluebuf == NULL || valuebuf == NULL/* || valuebuflen == NULL*/) { result = -1; return result; }
if (strstr(keyvaluebuf, keybuf) == NULL)// strstr函数返回一个指针,它指向字符串str2 首次出现于字符串str1中的位置,如果没有找到,返回NULL。 { result = -1; return result; } else { for (int i = 0; i < destlen; i++) { if (*keyvaluebuf == '=') { *keyvaluebuf++; break; } keyvaluebuf++; } while (*keyvaluebuf != '\0') { *valuebuf = *keyvaluebuf; valuebuf++; keyvaluebuf++; } *valuebuf = '\0'; }
int len = strlen(valuebuf); return result; } |
//char *p = "abcd11111abcd2222abcdqqqqq"; //字符串中"abcd"出现的次数。 //要求你自己写一个函数接口,并且写出测试用例。 //完成功能为:求出"abcd"字串出现的次数 //输入: int getSubCount(char *str, char *substr, int * mycount) { int ret = 0; char *p = str; char *sub = substr; int count = 0;
if (str==NULL || substr==NULL || mycount == NULL) { ret = -1; return ret; }
//char *p = "abcd11111abcd2222abcdqqqqqabcd"; //char *p2 = NULL; //p2 = p; do { p = strstr(p, sub); if (p!= NULL) { count++; //++后缀操作符优先级高,所以先执行*p操作 然后地址++ *mycount++; p = p + strlen(sub); } else { break; } } while (*p != '\0'); //printf("count:%d \n", count);
//mycount是实参的地址 *(实参的地址) *mycount = count; return ret; } |
05重复的错误何时休
#include #include #include
void copy_str21_modify(char *from, char *to) { int i = 0; if (*from != '\0')//要先考虑空串 { printf("ddddd"); } for (; *from != '\0'; from++, to++) { *to = *from; } *to = '\0'; printf("to:%s", to); printf("from:%s", from); }
void copy_str_err(char *from, char *to) { for (; *from != '\0'; from++, to++)//要先考虑空串 { *to = *from; } *to = '\0'; printf("to:%s", to); printf("from:%s", from); }
//字符串逆序 int mainaaaa() { char buf1[100] = "abcdefg"; char to[100]; copy_str_err(buf1, to); }
//越界场景 int main00000000000() { char from[5] = "abcde"; printf("\n %s", from); getchar(); return 0; } |
3.7const专题
- const基础知识(用法、含义、好处、扩展)
int main() { const int //上面两者一样
const char * const d; //这样限定指针的话就要为它赋初值,不然没有任何意义 char buf[100] const
return 0; }
Int func1(const) 初级理解:const是定义常量 const意味着只读 |
含义: //第一个第二个意思一样 代表一个常整形数 //第三个 c是一个指向常整形数的指针(所指向的内存数据不能被修改,但是本身可以修改) //第四个 d 常指针(指针变量不能被修改,但是它所指向内存空间可以被修改) //第五个 e一个指向常整形的常指针(指针和它所指向的内存空间,均不能被修改) |
Const好处 //合理的利用const, //1指针做函数参数,可以有效的提高代码可读性,减少bug; //2清楚的分清参数的输入和输出特性(参数列表中被const限定了的是传入参数) |
结论: //指针变量和它所指向的内存空间变量,是两个不同的概念。。。。。。 //看const 是放在*的左边还是右边 看const是修饰指针变量,还是修饰所指向的内存空变量 |
C语言复习:字符串和一级指针的更多相关文章
- C语言复习-字符串与指针
C语言复习-字符串与指针 例一: [字符串处理 去除C代码中的注释] C/C++代码中有两种注释,/* */和//.编译器编译预处理时会先移除注释.就是把/*和*/之间的部分去掉,把//以及之后的部分 ...
- 【C语言】字符串常量与指针
- C语言用一级指针处理字符串的反思
1.一级指针处理字符串的常见方式 如果使用单个指针,不方便对字符串本身进行操作,只适合遍历. 使用两个指针, 两个指针和字符串大致有两个常见处理方式: (1)两个指针从字符串首部开始向后移动,同时处理 ...
- c语言基础学习07_关于指针的复习
============================================================================= 指针变量之间赋值是需要兼容的. 例如:int ...
- C语言中的数组和指针以及字符串
数组名同时也是该数组首元素的地址,而指针提供了一种用来使用地址的符号方法,因此指针能够很有效地处理数组. 将一个整数加给指针,这个整数会和指针所指类型的字节数相乘,然后所得的结果会加到初始地址上 da ...
- C语言复习:指针知识
指针知识体系搭建 指针强化 指针是一种数据类型 指针也是一种变量,占有内存空间,用来保存内存地址 测试指针变量占有内存空间大小:sizeof(指针名); 2)*p操作内存 在指针声明时,*号表示所声明 ...
- C语言指针系列 - 一级指针.一维数组,二级指针,二维数组,指针数组,数组指针,函数指针,指针函数
1. 数组名 C语言中的数组名是一个特殊的存在, 从本质上来讲, 数组名是一个地址, 我们可以打印一个指针的值,和打印一个数组的值来观察出这个本质: int nArray[10] ={ 0 }; in ...
- go语言之字符串、指针、数组、切片、结构struct、面向对象
一: 字符串 概述: Go 语言将字符串作为 种原生的基本数据类型,字 符串的初始化可以使用字符串字面量. (1)字符串是常量,可以通过类 数组 索引访问其字节单元,但是不能修改某个字节的值 (2)宇 ...
- C语言一级指针与二级指针
指针的概念 指针就是地址, 利用这个地址可以找到指定的数据 指针就是地址, 那么在使用的时候, 常常会简单的说 指针变量为指针 指针变量就是存储地址的变量 int *p1;// 申请了一个变量, 即在 ...
随机推荐
- junit中线程需要注意的问题
Junit主线程执行完毕后,就会结束进程,不关注是否有其他线程在运行.当Junit运行完毕后,如果其他线程还没有执行完毕,那么不会再执行. 使用CountDownLatch,保证启动的线程运行结束后, ...
- [UE4]控制流
虽然官方文档说复杂的蓝图循环是会跨域多帧运行,但实际上测试下来,如果在循环体进行大量复杂的运算,不足以在一帧内完成时,游戏就会在当前帧卡住,直到循环结束为止. 一.Switch Switch可以在所有 ...
- 为什么QQ空间和QQ邮箱都是IE默认打开?
为什么QQ空间和QQ邮箱都是IE默认打开? 我已经设置成chrome为默认浏览器了 原文转载至:https://zhidao.baidu.com/question/390662851068217285 ...
- Go语言 函数,工程管理
Go语言 函数,工程管理 1.无参无返回值函数的使用 package main import "fmt" func main() { // 无参无返回值函数的调用:函数名() fu ...
- SSL&HTTPS简单介绍
这篇是最近看SSL和HTTPS的一个简单性总结,其中内容大部分都是参考网络上的内容,自己归纳整理了下. SSL介绍 HTTPS介绍 HTTP请求数据工作流程: l 用户在浏览器中输入网址,并告诉浏览 ...
- nonlocal和global
获取变量时遵循LEGB原则,修改变量时需要global/nonlocal进行修改 global # global的使用 函数外定义了全局变量: global关键字在函数内会修改全局变量 函数外没定义全 ...
- Linux性能优化 第一章 性能追踪建议
1.1常用建议1.1.1记大量的笔记(记录所有的事情)在做性能调优问题的时候很重要的一个操作就是记录下所有的事情,包括每一个输出.执行的结果.可以新建一个文件夹,然后把结果的文件都塞到该文件夹内.包括 ...
- isNAN的使用方法及介绍
NaN为 Not a Number isNaN()函数在接到一个值后,会尝试将这个值转换为数值. alert(isNaN(NaN)); //true alert(isNaN(25)); //false ...
- dns 域名地址
Public DNS+ 是属于 腾讯云旗下的公共 DNS 服务.拥有 80 多条国内线路和 4 条海外线路,有 BGP Anycast 技术,也是国内首家支持谷歌 ECS (edns-client-s ...
- Vue.js模拟百度下拉框
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...