【C语言】数组(详细讲解+源码展示)上

简介: 笔记

数组概述


在程序设计中,为了方便处理数据把具有相同类型的若干变量按有序形式组织起来——称为数组。


30.png


数组就是在内存中连续的相同类型的变量空间。同一个数组所有的成员都是相同的数据类型,并且所有的成员在内存中的地址是连续的。


--我们可以将一个数组分解为多个数组元素:这些数组元素可以是基本数据类型或构造类型。


int a[100];  //基本数据类型
struct Stu p[100];    //构造

(注:构造数据类型:数组类型、枚举类型enum、指针类型、引用类型、结构体struct、联合体union(又称联合,共用体)、class类等。)


--按数组元素类型的不同,数组可分为:数值数组、字符数组、指针数组、结构数组等类别。


int a[100] ;    //数值数组
char s[100] ;    //字符数组
char *p[100] ;    //指针数组
struct Peo n[100] ;    //结构数组

数组元素下标的个数也称为维数,我们可以根据维数的不同,将数组分为一维数组、二维数组、三维数组...... 我们在通常情况下将一维数组以上的数组称作多维数组 。


一维数组


如何使用一维数组

一维数组的定义包括以下几点要求:


数组名字符合标识符的书写规定(数字、英文字母、下划线) 。

数组名不能与其它变量名相同 。

方括号[]中常量表达式表示数组元素的个数 。

//方括号中的数量是其数组所包含元素,但其下标应该从0开始 。
a[3] 包含 a[0], a[1], a[2] 三个元素
//0, 1, 2分别表示其元素下标 。

好了,你已经掌握了一维数组的使用,下面就来练习以下一位数组的创建以及赋值吧。

代码如下;

#include <stdio.h>
int main()
{
  int a[100] ;    //在这里我们定义了一个数组a,a有100个成员,每个成员都是int类型
  //没有a这个变量,a是数组的名字,但不是变量名,它是常量
  int i = 0;
  for (i = 0; i < 100; i++)
  {
    a[i] = i; //给数组赋值 让a[0] = 0, a[1] = 1 ... a[i] = i ;
  }
  //遍历数组,输出每个成员的值
  for (i = 0; i < 100; i++)
  {
    printf("%d ", a[i]);
        printf("\n");
  }
  printf("\n");
  return 0;
}

一维数组的初始化

我们在定义数组的同时进行赋值,就叫做初始化。如果全局数组不做初始化,那么编译器将其初始赋值为零。但是局部数组如果不进行初始化,那么其内容将为随机值。

#include <stdio.h>
int b[5] ;  //定义全局数组 
int main()
{
  int a[5] = { 1, 2, 3, 4, 5 }  ; //定义一个数组并进行初始化 
  int c[5] ;  //定义局部数组
  int d[] = {1, 2, 3} ; //如果[]中不定义元素个数,定义时必须初始化 
  int e[5] = { 0 };//所有的成员都设置为0
  printf("%d\n", a[0]) ;
  printf("%d\n", b[0]) ;
  printf("%d\n", b[2]) ;
  printf("%d\n", c[0]) ;
  printf("%d\n", c[2]) ;
  return 0;
}

运行结果

31.png

这个运行结果就很好的展示了我们上面所讲到的知识。


数组名

一个数组方括号外的就是该数组的数组名,例如;a[10] , a就是该数组的数组名。数组名是一个地址的常量,代表数组中首元素的地址。


下面案例中我们会用到一个函数,那么在这里我们就提前为大家普及一下,sizeof()函数。


sizeof 是一个关键字,它是一个编译时运算符,用于判断变量或数据类型的字节大小。sizeof 运算符可用于获取类、结构、共用体和其他用户自定义数据类型的大小。


sizeof的语法:


sizeof (object) ;

其中object是我们要去计算大小的数据类型,这些数据类型包括类、结构、共用体和其他用户自定义数据类型。


好了,了解那么多之后我们就看一下这串代码吧。

#include <stdio.h>
int main()
{
  int a[5] = { 1, 2, 3, 4, 5 }; //定义一个数组并初始化所有成员变量 
  printf("%p\n", a) ;   //数组名是一个地址的常量,代表数组中首元素的地址。 
  printf("%p\n", &a[0]) ; // a和a[0]的地址是相同的 
  int n = sizeof(a) ;     //数组占用内存的大小,5个int类型,5 * 4  = 20
  int n0 = sizeof(a[0]) ;   //数组第0个元素占用内存大小也就是这个数组中每个元素内存的大小。 
  int i = 0;
  for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)  // sizeof(a) / sizeof(a[0]就是数组中元素个数
  {
    printf("%d ", a[i]);
  }
  printf("\n");
  return 0;
}

输出结果:


1.png

根据输出结果我们就能证实: 数组名代表数组中首元素的地址。


代码中出现的( sizeof(a) / sizeof(a[0] )这个就是利用整个数组的大小与数组中单个元素的大小相除就可以得到我们数组中的元素了 。


一维字符教组

一维字符数组一般用于存储和表示一个字符串,在 C 语言中,一般以空字符 '0' (ASCII 值为 0)作为字符串结束的标志。


一维字符教组的定义

一维字符数组定义与一维数组相差不大,其格式为:

char 数组名[数组大小] ;

例如:

char a[10] ;

该语句定义了一个一维字符数组 a,大小为 10,即占 10 个字符变量空间,最大可存储长度为 9 的字符串(第 10 个字符为 '\0')。由于没有显式给每个字符变量赋值,故每个字符变量为随机值。


一维字符数组初始化

以为字符数组在初始化时可以采用单个字符逐个赋值的方式初始化,也可以使用字符串初始化的方式。


1)逐个字符赋值


