C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

时间:2022-06-23 09:46:23

1昨日回顾

const int

和 int const是一样的

const char *p;值不变

char * const p; 指针不能变

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

编译器对参数的退化:

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

第三种模型:

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

三级指针

三级指针局部变量接收二级指针,并改变其内容

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

2拆分字符串第一种API

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

#define  _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

#include <string.h>

int splitString(char *str,char ch,char array[][30],int *count)

{

char *p = str;

char *q = p;

int temp_count = 0;

int len = 0;

if (str == NULL || array == NULL || count == NULL) {

fprintf(stderr, "str == NULL || array == NULL || count == NULL");

return -1;

}

// 在一个字符串中找到一个字符 找到了 返回第一个字符的地址 失败返回NULL

//strchr(母串,字符)

while (  (p = strchr(p, ch))!= NULL) {

// 找到了

strncpy(array[temp_count], q, p - q);

array[temp_count][p - q] = '\0';

temp_count++;

p++;

q = p;

if (*p == '\0')

{

break;

}

}

if (*q != '\0') {

len = (str + strlen(str)) - q;

strncpy(array[temp_count], q, len);

array[temp_count][len] = '\0';

temp_count++;

}

*count = temp_count;

return 0;

}

int main(void)

{

char *str = "abcdef.acccd.eeee.aaaa.e3eeee.ssss";

char array[10][30];

int count = 0;

int retn = 0;

int i = 0;

retn = splitString(str, ',', array, &count);

if (retn < 0)

{

fprintf(stderr, "splitString er\n");

return -1;

}

for (i = 0; i < count; i++)

{

printf("array[%d]:%s\n", i,array[i]);

}

return 0;

}

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

3拆分字符串第二种API

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

#include <string.h>

int spitString(char *str, char ch,char ***array_p,int *count)

{

// P,q指向str

char *p= str;

char *q = p;

// 计数

int temp_count = 0;

// 二级指针

char **array = NULL;

int str_len = 0;

if (str == NULL || array_p == NULL || count == NULL)

{

fprintf(stderr, "str == NULL || array_p == NULL || count == NULL\n");

return -1;

}

// 1 求出 字符串中 拆分的个数

while ((p = strchr(p, ch)) != NULL) {

temp_count++;

p++;

q = p;

if (*p == '\0') {

// 如果最后一位恰巧是ch那么+1就会是'\0'

break;}

}

// 如果有多余的

if (*q != '\0') {

temp_count++;

}

// 此时temp_count就是子字符串的个数

// 2 根据个数开辟指针数组 在堆上

// 在堆上开辟数组空间

array = (char**)malloc((sizeof(char*) * temp_count));

if (array == NULL)

{

fprintf(stderr, "malloc char **array error\n");

return -1;

}

// 清0

memset(array, 0, sizeof(char *)*temp_count);

// 3 拆分字符串,为每一个指针开辟堆空间 拷贝字符串

p = str;

q = p;

temp_count = 0;

while((p = strchr(p,ch))!= NULL){

// 找到了

str_len = p - q;

// 数组的某个元素指向新分配的堆空间 堆空间大小是 sizeof(char) * str_len +1,+1是为了'\0'

array[temp_count] = (char*)malloc(sizeof(char)*str_len+1);

if (array[temp_count] == NULL)

{

fprintf(stderr, "malloc array[%d] error\n",temp_count);

return -1;

}

// 将值拷贝到堆空间中

strncpy(array[temp_count], q, str_len);

// 最后要增添'\0'

array[temp_count][str_len] = '\0';

// 重复这个过程

temp_count++;

p++;

q = p;

// 如果字符串最后一位恰好是要被替换的ch 那么+1后就会遇到\0

if (*p == '\0')

{

break;

}

}

// 如果字符串最后一位不是ch的情况,q指向不是'\0'

if (*q != '\0') {

str_len = (str + strlen(str)) - q;

array[temp_count] = (char *)malloc(sizeof(char)*(str_len + 1));

// 任何分配空间都要做NULL值错误处理

if (array[temp_count] == NULL) {

fprintf(stderr, "malloc array[%d]error\n", temp_count);

return -1;

}

// 把最后一段复制到array中

strncpy(array[temp_count], q, str_len);

// 结尾补上'\0'

array[temp_count][str_len] = '\0';

// 计数增加

temp_count++;

}

if (array != NULL) {

// 三级指针接数组地址

*array_p = array;

*count = temp_count;

}

return 0;

}

int main(void)

{

char *str = "abcdef,acccd,eeee,aaaa,e3eeee,ssss";

char **array = NULL;

int count = 0;

int retn = 0;

int i = 0;

retn = spitString(str, ',', &array, &count);

for (i = 0; i < count; i++)

{

printf("array[%d]:%s\n", i, array[i]);

}

return 0;

}

