C语言—数组、指针、动态数据

一、数组、字符串基本概念

  1. 数组定义:由同一种类型、有序数据的集合;各数据称作元素,在内存中占据一段连续的存储单元;一般经常使用的是一维数组、二维数组;数组名就是这一数组在内存中的首地址;

  1. 一维数组的使用:元素只能逐个引用;下标越界编译器并不检查,这个检查交给程序员自己;数组元素的下标必须是方括号;可利用for循环为数组初始化复制及引用;

  1. 当数组被说明静态(static)存储类型时或者外部存储类型(即在所有函数外部定义时,)则在不显示给出初值的情况下,数组元素将在程序编译阶段自动初始化为0;

static int a[4] 等价于 static int a[4]={0,0,0,0};

  1. 二维数组的使用:存在行指针与列指针,但是不是二级指针,且二维数组在内存中是按照行接行的形式存储的;第一维长度在初始化时可以不指定长度,但是第二维不能省略;

  1. 数组名作为实参传递给调用函数的形参属于地址调用;

  1. 当实参把主函数的变量的地址传递给形参(指针)时,才可以在被调用函数中修改主函数中该变量的值,才能带回修改值;因为形参和实参两个数组或者变量指针()在内存中因指向同一地址,操作的是同一个内存空间造成的;

  1. 初始化一维字符数组时,可以省略数组长度,系统会自动根据初值个数确定数组长度;

  1. 连续输出字符数组时,需要利用for循环连续输出单个字符;

  1. 因为C语言没有字符串类型,所以将字符串作为字符数组处理;第一个结束标志‘\0’前的字符成为有效字符串;字符串存储在数组中才可以修改,并且该数组的名字就是该字符串的首地址;当把字符串的地址交给一个单独的指针时,无法通过该指针修改字符串,因为指针只是有字符串的首地址,并没有提供存储空间,此时字符串是一个“字符串常量”,无法修改,存储在内存的常量区;也就是说这个字符串常量本身代表的是该字符串在内存中的首地址,也就是一个地址常量;

  1. 记住:声明一个数组将为数据分配存储空间,而声明一个指针只为一个地址分配存储空间,无法存储数据;

