C语言数组篇

数组

数组是什么?

1.数组是数据的集合
2.数组的数据是同类型的 不能是又有整数 又有小数等。
3.数组地址连续的。

为什么要用?

需要大量数据同时也不关心名称的时候,比较方便。
对于数据个数比较多的时候,像我们想定义100个整型变量存放数据,你是不是我们直接定义 int a,b,c,d,e…到100个就好啦? 这显然是极其麻烦的并且傻瓜的一种做法。所以我们需要用到数组。

一维数组

如何定义?

类型 + 名字 + 多少个(多大)
例子:

创建一个能装100个数据的整型变量

整型 名字 个数
int array[100]; 

创建一个能装100个数据的浮点型变量

浮点型 名字 个数
float array[100];
如何初始化?

整型:

//定义了一个整型数组 个数5个 分别为1 2 3 4 5
int array[5] = {1,2,3,4,5}; 
//定义了一个整型数组 个数5个 部分初始化 分别为1 2 后面的默认没写是为 0 的
int array[5] = {1,2};

错误写法(越界):

int array{5} = {1,2,3,4,5,6,7,8}; //超出范围了 越界了 定义了5个 存放了8个

其他类型也一样。

浮点型:

//定义了一个浮点型数组 个数5个 分别为1.1 2.2 3.3 4.4 5.5
float array[5] = {1.1,2.2,3.3,4.4,5.5};
//定义了一个浮点型数组 个数5个 部分初始化 分别为1.1  后面的默认  为0.0
float array[5] = {1.1};

有时候你定义一个数组都得数一数元素个数,其实可以不用写多少个。
也可以这样定义:


int array[] = {1,2,3,4,5};
如何引用?

int a[3] = {1,2,3};
其实就是 a[0] = 1; a[1] = 2; a[3] = 2; 下标是从0开始算的
我们可以通过下标的方式访问。

打印单个数组数据
比如我想打印第数组的第5个数据array[4]

printf("%d\n",array[4]);
printf("%d\n",array[2*2]);

打印整个数组数据
首先打印得知道数组数据个数。你可能会说定义的时候不就写上了吗?
那我想说 int array[] = {1,2,3,4,5}; 这样呢?难道又去数数?
我们可以通过数组的大小来确定数组数据个数
int 类型是4字节。如果数组大小为8字节 那是不是就是数组个数为2。
像下面这样,比较推荐第一种来写。

length = sizeof(array)/sizeof(array[0]);
length = sizeof(array)/sizeof(int);
length = sizeof(array)/sizeof(4);

通过for循环来:

int array[5] = {1,2,3,4,5};
int array1[] = {1,2,3,4,5};

/*知道数组个数*/
for(i=0;i<5;i++)
{
	printf("%d ",array[i]);
}
/*=============================================*/
length = sizeof(array1)/sizeof(array1[0]);
/*不知道数组个数*/
for(i=0;i<length;i++)
{
	printf("%d ",array1[i]);
}

输出结果:1,2,3,4,5	(两个都是)
一维数组在内存中的存储

我们通过代码打印一下每个数据的地址吧

int array[] = {5,4,3,2,1};
int length; //计算数组个数
int i;
length = sizeof(array)/array[0];
for(i=0;i<length;i++)
{
	printf("array[%d]地址:%p\n",i,&array[i]);
}

输出结果:
array[0]地址:0060FED4
array[1]地址:0060FED8
array[2]地址:0060FEDC
array[3]地址:0060FEE0

发现了地址是从低往高存放的,地址是连续的 一个占4字节。

一维数组运用举例
一、找最大值
#include <stdio.h>
#include <stdlib.h>
int main()
{
	int i = 0;//遍历数组
    int array[5]; //存放数据
    int max = 0; //存放最大值
    while(i != 5)
    {
		printf("请输入第 %d 个数\n",i+1);
		scanf("%d",&array[i]);
        i++;
    }
    
    printf("数据: ");    
	for(i=0;i<5;i++)
	{
		printf("%d ",array[i]);
	}
	printf("\n");	
    max = array[0]; //把第一项给max 
    /*找最大值*/
    for(i=1;i<5;i++)
    {
		if(array[i] > max)
        {
			max = array[i];
        }
			
	}
	printf("最大值为%d\n",max);
    system("pause");
	return 0;
}

