C语言第七部分(二维数组,字符数组)

C语言

二维数组

定义:

二维数组本质上是一个行列式的组合,也就是说二维数组是由行和列两部分组成。二维数组数据是通过行列进行解读

二维数组可被视为一个特殊的一维数组相当于二维数组又是一个一维数组,只不过它的元素是一维数组。(也就是说数组的元素可以是数组类型)

语法:

类型 数组名

举例:

int arr1[3][3]={{11,12,13},{21,22,23},{31,32,33}};// 等价于下面写法
int arr1[][3] ={{11,12,13},{21,22,23},{31,32,33}};// 柔性数组
int arr2[3][3] = {{11,12},{21,22,23},{31}};//等价于下面写法(柔性数组,根据最大列中的元素个数分配)
int arr2[3][3] ={{11,12,0},{21,22,23},{31,0,0}};
int arr3[][]= {{1,2,3},{4,5,6},{7,8,9}};// 这种写法,会编译报错

注意:

在C语言中,二维数组在计算机的存储顺序是按行进行的,即第一维的下标变化慢,第二维的下标变化快。

应用场合:

主要应用于数据有行列要求的情况。比如说我们现在要存储粤嵌目前在读班级的学生的成绩。

特殊写法:

  • 下标可以是整型表达式,如:a[2-1][2*2-1]
  • 下标可以是已经有值的变量或数组元素,如 a[2*x-1][b[3][1]]
  • 数组元素可以出现在表达式中,如:b[1][2]= a[2][3]/2

注意;使用是数组元素的下标应在已定义数组的大小范围内;应注意区别定义数组大小和引用数组元素的区别。

初始化:

  • 分行给二维数组赋初值
int arr[3][4]={{11,12,13,14},{21,22,23,24},{31,32,33,34}};
  • 可将所有数据写在一个花括号内,按照排列顺序对元素赋值

    int arr[3][4]={11,12,13,14,21,22,23,24,31,32,33,34};
    
  • 可对部分元素赋初值,其余未赋值部分自动填充 整型默认值-0 | 字符型默认值-\0 | 浮点型默认值-0.0…

int arr[3][4]= {{11},{21,22},{31}};
  • 若对全部元素赋初值,自定义数组时可以省略第1维数组的长度,第2维数组的长度必须指明。
int a[][4]={11,12,13,14,21,22,23,24,31,32,33,34};
  • 在分行赋初值时,也可以省略第1维的长度。
int arr[][4]={{11,12,13},{0},{0,10}};

案例:

#include <stdio.h>
/**
* 需求:二维数组案例-二维数组的遍历
*/
int arr_test1()
{
	// 创建一个二维数组,经过论证:二维数组我们必须指定列的大小,行的大小可以省略
	int arr[][3] = {{11},{21,22},{31,32,33}};//
	// 获取二维数组的大小,二维数组的大小其实就是行数
	int len = sizeof(arr) / sizeof(arr[0]);
	// 遍历二维数组,因为二维数组是行列式,所以要使用到双重for循环
	// 外层循环遍历外层数组,获取行
	for(int row = 0; row < len; row++)
	{
		// 获取列元素的总大小
		int len2 = sizeof(arr[row]) / sizeof(int);
		// 内层循环遍历内层数组,获取列(数据元素)
		for(int col = 0; col < len2;col++)
			{
				// 获取元素
				printf("%-3d",arr[row][col]);// 意思时获取数组arr第row行第col列
			}
		printf("\n");
	}
	printf("\n");
	}
int main(int argc,char *argv[])
{
	arr_test1();
	return 0;
}

案例:

#include <stdio.h>
/**
* 需求:二维数组案例-矩阵的转置(就是将一个2行3列的数组转换为3行2列的数组)
*/
int arr_test2()
{
	// 准备2个数组,存放转置前后的数列
	int arr_before[2][3] = {11,12,13,14,15,16}; // {{11,12,13},{14,15,16}}
	int arr_after[3][2] = {0}; // {{11,14},{12,15},{13,16}}
	// 计算arr_before中行数
	int r_len = sizeof(arr_before) / sizeof(arr_before[0]);
	// 遍历arr_before
	for(int i = 0; i < r_len; i++)
	{
		// 计算arr_before中的列数
		int c_len = sizeof(arr_before[i]) / sizeof(int);
		for(int j = 0;j < c_len;j++)
		{
			printf("%-4d",arr_before[i][j]);
			// 转置
			arr_after[j][i] = arr_before[i][j];// arr_before[1][0]-- arr_after[0][1]
		}
		printf("\n");
	}
	printf("\n");
	// 遍历arr_after
	for(int i = 0; i < sizeof(arr_after)/sizeof(arr_after[0]); i++)
	{
		// 计算arr_after中的列数
		int c_len = sizeof(arr_after[i]) / sizeof(int);
		for(int j = 0;j < c_len;j++)
		{
			printf("%-4d",arr_after[i][j]);
		}
	printf("\n");
	}
	printf("\n");
}
int main(int argc,char *argv[])
{
	arr_test2();
	return 0;
}

案例:

#include <stdio.h>
/**
* 需求:二维数组案例-准备一个int类型二维数组,求该数组中最大的值,以及对应的行号和列号。
*/
int arr_test3()
{
	// 准备一个二维数组
	int arr[][4] = {{1,2,3,4},{9,8,7,6},{-10,10,-5,2}};
	// 创建变量:最大值、行号、列号
	int max = arr[0][0],row = 0,col = 0;
	// 遍历集合
	for(int i = 0; i < sizeof(arr)/sizeof(arr[0]);i++)
	{
		for(int j = 0;j < sizeof(arr[i])/sizeof(arr[i][0]);j++)
		{
			// 判断最大值
			if(arr[i][j] > max)
			{
				max = arr[i][j];
				row = i;
				col = j;
			}
		}
	}
	printf("max=%d,row=%d,col=%d\n",max,row,col);
}
int main(int argc,char *argv[])
{
	arr_test3();
	return 0;
}

字符数组

概念:
元素类型为char字符型的数组,字符数组往往是用来存储字符串数据的。需要注意的一点是,我们C语言中的字符是字节字符。

​ 字节字符:也就是1个字符占1个字节,在C语言中,我们使用char表示字节。

测试题:

char b ='1';// 正确
char c= 65;// 正确
char d ="A":// 正确,ASCII码
char d[1]=“A”;//错误,这是字符串的写法,也是char数组的写法,
char e='司';//错误,中文一个字符超过1个字节

语法:

char 数组名[容量];
char 数组名[行容量【[列容量];

字符数组的语法就是我们前面所学的一维数组和二维数组的语法,只不过数据类型是char而已

注意:

​ 如果我们的char数组初始化的时候,没有完全赋完值的时候,空出来的地方使用\0进行填充。

比如:

char c[8] = {‘h’,‘e’,‘l’,‘l’,‘o’} 等价于 char c[8] = {‘h’,‘e’,‘l’,‘l’,‘o’,‘\0’,‘\0’,‘\0’}

案例:

#include <stdio.h>
/**
* 需求:字符数组案例-输出一个字符串(I LOVE YOU!)
*/
int char_test1()
{
	// 准备一个测试数组 ASCII中码0和码32对应的不是同一类的空
	char arr[11] = {'I',' ','L','O','V','E',32,'Y','O','U','!'};
	// 通过一个for循环进行遍历输出
	for(int i = 0; i < sizeof(arr)/sizeof(char);i++)
	{
		printf("%c",arr[i]);
	}
	printf("\n");
}
int main(int argc,char *argv[])
{
	char_test1();
	return 0;
}

案例:

#include <stdio.h>
/**
* 需求:字符数组案例-输出一个用字符组成的菱形图案
*/
int char_test2()
{
	// 准备数据
	char arr[5][5] = {
		{' ',' ','*',' ',' '},
		{' ','*','*','*',' '},
		{'*','*','*','*','*'},
		{' ','*','*','*',' '},
		{' ',' ','*',' ',' '}
	};
	// 遍历数组
	for(int i = 0; i < sizeof(arr)/sizeof(arr[0]);i++)
	{
		for(int j = 0; j < sizeof(arr[i])/sizeof(char);j++)
		{
			printf("%c",arr[i][j]);
		}
	// 每一行中的列元素输出完毕,执行换行
	printf("\n");
	}
	printf("\n");
}
int main(int argc,char *argv[])
{
	char_test2();
	return 0;
}

注意:

①如果定义时不初始化,元素值不确定;

char arr1[2]; // 此时属于未初始化元素值是不确定的(随机的)
char arr2[5] = {'a','b','c'}; // 此时属于不完全初始化,未初始化的元素使用\0进行填充

②如果提供的字符个数大于数组长度,则按语法错误处理;如果字符个数小于数组长度,后面的元素自动为空字符(\0)

③如果提供的字符个数与数组长度相同时,可省略数组长度,系统会自动确定元素个数,适合字符个数较多时。

字符传和字符串结束标志

说明:

  • C语言规定,字符串以字符\0 作为结束标志。
  • 编译系统对字符串常量自动加一个\0作为结束标志。
  • 程序中往往通过判断\0 来检测字符串是否结束。
  • \0 的ASCII码为0,不是一个可显示的字符,是“空操作符",它什么都不做,不会增加有效字符,仅是一个提供判别的标志。
字符数组的多样表示

我们的char数组可以以数组的方式一个个输出每个字符;我们的char数组也可以以字符串的方式整体进行输出所有字符。

/**
 *需求:字符数组→字符串
 */
# include <stdio.h>
{
	// 字符串的第1种表示:
	
}

注意:

  • 字符串的长度与字符数组的长度不一定相同

  • 利用字符串常量可以对字符数组进行初始化,但不能用字符串常量为字符数组赋值。

字符串的基础操作

​ 在用格式说明符%s进行输入输出时,其输入输出项均为数组名。但在输入时,相邻两个字符串之间要用空格分隔,系统将自动的在字符串最后加结束符"\0"。在输出时,遇到结束符"\0’作为输出结束标志。

​ 对于字符串的操作,我们需要使用到一些系统提供的函数。

字符串的输入
  • scanf(“%d”,数组名);

注意:采用scanf0进行字符串输入,要求字符串中不能存在空格,否则字符串遇到空格会结束。

案例:

#include <stdio.h>
/**
* 字符串的输入
* 语法:scanf("%s",数组名);
*/
int test1()
{
	// 创建一个char数组,用来存放人的名字
	char name[20];
	printf("请输入您的姓名:\n");
	scanf("%s",name);// 注意:如果是字符串,这里不是变量地址,是变量名,数组本身不占内存空间,数组默认指向第一个元素的首地址
	printf("您的姓名是%s\n",name);
}
int main(int argc,char *argv[])
{
	test1();
	return 0;
}
  • fgets(数组名,数组容量,sdtin)

功能:

​ 从键盘录入一个字符串到字符数组,返回字符数组的地址。

说明:

​ 采用fgets进行字符串输入,可获取所有输入的字符串,包含 \n ,在实际的字符串处理时,我们可能需要处理 \n

案例:

#include <stdio.h>
/**
* 字符串的输入
* 语法:fgets(数组名,数组容量,sdtin);
*/
int test2()
{
	// 创建一个char数组,用来存放人的名字
	char name[20];
	printf("请输入您的名字:\n");
	// fgets和scanf只能二选一
	fgets(name,sizeof(name)/sizeof(char),stdin);
	printf("您的姓名是%s\n",name);
}
int main(int argc,char *argv[])
{
	test2();
	return 0;
}

注意:

①如果输入的字符串不包括 空格 和 换行,可以使用scanf() |fgets();

②如果输入的字符串需要包含 空格 和 换行,只能使用fgets();

③经过对比,我们发现,在字符串的输入中,fgets();

字符串的输出
  • printf(“%s”,数组名);

案例:

#include <stdio.h>
/**
* 字符串的输出
* 语法:printf("%s",数组名);
*/
int test3()
{
	// 创建一个char数组,用来存放人的名字
	char name[20];
	printf("请输入您的姓名:\n");
	scanf("%s",name);// 注意:如果是字符串,这里不是变量地址,是变量名,数组本身不占内存空间,数组默认指向第一个元素的首地址
	printf("您的姓名是%s\n",name);
}
int main(int argc,char *argv[])
{
	test3();
	return 0;
}
  • puts(数组名)

功能:

​ 输出一个字符串

说明:

​ 字符串可以包含转义字符

案例:

#include <stdio.h>
/**
* 字符串的输入
* 语法:puts(数组名);
*/
int test4()
{
	// 创建一个char数组,用来存放人的名字
	char name[20];
	printf("请输入您的名字:\n");
	// fgets和scanf只能二选一
	fgets(name,sizeof(name)/sizeof(char),stdin);
	puts(name); // 无法进行拼接,只能输出
	printf("您的姓名是%s\n",name);
}
int main(int argc,char *argv[])
{
	test4();
	return 0;
}
字符串拼接
  • strcat(数组名,“需要拼接的字符串”);

引用:

#include <>string.h>

案例:

#include <stdio.h>
#include <string.h>
/**
* 字符串的拼接
* 语法:strcat(数组名,"需要拼接的字符串");
*/
int test5()
{
	// 创建一个char数组,用来存放人的名字
	char name[20];
	printf("请输入您的名字:\n");
	// fgets和scanf只能二选一
	fgets(name,sizeof(name)/sizeof(char),stdin);
	puts(strcat(name," 快跑!")); // 无法进行拼接,只能输出
}
int main(int argc,char *argv[])
{
	test5();
	return 0;
}

注意:

①字符数组1(字符串1)的长度必须足够大,以便于能容纳被连接的字符串。

②连接后系统将自动取消 字符串1(字符数组1)后面的结束符\0

③字符串2 可以是字符数组名,也可以是字符串常量,如:strcat(s1,“def”);

字符串拷贝
  • strcpy(数组名,字符串);
引用#include <string.h>

说明:

​ 这个函数适合给字符串赋值用

char str[16] = "一二三";//正确,初始化
cahr str[16]; str[16] = "一二三"//错误,赋值
char str[16]; strcpy(str,"一二三")//正确,借用函数完成赋值

案例:

#include <stdio.h>
#include <string.h>
/**
* 字符串的拷贝
* 语法:strcpy(数组名,"字符串");
*/
int test6()
{
	// 创建一个char数组,用来存放人的名字
	char name[20];
	printf("请输入您的名字:\n");
	// fgets和scanf只能二选一
	fgets(name,sizeof(name)/sizeof(char),stdin);
	strcpy(name,"一二三");
	printf("您的姓名是%s\n",name);
}
int main(int argc,char *argv[])
{
	test6();
	return 0;
}
字符串比较
  • strcmp(字符串1,字符串2)

引入:

#include <string.h>

功能:
比较两个字符串对应位置字符ASCII的大小(字典顺序比较)

返回值:

​ 若 字符串1 等于字符串2,返回0

​ 若字符串1 大于 字符串2,返回正整数

​ 若字符串1 小于字符串2,返回负数

说明:

①执行这个函数时,自左到右逐个比较对应字符的ASCI的值,直到发现了不同字符或字符串结束符^0’为止。

②对字符串不能用数值型比较符

③字符串1与字符串2可以是字符数组名,也可以是字符串常量。

案例:

#include <stdio.h>
#include <string.h>
/**
* 字符串的比较
* 语法:strcmp(字符串1,字符串2);
*/
int test7()
{
	// 创建一个char数组,用来存放账户和密码
	char username[20],password[8];
	printf("请输入您的账户:\n");
	scanf("%s",username);
	printf("请输入您的密码:\n");
	scanf("%s",password);
	if(!strcmp(username,"admin") && !strcmp(password,"123456"))
	{
		printf("登录成功!\n");
	}
	else
	{
		printf("账户或者密码错误!\n");
	}
}
int main(int argc,char *argv[])
{
	test7();
	return 0;
}
字符串长度
  • strlen(字符串)

引用:

#include <stdio.h>

注意:

​ 返回字符串中包含的字符的实际个数,不含 \0

案例:

#include <stdio.h>
#include <string.h>
/**
* 字符串的长度
* 语法:strlen(字符串|字符数组);
*/
int test8()
{
	// 创建一个char数组,用来存放账户和密码
	char username[20];
	printf("请输入您的账户:\n");
	scanf("%s",username);
	// 获取字符串的长度
	unsigned long len = strlen(username);
	if(!strcmp(username,"admin"))
	{
		printf("账户输入正确!%lu\n",len);
	}
	else
	{
		printf("账户输入错误!%lu\n",len);
	}
}
int main(int argc,char *argv[])
{
	test8();
	return 0;
}

案例1

输入一行字符,统计其中有多少个单词,单词之间用空格分隔开。I LOVE YOU

分析:采用通过空格统计单词的方法。具体是:

① 用连续若干个空格算一个、一行开头的空格不计的方法决定单词数目;

② 从第一个字符开始逐个检查字符串中的每一个字符。若查到某一字符非空格,而其前面的字符

是空格,则表示新单词开始,让计数变量num++。否则,当前字符非空格,前面字符也非空格,则

非新单词,num不变;

③ 用变量word=0或1来表示前面字符是空格或不是空格。则:

#include <stdio.h>
void main()
{
	char string[81];
	int i,num=0,word=0;
	char c;
	fgets(string,81,stdin); /*从键盘输入一个字符串*/
	for (i=0;(c=string[i])!='\0';i++) /*从第一个字符开始判断是否串尾*/
	{
		if(c==' ') word=0; /*如不是串尾,若是空格 I LOVE YOU*/
		else if(word==0) /*如不是串尾、不是空格,而前一字符是空格*/
		{
			word=1;
			num++;
		} /*是新单词,计数*/
	}
	printf("There are %d words in this line.\n",num);
}

案例2

有三个字符串,要求找出其中最大者。abc 1234 5678b a[],b[],c[],max[] if(strcmp(max,a) < 0)

max = a strcpy(max,a)

分析:设计一个二维字符数组str3,即3行20列。

① 可把str[0]、str[1]、str[2]看作3个一维字符数组,各有20个元素;

② 用gets函数分别输入3个字符串到str[0]、str[1]、str[2]中 ;

③ 用字符串函数对str[0]、str[1]、str[2]进行比较,得到最大者。

#include <stdio.h>
#include <string.h>
void main ( )
{
	char max[20];
	char str[3][20];// 输入3个字符串
	int i;
	// 完成初始化
	for (i=0;i<3;i++)
	gets(str[i]); /*输入3个字符串*/
	// fgets(str[i],20,stdin)
	if (strcmp(str[0],str[1])>0) /*比较,若串0>串1*/
		strcpy(max,str[0]); /*把串0存入string*/
	else
		strcpy(max,str[1]); /*否则,把串1存入string*/
	if (strcmp(str[2],max)>0) /*再比较,若串2>string*/
		strcpy(max,str[2]); /*把串2存入string,否则string不变*/
	printf("\nthe largest string is:\n%s\n",string); /*输出string*/
}

符ASCII的大小(字典顺序比较)

返回值:

​ 若 字符串1 等于字符串2,返回0

​ 若字符串1 大于 字符串2,返回正整数

​ 若字符串1 小于字符串2,返回负数

说明:

①执行这个函数时,自左到右逐个比较对应字符的ASCI的值,直到发现了不同字符或字符串结束符^0’为止。

②对字符串不能用数值型比较符

③字符串1与字符串2可以是字符数组名,也可以是字符串常量。

案例:

#include <stdio.h>
#include <string.h>
/**
* 字符串的比较
* 语法:strcmp(字符串1,字符串2);
*/
int test7()
{
	// 创建一个char数组,用来存放账户和密码
	char username[20],password[8];
	printf("请输入您的账户:\n");
	scanf("%s",username);
	printf("请输入您的密码:\n");
	scanf("%s",password);
	if(!strcmp(username,"admin") && !strcmp(password,"123456"))
	{
		printf("登录成功!\n");
	}
	else
	{
		printf("账户或者密码错误!\n");
	}
}
int main(int argc,char *argv[])
{
	test7();
	return 0;
}
字符串长度
  • strlen(字符串)

引用:

#include <stdio.h>

注意:

​ 返回字符串中包含的字符的实际个数,不含 \0

案例:

#include <stdio.h>
#include <string.h>
/**
* 字符串的长度
* 语法:strlen(字符串|字符数组);
*/
int test8()
{
	// 创建一个char数组,用来存放账户和密码
	char username[20];
	printf("请输入您的账户:\n");
	scanf("%s",username);
	// 获取字符串的长度
	unsigned long len = strlen(username);
	if(!strcmp(username,"admin"))
	{
		printf("账户输入正确!%lu\n",len);
	}
	else
	{
		printf("账户输入错误!%lu\n",len);
	}
}
int main(int argc,char *argv[])
{
	test8();
	return 0;
}

案例1

输入一行字符,统计其中有多少个单词,单词之间用空格分隔开。I LOVE YOU

分析:采用通过空格统计单词的方法。具体是:

① 用连续若干个空格算一个、一行开头的空格不计的方法决定单词数目;

② 从第一个字符开始逐个检查字符串中的每一个字符。若查到某一字符非空格,而其前面的字符

是空格,则表示新单词开始,让计数变量num++。否则,当前字符非空格,前面字符也非空格,则

非新单词,num不变;

③ 用变量word=0或1来表示前面字符是空格或不是空格。则:

#include <stdio.h>
void main()
{
	char string[81];
	int i,num=0,word=0;
	char c;
	fgets(string,81,stdin); /*从键盘输入一个字符串*/
	for (i=0;(c=string[i])!='\0';i++) /*从第一个字符开始判断是否串尾*/
	{
		if(c==' ') word=0; /*如不是串尾,若是空格 I LOVE YOU*/
		else if(word==0) /*如不是串尾、不是空格,而前一字符是空格*/
		{
			word=1;
			num++;
		} /*是新单词,计数*/
	}
	printf("There are %d words in this line.\n",num);
}

案例2

有三个字符串,要求找出其中最大者。abc 1234 5678b a[],b[],c[],max[] if(strcmp(max,a) < 0)

max = a strcpy(max,a)

分析:设计一个二维字符数组str3,即3行20列。

① 可把str[0]、str[1]、str[2]看作3个一维字符数组,各有20个元素;

② 用gets函数分别输入3个字符串到str[0]、str[1]、str[2]中 ;

③ 用字符串函数对str[0]、str[1]、str[2]进行比较,得到最大者。

#include <stdio.h>
#include <string.h>
void main ( )
{
	char max[20];
	char str[3][20];// 输入3个字符串
	int i;
	// 完成初始化
	for (i=0;i<3;i++)
	gets(str[i]); /*输入3个字符串*/
	// fgets(str[i],20,stdin)
	if (strcmp(str[0],str[1])>0) /*比较,若串0>串1*/
		strcpy(max,str[0]); /*把串0存入string*/
	else
		strcpy(max,str[1]); /*否则,把串1存入string*/
	if (strcmp(str[2],max)>0) /*再比较,若串2>string*/
		strcpy(max,str[2]); /*把串2存入string,否则string不变*/
	printf("\nthe largest string is:\n%s\n",string); /*输出string*/
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值