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;// 申请了一个变量, 即在 ...
随机推荐
- 获取SQL数据库表空间结构
if exists(select 1 from tempdb..sysobjects where id=object_id('tempdb..#tabName') and xtype='u')drop ...
- css样式,高斯模糊
.blur-container.blur-3 { --bg: url("background.jpg"); background-image: var(--bg); } .blur ...
- 第10课 std::bind和std::function(1)_可调用对象
1. 几种可调用对象(Callable Objects) (1)普通函数指针或类成员的函数指针 (2)具有operator()成员函数的类对象(仿函数).如c++11中的std::function类模 ...
- Linux打开TCP BBR拥塞控制算法
要求内核为4.9以上,如果不是,请升级内核. modprobe tcp_bbr echo "tcp_bbr" >> /etc/modules-load.d/module ...
- 生成excel的时候要用双引号。。。。。
<?php header("Content-type:application/vnd.ms-excel"); header("Content-Disposition ...
- 新型DenseBody框架:一张照片获得3D人体信息
来自云从科技和上海交通大学的研究者近期提出一种新型框架 DenseBody,可直接从一张彩色照片中获取 3D 人体姿势和形状.该研究设计了一种高效的 3D 人体姿势和形状表示,无需中间表示和任务,端到 ...
- Java - 27 Java 集合框架
Java 集合框架 早在Java 2中之前,Java就提供了特设类.比如:Dictionary, Vector, Stack, 和Properties这些类用来存储和操作对象组. 虽然这些类都非常有用 ...
- WPF Blend 一个动画结束后另一个动画开始执行(一个一个执行)
先说明思路:一个故事版Storyboard,两个双精度动画帧DoubleAnimation. 一个一个执行的原理:控制动画开始时间(例如第一个动画用时2秒,第二个动画就第2秒起开始执行.) XAML: ...
- python基础易错总结
1.python安装配置环境变量 [右键计算机]------->[属性]------->[高级系统设置]------->[高级]------->[环境变量]--------&g ...
- [Lua]table(一):打印与复制
一.打印table function PrintTable(tb) if type(tb) ~= "table" then print(tb) return end local c ...