运行结果:
在这里插入图片描述

二、冒泡法排序(从小到大)

就是每次将相邻的两个数对比,把小的放到前面,如果有5个数:5 4 3 2 1。首先先5跟4对比 4最小 4放到前面 变成 4 5 3 2 1。然后继续5跟3对比,3最小,3放在前面。变成 4 3 5 2 1…直接看图吧。
在这里插入图片描述
我们会发现一个规律,总共进行了4轮(数组个数-1),每一轮都在减一。
那么通过for循环嵌套,如果i 代表是大的循环(4轮)j 表示里面互换次数的循环。

大循环好办 就是数组个数-1。 你5个 就for循环就是 4。

for(i=0;i<length-1;i++)
{
	
}

那么内循环 j 我们看图发现 第一轮进行了4次对比,正好是数组个数-1。第二轮进行了3次,第三轮进行了2次,第四轮进行了1次。
就是要j 第一次循环4次 第二次 循环3次 第三次 循环2次 第四次 1次。
刚好就是数组个数-i 就是大循环的次数-i

for(j=0;j<(length-1)-i;j++)
{
	我们得知数组个数为5 	5-1=4.
/*	第一轮i=0;	当j=0;		4-i = 4 	可以进行4次循环
	第二轮i=1;	当j=1; 		4-i = 3		可以进行3次循环
	第三轮i=2;	当j=2;		4-i = 2		可以进行2次循环	
	第四轮i=3;	当j=3;		4-i = 1		可以进行1次循环	 	*/
}

完整程序:

#include <stdio.h>

int main()
{
    int array[] = {5,4,3,2,1};
    int length; //计算数组个数
    int i,j;
    int max; 
	length = sizeof(array)/sizeof(array[0]); //计算出数组个数
    
	/*开始排序*/
    for(i=0;i<length-1;i++)
    {
		for(j=0; j<(length-1)-i;  j++)
        {
			if(array[j] > array[j+1]) //判断哪个大
            {
				max = array[j]; //大的给max
                array[j] = array[j+1]; //把小的放在前面。
                array[j+1] = max; //大的值放回后面
            }
        }
    }
    
    /*排序结果输出*/
    printf("从小到大:");
    for(i=0;i<length;i++)
    {
		printf("%d ",array[i]);
	}
    system("pause");
	return 0;
}

输出结果:1 2 3 4 5

二维数组

如何定义?

二维数组就相当于一个矩阵,有行有列。比如下面定义的就是两行三列。

int array[2][3];
如何初始化?

类型 + 名字 + [行]][列];
注意:二维数组变量定义的时候 必须要有列的大小 可以没有行
正确的定义并初始化:

int array1[2][3] = {{1,2,3},{4,5,6}};
int array2[2][3] = {1,2,3,4,5,6};
int array3[][3] = {{1,2,3},{4,5,6}};
int array4[][3] = {1,2,3,4,5,6};

错误定义

int array[][] = {{1,2,3},{4,5,6}}; //至少也要有列
int array[2][] = {{1,2,3},{4,5,6}}; //没有列
int array[2][3] {{1,2,3},{4,5,6},{7,8,9}};//越界 超出范围
如何引用?

比如:

int array[2][3] = {{1,2,3},{4,5,6}};

排列顺序:
array[0][0] —→ array[0][1] —→ array[0][2] 
array[1][0] —→ array[1][1] —→ array[1][2] 

下标是从0开始算的

打印单个数据
比如我想打印第一行,第二个数据 即 2 array[0][1];

printf("%d\n",array[0][1]);
printf("%d\n",array[0*0][1*1]); //显得有点多余。。。