3拆分字符串第二种API

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

#include <string.h>

void free_mem(char ***array_p,int count) {

char **array = *array_p;

int i = 0;

if (array_p == NULL) {

return;

}

if (array != NULL) {

for (i = 0; i < count; i++) {

if (array[i] != NULL) {

free(array[i]);

array[i] = NULL;

}

}

free(array);

*array_p = NULL;

}

}

int spitString(char *str, char ch,char ***array_p,int *count)

{

// P,q指向str

char *p= str;

char *q = p;

// 计数

int temp_count = 0;

// 二级指针

char **array = NULL;

int str_len = 0;

int retn = 0;

if (str == NULL || array_p == NULL || count == NULL)

{

fprintf(stderr, "str == NULL || array_p == NULL || count == NULL\n");

return -1;

}

// 1 求出 字符串中 拆分的个数

while ((p = strchr(p, ch)) != NULL) {

temp_count++;

p++;

q = p;

if (*p == '\0') {

// 如果最后一位恰巧是ch那么+1就会是'\0'

break;}

}

// 如果有多余的

if (*q != '\0') {

temp_count++;

}

// 此时temp_count就是子字符串的个数

// 2 根据个数开辟指针数组 在堆上

// 在堆上开辟数组空间

array = (char**)malloc((sizeof(char*) * temp_count));

if (array == NULL)

{

fprintf(stderr, "malloc char **array error\n");

retn = -1;

goto END;

}

// 清0

memset(array, 0, sizeof(char *)*temp_count);

// 3 拆分字符串,为每一个指针开辟堆空间 拷贝字符串

p = str;

q = p;

temp_count = 0;

while((p = strchr(p,ch))!= NULL){

// 找到了

str_len = p - q;

// 数组的某个元素指向新分配的堆空间 堆空间大小是 sizeof(char) * str_len +1,+1是为了'\0'

array[temp_count] = (char*)malloc(sizeof(char)*str_len+1);

if (array[temp_count] == NULL)

{

fprintf(stderr, "malloc array[%d] error\n",temp_count);

retn = -1;

goto END;

}

// 将值拷贝到堆空间中

strncpy(array[temp_count], q, str_len);

// 最后要增添'\0'

array[temp_count][str_len] = '\0';

// 重复这个过程

temp_count++;

p++;

q = p;

// 如果字符串最后一位恰好是要被替换的ch 那么+1后就会遇到\0

if (*p == '\0')

{

break;

}

}

// 如果字符串最后一位不是ch的情况,q指向不是'\0'

if (*q != '\0') {

str_len = (str + strlen(str)) - q;

array[temp_count] = (char *)malloc(sizeof(char)*(str_len + 1));

// 任何分配空间都要做NULL值错误处理

if (array[temp_count] == NULL) {

fprintf(stderr, "malloc array[%d]error\n", temp_count);

retn = -1;

goto END;

}

// 把最后一段复制到array中

strncpy(array[temp_count], q, str_len);

// 结尾补上'\0'

array[temp_count][str_len] = '\0';

// 计数增加

temp_count++;

}

if (array != NULL) {

// 三级指针接数组地址

*array_p = array;

*count = temp_count;

}

// 释放内存的步骤

END:

if (retn != 0) {

// 已经出现错误了

free_mem(&array, temp_count);

}

return 0;

}

int main(void)

{

char *str = "abcdef,acccd,eeee,aaaa,e3eeee,ssss";

char **array = NULL;

int count = 0;

int retn = 0;

int i = 0;

retn = spitString(str, ',', &array, &count);

for (i = 0; i < count; i++)

{

printf("array[%d]:%s\n", i, array[i]);

}

free_mem(&array, count);

if (array == NULL) {

printf("arraykong");

}

return 0;

}

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

4 数组的概念

数组:1. 连续的一大片内存空间