我们在逐个字符赋值的时候可能会出现以下三种情况。


a.当字符个数少于数组空间大小时


比如:

char a[8] = {'h','e','l','l','o'} ;    //始值个数5小于数组a空间个数8

该语句定义了含 8 个字符变量的一维字符数组a,前 5 个字符变量分别显式初始化为 'h','e','l','l','o' 等 5 个字符,后 3 个字符变量为空字符 '\0'。

2.png

当字符数组中含有字符串结束字符 '\0' 时,这时我们就可以使用 printf 函数和格式控制符 %s,输出该字符数组中的字符串 。其中格式控制符 %s,从输出列表中的该地址开始,到第一次遇到 '\0' 为止,这之间的字符全部输出。

printf ("%s”,a) ;

并且我们在进行一维数组初始化时,其第一维大小可以省略 。


char a[] = {'h','e','l','l','o'} ;

而这时储存的形式就变成了这样:


3.png


这时数组中就不存在\0了,也就是说我们不可以使用不能使用%s去进行输出了。 所以char a[8] = {'h','e','l','l','o'}  与 char a[] = {'h','e','l','l','o'} 并不是等价关系。


b.当字符个数等于数组空间大小时


比如:


char a[5]={'h','e','l','l','o'} ;    //初值个数5等于数组大小5

此语句的执行结果如下图:

3.png

可以发现,这时char a[5]={'h','e','l','l','o'} 与 char a[] = {'h','e','l','l','o'}就成为了等价关系。同样该字符数组中不包含字符串结束标志 '\0',故不能使用 printf("%s",c); 输出其中的字符串。


所以对于这种数组,我们通常会采用for循环的形式去输出该字符数组。

int i;
for(i=0;i<5;i++) 
{
    printf ("%c",a[i]) ;
}


c.当字符个数多于空间大小时


我们在初始化的时候,当字符个数多于空间大小时,编译时报错。

char a[4] = {'h','e','l','l','o'}; //初值个数5大于数组大小4

报错:

4.png

2)字符串初始化赋值


在 C 语言中,字符串一般是指含有字符串结束符 '\0' 的若干个字符的集合。而使用双引号括起来的字符串常量,默认隐含字符串结束符 '\0'。


char a[15] = {"Hello World"}; //注意该数组大小应足够大 不然会报错

并且我们在用字符串对字符数组初始化时,一般大括号可以去掉,即:


char a[15] = "Hello World"  ;

这时我们的语句的等价关系就是:


char a[15] = {"Hello World"} ;
//等价于 
char a[15] = "Hello World"  ; 
//等价于
char a[15]= {'H','e','l','l','o',' ','W','o','e','l','d','\0','\0','\0','\0'} ; 
//等价于
char a[15]= {'H','e','l','l','o',' ','W','o','e','l','d','\0'} ;
//等价于
char a[15]= {'H','e','l','l','o',' ','W','o','e','l','d'} ;

其中,其数组大小都是我们指定的15 。 而储存形式也如下图所示。

5.png



为了防止字符个数超出数组空间的现象,我们在采用字符串对字符数组进行初始化时,一般省略一维数组空间的大小,即:


char a[] = {"Hello World"} ;

该数组中除了存储字符串中的 11 个有效字符外,还自动在字符串的结尾存储 '\0' 字符。所以该数组的大小为 12。其存储形式如下所示。

6.png

为节省空间以及书写方便防止不必要的失误,当我们采用用字符串对字符数组初始化时,一般均省略其一维的大小。


一维字符数组的引用

字符数组中的每一个元素都是一个字符,所以我们可以使用下标的形式来访问数组中的每一个字符。


char a[]="abcd" ;

定义了一个一维字符数组 a,用字符串常量对其初始化,该a数组大小为 5,前 4 个元素的值分别为 'a'、'b'、'c'、'd',第 5 个元素的值为 '\0'。其存储形式如下所示。

7.png


我们可以使用 a[i] 引用该数组中的每个元素,例如:


int i;
for(i=0;c[i]!='\0';i++) //当前i号位置的字符变量只要不是结束符就输出
    printf("%c",a[i]) ;

其中for循环使用 '\0' 作为判断依据也可以很好的避免了计算长度所带来的复杂程度。


相关文章
|
2月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
284 9
|
1月前
|
传感器 算法 安全
【C语言】两个数组比较详解
比较两个数组在C语言中有多种实现方法,选择合适的方法取决于具体的应用场景和性能要求。从逐元素比较到使用`memcmp`函数,再到指针优化,每种方法都有其优点和适用范围。在嵌入式系统中,考虑性能和资源限制尤为重要。通过合理选择和优化,可以有效提高程序的运行效率和可靠性。
150 6
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
87 5
|
2月前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
2月前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
2月前
|
存储 NoSQL 编译器
C 语言中指针数组与数组指针的辨析与应用
在C语言中,指针数组和数组指针是两个容易混淆但用途不同的概念。指针数组是一个数组,其元素是指针类型;而数组指针是指向数组的指针。两者在声明、使用及内存布局上各有特点,正确理解它们有助于更高效地编程。
|
2月前
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
70 4
|
2月前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
126 16
|
2月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
170 7
|
2月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
139 8

热门文章

最新文章