打印整个数组数据
首先得知道行数 和 列数:

sizeof(array[0][0]);	为一个元素占用的空间,
sizeof(array[0]);	为一行元素占用的空间,
sizeof(array);	为整个数组占用的空间,

行:line = sizeof(array)/sizeof(array[0]);
列:column = sizeof(array[0]/sizeof(array[0][0]))

通过for循环打印全部数组


int i,j;
int array[2][3] = {{1,2,3},{4,5,6}};
int size,line,column;
size = sizeof(array);//获取大小
line = sizeof(array)/sizeof(array[0]); //行
column = sizeof(array[0])/sizeof(array[0][0]); //列
printf("size:%d\n",size);
printf("line:%d\n",line);
printf("column:%d\n",column);

for(i=0;i<line;i++)
{
	for(j=0;j<column;j++)
    {
		printf("array[%d][%d]:%d \n",i,j,array[i][j]);
    }
}

输出结果:

size:24
line:2
column:3
array[0][0]:1
array[0][1]:2
array[0][2]:3
array[1][0]:4
array[1][1]:5
array[1][2]:6
二维数组在内存中的存储

二维数组是按行存放的,在内存中先放第一行的 然后 第二…

通过编程来查看地址:

#include <stdio.h>

int main()
{
	int i,j;
	int array[2][3] = {{1,2,3},{4,5,6}};
    int size,line,column;
    size = sizeof(array);//获取大小
    line = sizeof(array)/sizeof(array[0]); //行
    column = sizeof(array[0])/sizeof(array[0][0]); //列
    printf("size:%d\n",size);
    printf("line:%d\n",line);
    printf("column:%d\n",column);
    for(i=0;i<line;i++)
    {
		for(j=0;j<column;j++)
        {
			printf("array[%d][%d]地址:%p \n",i,j,&array[i][j]);
        }
    }
    system("pause");
	return 0;
}

输出结果:
size:24
line:2
column:3
array[0][0]地址:0060FEC4
array[0][1]地址:0060FEC8
array[0][2]地址:0060FECC
array[1][0]地址:0060FED0
array[1][1]地址:0060FED4
array[1][2]地址:0060FED8

跟一维数组一样。

二维数组运用举例
一、推箱子地图绘制
#include <stdio.h>

int main()
{
	int i,j;
	int Map[8][8] = {
    0,0,1,1,1,0,0,0,
    0,0,1,2,1,0,0,0,
    0,0,1,0,1,1,1,1,
    1,1,1,3,0,3,2,1,
    1,2,0,3,4,1,1,1,
    1,1,1,1,3,1,0,0,
    0,0,0,1,2,1,0,0,
    0,0,0,1,1,1,0,0,
    };
    /*地图显示*/
    for(i=0;i<8;i++)
    { 
		for(j=0;j<8;j++)
		{	
			switch(Map[i][j])
			{	
				case 0: printf("  "); break;         
				case 1: printf("▇"); break;//围墙
				case 2: printf("★"); break; //目的地
				case 3: printf("●"); break; //箱子
				case 4: printf("♂"); break;//人      
			}
				if((j+1)/8==1) //够8次 换行
                {                
					putchar('\n');
                }
        }	
    }
	return 0;
}

输出结果:
在这里插入图片描述
如果有的运行结果不像图中这样 把符号变成其他。改成*啥的

二、实现二维数组行列互换。
#include <stdio.h>

int main()
{
	int array[2][3] = {{1,2,3},{4,5,6}};
    int newArray[3][2];
    int i,j;
    /*原有数组输出数据*/
	for(i=0;i<2;i++)
	{
		for(j=0;j<3;j++)
        {
			printf("array[%d][%d]: %d ",i,j,array[i][j]);
        }
        printf("\n");
    }
    /*变换行列*/
    for(i=0;i<2;i++)
    {
		for(j=0;j<3;j++)
        {
			newArray[j][i] = array[i][j];
        }
    }  
    /*新数组输出数据*/
    printf("\n=======变换行列结果========\n\n");
    for(i=0;i<3;i++)
	{
		for(j=0;j<2;j++)
        {
			printf("newArray[%d][%d]: %d ",i,j,newArray[i][j]);
        }
        printf("\n");
    }

	return 0;
}


