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;// 申请了一个变量, 即在 ...
随机推荐
- lucene索引查看工具luke和文本提取工具Tika
luke可以方便的查看lucene的索引信息,当然也可以查看solr和es中的索引信息(基于lucene实现). 查看索引前,要注意lucene版本的问题,高版本的lucene用低版本的luke工具就 ...
- [UE4]区分敌我
第一方法是:使用Actor对象的Tag: 只要继承自Actor的对象,都会有Tags这个属性,这是一个数组,可以添加多个Tag. 在蓝图中可以使用“get Components by Tag”获得某个 ...
- @postconstruct初始化的操作(转载)
原文地址:https://www.cnblogs.com/qingruihappy/p/7861623.html 从Java EE 5规范开始,Servlet中增加了两个影响Servlet生命周期的注 ...
- jms和activemq简介
一.JMS简介 JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消 ...
- DELPHI中自定义消息的发送和接收
DELPHI中的消息处理机制 Delphi是Borland公司提供的一种全新的WINDOWS编程开发工具.由于它采用了具有弹性的和可重用的面向对象Pascal(object-orientedpasca ...
- 转载-----BUFG,IBUFG,BUFGP,IBUFGDS等含义以及使用
目前,大型设计一般推荐使用同步时序电路.同步时序电路基于时钟触发沿设计,对时钟的周期.占空比.延时和抖动提出了更高的要求.为了满足同步时序设计的要求,一般在FPGA设计中采用全局时钟资源驱动设计的主时 ...
- php namespace use 研究
1.file1.php: <?php namespace foos; class demo{ function testfn(){ echo "sdlkfjskdjf"; } ...
- centos7安装gitlab并汉化
一.基础环境准备 1.安装依赖包 [root@gitlab-server ~]#yum install curl policycoreutils openssh-server openssh-clie ...
- 完全使用css编写复选框
在日常的项目中,出现复选框或者单选框,应该都属于常见需求了,最开始阶段,一般只有两种可能性: 一.完全使用 <input type="checkbox" />或者&l ...
- inno setup 软件打包
2017-05-26 软件开发完毕以后,要进行打包发布,有几款打包用的软件很常见:innosetup,nullsoft,installshield.本人今天终于把自己独立开发的呈现软件打了包.第一个版 ...