2. 每个元素数据类型相同 (否则不知道该偏移多少

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

#include <string.h>

int main(void)

{

int a[10] = { 0 };

int i = 0;

int j = 0;

/*  a是数组名 不能a++,,,,a=a+1;只能a[1]; *(a+i) //数组名是一个常量,是一个常指针,不能够被修改

数组名a本质是指向首元素地址 即&a[0]

a+1 a是int *const p; a+1  4个字节的偏移

&a+1 &a是int[10] *p    &a+1 4*10 = 40个字节的偏移

*/

int aa[3][4] = {

{3,5,4,3},

{2,3,4,5}

};

// 初始化一个数组 不管是几维,如果初始化不完全,剩下的就全部填充0

for (i = 0;i<3;i++)

{

for (j = 0; j < 4; j++)

{

printf("%d", aa[i][j]);

}

printf("\n");

}

printf("\n");

int size = sizeof(aa); //再求一个二维数组的 数据类型大小 int[3][4]

printf("size = %d\n", size);

// 如何定义指针?

// 比较好理解的方法 (int[3][4]) *p = NULL;

// 但是C语言中不能这么写,要把p放在数组前面 下面这样:

int(*p)[3][4] = NULL; // 指向二维数组int[3][4]的指针

printf("p: 0x%p, p+1:0x%p\n", p, p + 1);

// 0x0000 0030 (30是十进制的48)

// 数组也是有数据类型的

return 0;

}

5指针数组和数组指针的概念

typedef unsigned int u32;

int main(void)

{

//unsigned int a;

//u32 b;

//int a[3][4];

int a[10];

//typedef int[10] ARRAY_INT_10; 语法不能这么写,要用下面的写法:

typedef int ARRAY_INT_10 [10]; //为 int[10]这种数组 起一个别名 ARRAY_INT_10

ARRAY_INT_10 b_array; //int b_array[10]

int i = 0;

for (i = 0;i<10;i++)

{

b_array[i] = i;

}

for (i = 0;i<10;i++)

{

printf("%d\n", b_array[i]);

}

ARRAY_INT_10 *p = &b_array;

printf("p:%d,p+1:%d", p, p + 1);

return 0;

}

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

指针数组:

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

数组指针:

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

数组指针的两种定义方式:

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

6如何定义一个数组指针

void test(){

int aa; //0维数组 一级指针

int aaa[10]; //一维数组,二级指针

int aaaa[10][20]; //二维数组,三级指针

int a[3][4];

// a是一个指针 指向此二维数组首元素int[4]地址  int (*p)[4] == 二级指针 指向一维数组

// &a也是一个指针 指向此二维数组int[3][4]的地址 int(*p)[3][4] == 三级指针 指向一个二维数组

// 推论:一个数组指针,如果是几级指针,就是指向比他低一个维度的数组。

}

int main(void)

{

// 定义一个指针数组

// 在栈上  用char* 还是void*都是一样的四个长度

char *pinter_array[4] = { "asd",NULL,NULL,NULL };

// 在堆上:

char *heap_array =  malloc( 4 * sizeof(char*));

for(int i = 0;i<4;i++)

{

heap_array[i] = NULL;

}

int i = 0;

// 定义一个数组指针

// 方法一

// 直接定义一个数组类型

typedef int (ARRAY_CHAR_4) [4];

ARRAY_CHAR_4 array = { 1,2,3,4 };

ARRAY_CHAR_4 *p = NULL;

p = &array;

//方法二

typedef int (*ARRAY_CHAR_4_POINTER) [4];

ARRAY_CHAR_4_POINTER array_pointer = &array;

// 方法三

int(*array_p)[4] = NULL; // 直接定义一个数组指针

array_p = &array;

return 0;

}

7中午回顾

1这个算法: 用两个指针

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

2.养成好习惯:

free之后一定要 null

如果是NULL就return

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

free函数的返回值是void 所以不知道有没有成功,

自己接收的时候一定要用null来判断一下

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

8多维数组做为函数参数

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

(编译器并不是在栈中拷贝一份数组)

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

(并不是这样,否则太浪费空间了)

结论:当数组作为函数参数的时候,会退化成指针

形参用了数组的元素的指针来接收数组

(因为用了数组元素指针,就可以任意索引遍历数组

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

(数组作为形参被编译器退化)

。。。

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

补充:

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

总结:

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

9指针数组的练习

// 数组无论是几维数组 都是一块连续的内存空间

10main函数的命令行参数

判断数组长度了 除了 sizeof(p)/sizeof(*p) 这种方法,

还有一种方法:

就是在数组最后加一个NULL

然后for循环,

for(i = 0; arr[i] !=NULL;i++)

{

// 遍历

}

main函数入口的第三个参数是char *env[]

(前两个是int argc,char* argv

env指针数组就是这样实现的,最后一项默认是NULL

所以可以打印出来:

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

(环境变量:进程共享的变量

在windows运行桌面上的应用程序时候其实就是相当于在cmd里输入….exe 可执行程序可以拿到环境变量,环境变量是key value值的形式,value值是一段字符串

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针

C语言提高 (4) 第四天 数组与数组作为参数时的数组指针的更多相关文章

  1. 数组名作为函数参数以及sizeof用法

    来源:https://blog.csdn.net/jay_zhouxl/article/details/51745518 int f(int *p,char *a) { printf("p[ ...

  2. GO语言学习(十四)Go 语言数组

    Go 语言数组 Go 语言提供了数组类型的数据结构. 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形.字符串或者自定义类型. 相对于去声明number0 ...

  3. C语言提高 &lpar;3&rpar; 第三天 二级指针的三种模型 栈上指针数组、栈上二维数组、堆上开辟空间

    1 作业讲解 指针间接操作的三个必要条件 两个变量 其中一个是指针 建立关联:用一个指针指向另一个地址 * 简述sizeof和strlen的区别 strlen求字符串长度,字符数组到’\0’就结束 s ...

  4. Android JNI编程(四)——C语言多级指针、数组取值、从控制台输入数组

    版权声明:本文出自阿钟的博客,转载请注明出处:http://blog.csdn.net/a_zhon/. 目录(?)[+] 一:前面我们介绍了一级指针的相关概念和用发,今天我们就来说一说多级指针. 1 ...

  5. c语言提高第二天

    一.指针强化1.指针也是一种数据类型,指针变量也是一种变量,和int a本质是一样的 1)指针变量也是一种变量,也有空间,32位程序大小为4个字节 int *p = 0x1122; 2)*操作符,*相 ...

  6. c语言提高篇 第一天

    一.听课标准 1.选择法排序 2.会简单封装函数 3.数组做函数参数会退化为一级指针 a.数组做函数参数时,应该吧数组元素个数也传递给函数 b.形参中的数组,编译器把它仿作指针处理,c语言特色 c.实 ...

  7. Swift5 语言指南&lpar;二十四&rpar; 泛型

    通用代码使您能够根据您定义的要求编写可以使用任何类型的灵活,可重用的函数和类型.您可以编写避免重复的代码,并以清晰,抽象的方式表达其意图. 泛型是Swift最强大的功能之一,Swift标准库的大部分内 ...

  8. C语言高速入门系列&lpar;四&rpar;

    C语言高速入门系列(四) C语言数组 ---------转载请注明出处:coder-pig 贴心小提示:假设图看不清晰可右键另存为,应该就非常清晰了; 注意上面的代码都要自己过一遍哦! 本节引言: 经 ...

  9. 《C语言程序设计(第四版)》阅读心得(一)

    本篇开始写我个人觉得谭浩强老师的<C语言程序设计(第四版)>中之前没有认识到,或者忘了的知识.因为本科学过,所以有些简单的东西就没有放进来了,所以可能并不是太全面. 第一章程序设计与语言 ...

随机推荐

  1. 【MySql】C&num;数据库备份与还原

    public static class SQLBackup { /// <summary> /// 执行Cmd命令 /// </summary> /// <param n ...

  2. 优秀而又实用的PHP工具集锦

    优秀而又实用的PHP工具集锦   浏览:1141 发布日期:2013/09/04 分类:技术分享 PHP是目前实用最为广泛的服务器端开源脚本语言之一,很多优秀的开源程序都是基于PHP构建的,比如大名鼎 ...

  3. 解决Twitter Bootstrap Tab URL链接问题

    例如这样的一个Tabs 代码: <ul class="nav nav-tabs" id="myTab"> <li class="ac ...

  4. hdoj 2579 Dating with girls&lpar;2&rpar;【三重数组标记去重】

    Dating with girls(2) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  5. HTML Imports

    为什么需要导入? 先想想你在 web 上是如何加载不同类型的资源.对于 JS,我们有 <script src>.<link rel="stylesheet"&gt ...

  6. BrainFuck语言生成器

    还要求生成的代码比较快和短. 当然stackexchange上面给出了实现,java的 http://codegolf.stackexchange.com/questions/5418/brainfu ...

  7. HTML学习笔记 w3sCss盒子模型应用案例(div布局) 第十一节 (原创) 参考使用表

    * { margin: 0px; padding: 0px; } .top { width: 100%; height: 50px; background-color: antiquewhite; } ...

  8. 从零开始学习前端开发 — 1、HTML基础

    一.web标准 web标准-网页制作的标准,它是由一系列标准组成的,主要包含三个方面:结构(html,xhtml),表现(css),行为(javascript) 注:结构和表现的标准由w3c(万维网联 ...

  9. MySQL索引扩展&lpar;Index Extensions&rpar;学习总结

    MySQL InnoDB的二级索引(Secondary Index)会自动补齐主键,将主键列追加到二级索引列后面.详细一点来说,InnoDB的二级索引(Secondary Index)除了存储索引列k ...

  10. JAVA 程序编译过程&semi;编辑器&comma;编译器和解释器

    最基本的软件工具包括,编辑器,编译器,解释器; 编译器:编译器就是将一种编程语言代码翻译成另一种语言的等效代码程序. 解释器:解释器将编译和执行交织在一起,即编译一部分代码后执行该部分代码,然后再编译 ...