输出结果:
array[0][0]: 1 array[0][1]: 2 array[0][2]: 3
array[1][0]: 4 array[1][1]: 5 array[1][2]: 6

=======变换行列结果========

newArray[0][0]: 1 newArray[0][1]: 4
newArray[1][0]: 2 newArray[1][1]: 5
newArray[2][0]: 3 newArray[2][1]: 6

字符数组

如何定义?

字符很显然我是用char类型对吧。
定义一个char类型数组 数组个数是10个。

char string[10];
如何初始化?

定义一个字符数组 存放HelloWorld。

char string1[10] = {'H','e','l','l','o','W','o','r','l','d'}; //这种比较麻烦
char string2[10] = "HelloWorld"; //这种是比较简单 没那么麻烦
char string3[] = "HelloWorld"; //这种更简单 省略数组个数
如何引用?

1.通过访问下标的方式 一个一个字符的输出。——for循环 或者 while()循环

通过访问下标的方式:————string1字符数组
int i;
//		i < string1整体大小 除以 string1首元素大小
for(i=0;i<sizeof(string1)/sizeof(string1[0]);i++)
{
	printf("%c",string1[i]);	
}
printf("\n"); //结束来个换行

输出结果:HelloWorld

2.通过%s输出字符串———string2 string3

//打印string2 内容:
printf("string2:%s \n",string2); string2 是指 字符串数组的首地址

//打印string3 内容:
printf("string3:%s \n",string3); string3 是指 字符串数组的首地址

输出结果:

输出结果:
string2:HelloWorld@
string3:HelloWorld

这里会发现 string2这个 打印出来字符串 在最后面有个乱码 这是为啥呢?
其实 在字符串中 字符串会默认以 ‘\0’ 这个符号 作为结束的标志

解决办法就是把	string2[10] 改成 string2[11]

我们可以打印一下string3这个大小。就知道其实后面有没有多了个元素。

printf("string3的大小:%d\n",sizeof(string3));

输出结果:
11

我们也可以通过检测’\0’ 来输出字符串:

int i = 0;
while(string3[i] != '\0')
{
	printf("%c",string3[i]);
	i++;
}

输出结果:
HelloWorld
字符数组在内存中的存储

其实这个可以猜到 char 类型是占一个字节的 那么他们的存储是连续的一次是一个字节。

字符数组运用举例
字符串逆序

就是最前面的元素和最后面的元素互换 第二个元素和倒数第二个元素互换…

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
	char string[] = "ABCDEF";
    int number; //存放插入位置
    int i;
    char str; //存放新字符
    int length;//获取字符串长度
    int moveNumber; //获取移动的次数
    printf("字符串为:%s\n",string);
   
    printf("你想在第几个插入字符?\n");
    scanf("%d",&number);
	getchar(); //吸收回车键

	printf("插入的字符为:\n");
    scanf("%c",&str);  
	getchar();
   
    printf("你想在%s 字符串 在第 %d 个插入字符 '%c' \n",string,number,str);

    length = strlen(string); //获取字符串的长度
    printf("字符长度:%d\n",length);
    
	if(length == number)
    {
		string[length+1] = string[length];//为防止乱码 往右移一位 在Linux上 不需要加这行代码
        string[length] = str; //插入数据
        printf("==============================\n");
		printf("插入后结果:%s\n",string);
		printf("==============================\n");
        return 0; //程序结束
    }
    
    
    moveNumber= length-number+1; //获取移动次数
    printf("移动次数:%d\n",moveNumber); 
	
	//每一次循环移动一次
	for(i=0;i<moveNumber;i++) 
    {	
		string[length-i] = string[length-1-i]; //往右移动
    }
    string[number-1] = str; //插入字符
    printf("==============================\n");
    printf("插入后结果:%s\n",string);
    printf("==============================\n");

	return 0;
}