char c[]={"I am happy};    //正确,可修改字符串
char c[]="I am happy";    //正确,可修改字符串
char *p="I am happy";    //正确,只是该字符串是常量,无法通过指针修改,只可以打印;
  1. 字符串输出puts自带换行输出功能;

  1. 字符串输入gets可将空格等读入,直到\n;


二、字符串函数(string.h)

  1. 字符串输入输出

①scanf("%s",name); 缺点:无法跳过' ' ,即遇到空格就停止读入,导致后面的无法被读入到数组中;会在最后自动添加'\0'作为结束标志;适用于混合类型数据的读取和转换;

②ptr=gets(name); 最常用,优点是会自动跳过空格等,直到遇到换行符(即键盘的换行),并在最后自动添加'\0'作为结束标志;缺点是不检查输入的字符个数,可能超过数组总长度,导致越界;其返回值是字符串的地址(即数组的地址)返回给调用它的地方(交给指针ptr);

③ptr=fgets(name,MAX,stdin); 专用为io文件设置,为了避免gets的越界问题,fgets需要输入第二的参数(说明最大读入字符数,则实际存储的是MAX-1个,因为最后留一个给‘\0’)、第三个参数(说明从哪里读文件,如果是键盘,则使用stdin);需要注意的是fgets会存储‘\n’,然后最后是‘\0’,导致后续输出时,会输出一个换行符;所以如果后面利用printf输出是,后面就不用加‘\n’,如果使用puts输出将会导致连续两个换行;

④printf("%s\n",name); printf不会自动换行,需要添加一个'\n',适合于多种数据类型的格式化输出;

⑤puts(name); 会输出字符串后自动添加一个‘\n’;

⑥fputs(name,stdout); 面向io文件,stdout是标准输出(屏幕);注意他不会为输出添加换行符,一般配合fgets使用(因为fegets存储了换行符);

⑦循环方式:putchar, getchar 注意循环使用;

输入

输出

配合原因

scanf

printf

多种类型形式混合,面向单词

gets

puts

使用方便,前者不存储\n,后者自带\n

fgets

fputs

面向io文件,可指定输入个数,前者存储\n,后者不带\n;

  1. 功能性字符串函数

函数

格式

功能说明

strlen

strlen(name)

得到字符串的长度,不包括‘\0’,但是包括空格、制表符等;

strcat

strcat(name1,name2)

将第二个字符串拷贝到添加到第一个字符串的结尾,同时将自己最后的‘\0’也同步复制过去,但是不检查第一个数组的剩余空间是否足够,存在越界的可能;

返回值是第一个字符串的地址;

strncat

strncat(name1, name2, num);

num是第三个参数表明第一个数组最多可以容纳多少个字符,注意第一个数组的‘\0’位置是要被第二个数组的字符覆盖掉的;

返回值是第一个字符串的地址;

strcmp

strcmp(name1, name2);

字典式比较两个字符串,若相同则返回0,若第一个字符串的ansii码小于第二个字符串,则返回-1,否则返回1;

ansii中先显示大写字母(A65),后显示小写字母(a97),两者相差32;

返回值是int(-1,0,1)

strncmp

strncmp(name1, name2, num);

num限定了比较两者的前几个字符,设置了范围;其他同上;

strcpy

strcpy(name1, name2);

将字符串2赋值或者复制到字符串1;

strncpy

strcpy(name1, name2,num);

num是数组1可接受的最大的字符数,其他同上;

sprintf

sprintf(name, "%s,%s,%d\n",str1,str2,num)

把几个元素组合成一个字符串,例如将两个字符串、数字合并为一个字符串放到数组name中,而不是输出到显示屏上;

strlwr

strlwr(name)

将字符串中的大写字母转换为小写字母,同时将name的指针返回

strupr

strupr(name)

将字符串中的小写字母转换为大写字母,同时将name的指针返回


三、指针基础知识

  1. 直接寻址:直接按变量名来获取变量内容的访问方式;&a;

  1. 专门用于存放地址型数据的变量就是指针变量;

  1. 间接寻址:通过指针变量来间接存取它所指向的变量的访问方式称为间接寻址;int *p=&a;

  1. 指针的作用:

①指针提供通过变量地址访问变量的手段;增加了间接寻址方式;

②指针为c的动态内存分配系统提供了支持;

③指针为动态数据结构(例如 链表、队列、二叉树等)提供支持,操作系统的编写;

④指针可以改善某些子程序的效率;(传指针参数在调用函数里面就可以直接修改主函数中的对应变量,不需要将该变量的整体数据传到调用函数中);

  1. int *p=&a; int等类型是指针的基类型,说明指针可以指向这种类型的变量;

  1. 指针变量必须先定义(必须有地址交给它)再使用,否则会造成野指针;

  1. 运算符*和++、--优先级等同,连续运算,采用右结合。下列各语句的含义如下:

a=*p++ 先运算p++,但为后增运算,因而先将*p的值赋给a,然后p加1。

a=(*p)++ 先取*p的值,赋给a。然后将p所指向的变量内容加1。

  1. 字符指针:就是指向字符型数据的指针变量;可以指向字符串;

字符数组可用于存放字符串,直接通过数组元素存取字符串属于直接寻址,字符指针则属

于间接寻址。

  1. 字符指针作为函数参数传递给形参,那么就可以在调用函数中修改其指向的变量的值;

  1. 在表达式中,数组名被自动转化为指向数组中第一个元素的常量指针;

  1. 利用指向字符串的指针的自增运算(++、--)可以逐个访问各元素,遍历;


四、指针数组

  1. 由若干基类型相同的指针所构成的数组。一个数组,其元素均为指针的数组;但是这种不是二维指针;

  1. 主要作用:适用于用来指定若干个字符串,使字符串处理更加灵活;


五、动态数据结构

  1. 静态数据结构—数组对于数据个数变化 较大时,存储空间浪费很大。是由于在编译时,数组元素的存储空间已分配

  1. 动态数据结构—结点对于数据个数变化较大时,存储空间得到100%的利用,是由于在编译时,不分配结点的存储空间,需要时,临时申请,系统再分配存储空间。

  1. 动态存储分配函数头文件:malloc.h/stdlib.h;

  1. malloc()函数

①在内存的动态存储区中分配一个长度为size的连续空间;

②此函数的返回值是一个指向分配域的起始地址指针 (基类型为void,可以在前面强制转换) 。如果此函数未能成功地执行,则返回空指针。

③例子:

long *p;
p=(long *)malloc(8);
//申请一个8个存储字节的空间,
//并将其返回的指针转换成长整形指针。
  1. calloc()函数

①格式:void *calloc(unsigned int n, size) 其中n是一共几个数据,size是每个数据所占字节数;

long  *p;
p=(long  *)malloc(5, 4);

③其他同malloc()函数;

  1. free()函数

①作用:释放由p指向的存储区,使这部分存储区归还给系统,以便再分配。

long *p;
p=(long  *)malloc(5, 8);    //申请
……                //使用
free(p);          //释放
  1. relloc()函数

①作用将p指向的存储空间大小改为size个字节,扩大或缩小原存储空间;就是说前面malloc()或calloc()函数分配的空间在运行中过大或过小,利用realloc()函数更改空间大小;

char *p;
p=(char  *)calloc(5, 8);
……
p=realloc(p, 10);    //将元素的个数增加到10个;
……
free(p)

③函数的返回值是新的存储空间的首地址,与原首地址不一定相同。若不一致,该函数会把原来的数据同步复制到新的空间里面,不会造成数据丢失;

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言中,数组名可以看作是一个指向数组首元素的指针。因此,可以通过数组名来访问数组中的元素。同时,也可以使用指针来访问数组中的元素。这种指向数组指针被称为数组指针。 定义数组指针的一般形式为: ``` 数据类型 (*指针变量名)[元素个数]; ``` 其中,指针变量名是你定义的数组指针变量名,数据类型是数组中元素的数据类型,元素个数是数组中元素的个数。 例如,定义一个指向int类型,元素个数为5的数组指针变量可以这样写: ``` int (*p)[5]; ``` 使用数组指针变量访问数组元素时,需要使用指针运算符*来解引用指针,然后再使用下标运算符[]来访问元素。例如,访问第3个元素可以这样写: ``` *(p+2); ``` 这里的p+2表示将p指向的地址加上2个int类型数据大小,得到的新地址即为第3个元素的地址。然后使用解引用符号*来获取该地址对应的元素值。 还可以使用指针数组来表示数组指针指针数组就是一个数组,其每个元素都是一个指针。例如,定义一个指向int类型,元素个数为5的指针数组可以这样写: ``` int *p[5]; ``` 使用指针数组来访问数组元素时,可以直接使用下标运算符[]来访问元素。例如,访问第3个元素可以这样写: ``` p[2]; ``` 这里的p[2]表示指针数组中第3个元素的地址,可以直接使用该地址来访问元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值