运行程序结果:

字符串为:ABCDEF
你想在第几个插入字符?
2
插入的字符为:
G
你想在ABCDEF 字符串 在第 2 个插入字符 'G'
字符长度:6
移动次数:5
==============================
插入后结果:AGBCDEF
==============================
//注:如果最后有乱码 
//请把string[] = "ABCDEF" 改成 string[8] = "ABCDEF" 或者数组个数更大。

/*
为什么移动的时候是以下的代码? (都加上了-i)
string[length-i] = string[length-1-i]; //往右移动

为什么不是下面这个?
string[length] = string[length-1];
因为在移动的时候 for循环中 这个是永远都是把最后一个元素往右边移动  
*/

去掉字符串左边空格
#include <stdio.h>
#include <string.h>

int main()
{
	char string[] = "  hello"; //左边两个空格  
    int length = strlen(string); //获取字符串的长度
    int i = 0;
    int moveCount = 0; //记录需要移动的次数
    
    printf("长度为:%d\n",length);

    
    while(string[i] == ' ' && string[i] != '\0') //检测左边有多少个空格
    {
		i++;
        moveCount++; //记录次数
    }
    printf("字符串中左边有 %d 个空格.后面的每个元素需要移动次数 %d 次\n",moveCount,moveCount);
	/*也可以这么计算,增加一个标志位flag*/
	/*
	int flag = 1;
	for(i=0;i<length;i++)
    {
		if(string[i] == ' ' && string[i] != '\0' && flag == 1)
        {
			number++;
		}
        else
        {
			flag=0; //一旦出现了不是空格 则不再计算左边空格数据
        }
	}   
	*/


    /*循环次数:总共的字符串长度 - 左边的空格数*/
    for(i=0;i<length-moveCount;i++) 
    {
		string[i] = string[i + moveCount]; //将剩下的元素移动到前面
    }
    
    string[length-moveCount] = '\0'; //紧接着后面加个'\0'
    
    printf("sting:%s\n",string); //输出结果


	return 0;
}


输出结果:
长度为:7
字符串中左边有 2 个空格.后面的每个元素需要移动次数 2 次
sting:hello

去掉字符串右边空格
#include <stdio.h>
#include <stdlib.h>
int main()
{ 
	char string[] = "        hello       "; //字符串  
	int i;
    int number = 0; //计算字符串右边空格数量
    int length = strlen(string); //计算字符串长度
    printf("字符串长度为%d\n",length);
    
    for(i=0;i<length;i++)
    {
		if(string[i] == ' ' && string[i] != '\0') //计算字符串右边的空格个数
        {
			number++;
		}
        else
        {
			number=0;
        }
	}
	printf("右边空格有%d个\n",number);
    
    string[length-number] = '#'; //为了能看出空格 在最后加个#号
    string[length-number+1] = '\0'; 
    printf("string:%s\n",string);
	return 0;
}

输出结果:
字符串长度为20
右边空格有7个
string:        hello#
去掉字符串左边的空格和右边的空格

这个就是比较简单了 把上面的结合一下就行了。

#include <stdio.h>
#include <stdlib.h>

int main()
{ 
	char string[] = "     he llo       ";   
	int i;
    int leftNumber = 0;
    int rightNumber = 0;
    int flag = 1; //左边空格标志位
    int length = strlen(string);
    printf("字符串长度为%d\n",length);
    
    /*计算字符串左边的空格数*/
    for(i=0;i<length;i++)
    {
		if(string[i] == ' ' && string[i] != '\0' && flag == 1)
        {
			leftNumber++;
		}
        else
        {
			flag=0; //一旦出现了不是空格 则不再计算左边空格数据
        }
	}
	printf("左边空格有%d个\n",leftNumber);
    
    
	/*计算字符串右边的空格数*/
    for(i=0;i<length;i++)
    {
		if(string[i] == ' ' && string[i] != '\0')
        {
			rightNumber++;
		}
        else
        {
			rightNumber = 0; 
        }
	}
	printf("右边空格有%d个\n",rightNumber);
    
    
    /*循环次数:字符串总长度 去掉左边的空格数 和 右边的空格数*/
    for(i=0;i<length-leftNumber-rightNumber;i++) 
    {
		string[i] = string[i + leftNumber];  //有效的字符串往左移动 (左空格数)
    }
    
    string[length-leftNumber-rightNumber] = '#'; //为了方便好看出结果  在最后加上 # 号
    string[length-leftNumber-rightNumber+1] = '\0'; 
    printf("删除字符串的左边空格 和 右边空格结果 string:%s\n",string);
	return 0;
}


输出结果:
字符串长度为18
左边空格有5个
右边空格有7个
删除字符串的左边空格 和 右边空格结果 string:he llo#

关于函数传数组作为参数知识

记住一点:函数传参数 过去只能 数组的首地址。而不是整个数组。

#include <stdio.h>

void aaa(int array[5])
{
    printf("aaa函数结果\n");
    printf("%d\n",sizeof(array));//查看大小
    printf("%d\n",sizeof(array)/sizeof(array[0]));//查看个数
}

void bbb(int array[])
{
    printf("bbb函数结果\n");
    printf("%d\n",sizeof(array));//查看大小
    printf("%d\n",sizeof(array)/sizeof(array[0]));//查看个数
}


int main()
{
	int array[5] = {1,2,3,4,5};
	printf("main函数结果:\n");
    printf("%d\n",sizeof(array));//查看大小
    printf("%d\n",sizeof(array)/sizeof(array[0]));//查看个数
    aaa(array); //数组名就是地址 是数组第一个元素地址
    bbb(array);
    system("pause");
	return 0;
}


输出结果:
main函数结果:
20
5
aaa函数结果
4
1
bbb函数结果
4
1

在Linux底下aaa,或bbb函数 sizeof(array)是8个字节。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
• Table of Contents • Index • Reviews • Reader Reviews • Errata • Academic Python Cookbook, 2nd Edition By David Ascher, Alex Martelli, Anna Ravenscroft Publisher : O'Reilly Pub Date : March 2005 ISBN : 0-596-00797-3 Pages : 844 Copyright Preface The Design of the Book The Implementation of the Book Using the Code from This Book Audience Organization Further Reading Conventions Used in This Book How to Contact Us Safari® Enabled Acknowledgments Chapter 1. Text Introduction Recipe 1.1. Processing a String One Character at a Time Recipe 1.2. Converting Between Characters and Numeric Codes Recipe 1.3. Testing Whether an Object Is String-like Recipe 1.4. Aligning Strings Recipe 1.5. Trimming Space from the Ends of a String Recipe 1.6. Combining Strings Recipe 1.7. Reversing a String by Words or Characters Recipe 1.8. Checking Whether a String Contains a Set of Characters Recipe 1.9. Simplifying Usage of Strings' translate Method Recipe 1.10. Filtering a String for a Set of Characters Recipe 1.11. Checking Whether a String Is Text or Binary Recipe 1.12. Controlling Case Recipe 1.13. Accessing Substrings Recipe 1.14. Changing the Indentation of a Multiline String Recipe 1.15. Expanding and Compressing Tabs Recipe 1.16. Interpolating Variables in a String Recipe 1.17. Interpolating Variables in a Stringin Python 2.4 Recipe 1.18. Replacing Multiple Patterns in a Single Pass Recipe 1.19. Checking a String for Any of Multiple Endings Recipe 1.20. Handling International Text with Unicode Recipe 1.21. Converting Between Unicode and Plain Strings Recipe 1.22. Printing Unicode Charactersto Standard Output

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皮卡丘吉尔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值