四:C语言细节代码解析:数组使用(赋值,索引),二维矩阵数组(主对角线,次对角线,上三角,下三角),字符处理函数 strlen,strcpy,strcat,strlen, 字符串长度如何区分

目录

 一:数组概念

二:数组定义 

注意点

一维数组初始化

二维数组初始化

字符数组初始化

辨别字符数组和字符串

二维字符数组

数组元素引用

二维数值数组

 N*N数组(方阵)的特点

错题

字符串数组长度以及字符串长度

会区分转义字符和字符串结束符

字符串函数 

 strlen(数组地址)  字符串求长度, 遇到'\0'结束,不算‘\0’

会看字符串有效长度

strcpy   字符串赋值(覆盖)

 strcmp(地址1,地址2)字符串比较, 

strcat(地址1,地址2)字符串追加


 一:数组概念

具有相同类型和名称的变量集合,这些变量就是数组元素,个数确定,连续存放

用循环处理数组,不能整体使用。

二:数组定义 

数据类型  数组名[长度];  长度为整形常量或者整形常量表达式

正确形式举例

#define N 10
void main()
{
	int arr[5];
	int arr[N];
	int arr[] = { 1,2,3 };
}

错误形式举例

void main()
{
	int n = 10;
	int arr[1.1];// 错误长度不是整形
	int arr[n];// 错误,长度不能为变量
 	int arr[]; // 错误,前面不给长度,后面还不给元素,编译器就懵逼了
    int arr[0];//更不行
}
注意点
  1. 先定义后使用
  2. 数组名必须为合法标识符,不能与其他变量同名
  3. 数组名是地址常量
  4. 长度必须为整形常量或者整形常量表达式

一维数组初始化

  1. 对全部元素初始化;可以省略长度
    int arr[]={1,2,3}
  2. 对于部分元素初始化;不可以省略长度,其余的元素会补0(\0)
  3. 不允许指明的长度小于实际的长度
    int arr[1]={1,2};//错误
  4. 即使数组元素全部相等,也不能整体赋值
  5. 字符数组初始化方法
    	//字符
        char s1[] = { 'c','h','e','n'}; //没有\0这个是字符,不能用puts输出
    	puts(s1);// 找到\0才会停止
    
        	//字符串
    	char s1[] = { 'c','h','e','n','\0'}; 
    	char s2[5] = "chen";  //这两种方式定义的是字符串,等价
    	//可以用puts输出
    	puts(s1); //puts自带换行功能 
    	printf("%s\n", s2);// 等价

二维数组初始化

  1. 按行给二维数组赋初值
        //把第一个括号内的元素赋值给第一行
    	//不考虑内存对其,这个两个数组的存放方式相同
    	int arr[2][3] = { {1,2,3},{4,5,6}};//二维数组按行存放连续
    	int arr1[6] = { 1,2,3,4,5,6 };

  2. 第二种方式一次赋初值
    int arr[2][3] = { 1,2,3,4,5,6 };

  3. 对部分元素赋初值
    	//第一行第一个元素初始化为1, 第二行第一个元素初始化为3
    	//未初始化的默认为0
    	int arr[2][2] = { {1},{3} };//正确 
    	//int arr[3][3] = { {1},{},{3} }; 错误括号里必须要有东西
    	int i, j;
    	for (i = 0; i < 2; i++)
    	{
    		for (j = 0; j < 2; j++)
    			printf("%d\t", arr[i][j]);
    	}

    输出

  4. 全部赋初值为0
    int arr[2][2] = { 0 };//全部赋初值为0

  5. 给全部元素或者按行赋初值,行数可以省略,列数不可省略
    	//以下都是正确形式
        int arr[][2] = { {1,2},{3,4} };
    	int arr2[][2] = { {1},{3} };
    	int arr3[][2] = { 1,2,3,4 };
    int arr[][2];// 错误 不能又没有行数,元素还不给出来

字符数组初始化

辨别字符数组和字符串
  1.   存的是字符还是字符串,看看右面有没有放\0的位置就可以知道
    	//字符
        char s1[] = { 'c','h','e','n'}; //没有\0这个是字符,不能用puts输出
    	puts(s1);//错误 找到\0才会停止
        char s2[]={"chen"};
    
        	//字符串
    	char s1[] = { 'c','h','e','n','\0'}; 
    	char s2[5] = "chen";  //这两种方式定义的是字符串,等价
    	//可以用puts输出
    	puts(s1); //puts自带换行功能 
    	printf("%s\n", s2);// 等价
    `char arr[] = { "chen" };` 和 `char arr1[] = "chen";` 
    这两种声明数组的方式看似相似,但实际上有细微的区别:
    
    1. `char arr[] = { "chen" };`:
       - 这是一个不太常见的声明方式。
       - 它实际上是创建了一个字符数组,数组的每个元素都是一个字符。
       - 在这个声明中,`"chen"` 被视为一个字符数组,
    所以整个字符串作为一个单独的元素被放入到 `arr` 数组中。
    这可能导致编译错误或者意想不到的行为,因为字符串字面量实际上是字符数组。
    
    注意:
      如果你的编译器没有报错并接受了 `char arr[] = { "chen" };` 这种声明方式,
    那么可能是编译器的特定行为或者对C标准的某种解释。然而,
    这并不是标准C语言中推荐的声明方式。在大多数情况下,这种声明可能会导致未定义的行为。
    
       关于 `\0` 的包含情况,如果编译器接受了这种语法,
    它可能会将 `"chen"` 视为一个指向字符数组的指针,
    并尝试将这个指针作为数组的第一个元素。这样,`arr` 实际上将包含指针的值,
    而不是字符串 `"chen"` 的单个字符。在这种情况下,数组不会包含空字符 `\0` 作为其元素。
    
      为了更清楚地理解编译器的行为,你可以检查 `arr` 的内容,
    例如,通过打印数组的每个元素或查看内存表示。
    这样可以帮助你确定编译器实际上是如何处理这种声明的。
    但请记住,即使你的编译器接受这种语法,它也可能不是跨不同编译器或平台的可移植或可靠的做法。
    
    2. `char arr1[] = "chen";`:
       - 这是一种常见的声明方式。
       - 它创建了一个字符数组,并自动计算数组的大小,包括结尾的空字符 `\0`。
       - 数组 `arr1` 将包含字符 `'c'`, `'h'`, `'e'`, `'n'`, 和一个结尾的空字符 `\0`,总共5个字符。
    
    总的来说,第二种声明方式 `char arr1[] = "chen";` 是正确且常用的,而第一种方式可能不会按预期工作。通常在C语言中声明字符串时,应该使用第二种方式。
    二维字符数组
  2. 二维字符数组
    在C语言中,声明 `char arr[3][4];` 定义了一个二维字符数组。
    这里的 `3` 和 `4` 分别代表数组的维度大小:
    
    - `3` 表示这个数组有3行。
    - `4` 表示每行数组有4个字符。
    
    所以,`arr` 是一个包含3行,每行4个字符的二维数组。
    你可以将它视为一个字符表格,
    其中每行可以包含一个最多3个字符的字符串(考虑到字符串末尾的空字符 `\0`)。
    
    例如,你可以这样初始化这个数组:
    
    ```c
    char arr[3][4] = {
        "row1",
        "row2",
        "row3"
    };
    ```
    
    在这个例子中,每行都包含了一个3字符的字符串
    和一个隐含的空字符 `\0` 作为字符串的结尾。这种结构非常适合存储一系列的短字符串
    //输出演示
    void main()
    {
    	// 行标为字符串个数,列标为字符串长度
    	char arr[][7] =
    	{
    	   "Chen",
    	   "is",
    	   "a",
    	   "cool",
    	   "guy",
    	   "indeed",
    	};
    	//使用行标,访问某一个字符串
    	puts(arr[0]); // 输出 Chen
    	printf("%s %s", arr[1], arr[2]);  // 输出is a
    	//使用行标和列标可以进到字符串里面,输出单个字符
    	printf("%c", arr[4][0]);  //输出 g
    }
    void main()
    {
    	char arr[5][5];
    	//方式1单个输入
    	scanf("%s", arr[1]); //输入放在第一行, scanf不能接收空格
    	gets(arr[1]);//输入放在第二行, 可以接收空格,遇到换行符结束
    
    	//方式2使用循环对整体初始化
    	int i;
    	for (i = 0; i < 5; i++)
    	{
    		gets(arr[i]);// 按回车输入下一个字符
    	}
    
    	//输出字符串
    	for (i = 0; i < 5; i++)
    	{
    		puts(arr[i]);
    	}
    }

    ​​​​​​​

 B

 B

 D

数组元素引用

  1. 格式 : 数组名[下标]     
  2. 下标: 从0到长度减1, 如定义 int arr[5]; 下标的上线为 5-1=4 ;C对下标越界不检查
  3. 可以为整形变量,整形表达式,数组元素,返回值函数调用
    //都对
    int test() {
    	return 3;//返回下标3
    }
    void main()
    {
    	int a = 3;
    	int arr[] = { 1,2,3,4,5 };
    	arr[a] = 666;
    	arr[test()] = 666;
    	arr[1 + 2] = 666;
    }
  4. 每个元素相当于一个变量,变量这么用元素就怎么用
  5. 定义完成后不能对整个数组进行操作,一般是用循环配合元素
    arr = {1, 2, 3, 4, 5}; // 错误!不能在声明之后这样赋值
    

二维数值数组

格式: 数组名[下标][下标]

void main()
{
	int arr[2][3] = { 1,2,3,4,5,6 };
	int i, j;
	for (i = 0; i < 2; i++) {
		for (j = 0; j < 3; j++)
		{
			printf("%d\t", arr[i][j]);
		}
		printf("\n");
	}
}

 N*N数组(方阵)的特点

例如: int arr[2][2]={1,2,3,4};    其中 i=2,j=2,N=2

主对角线元素   i=j

次对角线元素 i+j=N-1

下三角  i<=j  行标小于列标

上三角 i>=j  行标大于列标

这些表达式是用于在二维数组(特别是方阵)中识别和处理不同部分的元素的常见方法。
假设有一个 `N*N` 的二维数组 `arr[N][N]`,其中 `i` 和 `j` 分别表示行索引和列索引,
它们都是从 0 开始的。下面解释这些表达式的含义:

1. **主对角线元素 `i=j`**:
   - 在一个方阵中,主对角线是从左上角到右下角的斜线。
   - 主对角线上的元素满足行索引和列索引相等,即 `arr[i][i]`。
   - 例如,在一个 3x3 矩阵中,主对角线上的元素是 `arr[0][0]`, `arr[1][1]`, `arr[2][2]`。

2. **次对角线元素 `i+j=N-1`**:
   - 次对角线(有时称为反对角线)是从右上角到左下角的斜线。
   - 次对角线上的元素满足行索引和列索引之和等于 `N-1`。
   - 在一个 3x3 矩阵中,次对角线的元素是 `arr[0][2]`, `arr[1][1]`, `arr[2][0]`。

3. **下三角 `i>=j`(行标大于等于列标)**:
   - 下三角包含主对角线和主对角线以下的所有元素。
   - 对于数组中的任意元素 `arr[i][j]`,如果 `i` 大于等于 `j`,则该元素位于下三角。
   - 在 3x3 矩阵中,下三角的元素是 `arr[0][0]`, `arr[1][0]`, `arr[1][1]`, `arr[2][0]`, `arr[2][1]`, `arr[2][2]`。

4. **上三角 `i<=j`(行标小于等于列标)**:
   - 上三角包含主对角线和主对角线以上的所有元素。
   - 对于数组中的任意元素 `arr[i][j]`,如果 `i` 小于等于 `j`,则该元素位于上三角。
   - 在一个 3x3 矩阵中,上三角的元素是 `arr[0][0]`, `arr[0][1]`, `arr[0][2]`, `arr[1][1]`, `arr[1][2]`, `arr[2][2]`。

理解这些概念对于处理矩阵和执行相关的算法非常重要,
尤其是在涉及线性代数、图像处理或者数据结构方面的编程中。

 

3  3

2  2 

12      13 

 D

D

 C

3 5 7

错题

7,0 

字符串数组长度以及字符串长度

字符数组的长度: 占内存字节的个数 ; 使用sizeof(数组名), 测试

字符数组中存放字符串长度:  有效字符串个数  \0之前,不含\0

void main()
{
	char arr[] = "Chen\0 is a cool guy"; //末尾还隐藏了个\0
	printf("字符数组占内存大小=%d\n", sizeof(arr));// 算空格
	printf("有效字符串的长度=%d", strlen(arr));
}

注意:字节个数,末尾有\0也要补\0

长度数到\0结束就可以

会区分转义字符和字符串结束符
void main()
{
	char arr[] = "\\n\078\087\0";
//解释  第一个'\'就是告诉后面的'\'你就是个'\',所以这两个算一个
// 'n'自己算一个
//'\07' 这个8进制的字符表示形式 算一个
// '8' 自己算一个
// '\0' 直接结束了(不算字符串长度),因为他后面是8,他俩想在一起条件也不允许啊
// 末尾有'\0', 系统也会自动在补上一个'\0'
	printf("字符数组占内存大小=%d\n", sizeof(arr));
	printf("有效字符串的长度=%d", strlen(arr));
}

 A

 A

 A

 

字符串函数 

导入  #include<string.h>

 strlen(数组地址)  字符串求长度, 遇到'\0'结束,不算‘\0’

会看字符串有效长度
void main()
{ 
	                              //strlen测试的结果
	char s0[] = "0111\0116";       // 6
	char s1[] = "0111\0a";         //4
	char s2[] = "\xaa\08\n";        //1
	char s3[] = "\t\n\\\0888";      // 3
	char s4[] = { '1','2','\0','3' }; //2
	printf("%d\n", strlen(s0));
	printf("%d\n", strlen(s1));
	printf("%d\n", strlen(s2));
	printf("%d\n", strlen(s3));
	printf("%d\n", strlen(s4));
}

strcpy   字符串赋值(覆盖)

strcpy(地址1,地址2);  把地址2的指向内容(带上自己的'\0')复制到地址1然后:在末尾追加'\0'

可以用于对字数组的赋值

void main()
{
    char arr[10] = "initial";
    //arr = "error";  不对
    strcpy(arr, "true");
    puts(arr); //输出 true
}

strcpy 如果原来的数组里面有数据,会覆盖原来的数据。从头开始。   有多长覆盖就覆盖多长

 strcmp(地址1,地址2)字符串比较, 

比较的是ASCII,一次比较; 

 返回值 >0, 地址1大

 <0 二大,

=0两者相等, (感觉和汇编的很像呢!,dest-src) 

void main()
{
	char s0[] = "aab";
	char s1[] = "aba";
	if (strcmp(s0, s1) > 0)
		printf("s0 nb");
	else
		printf("s1 nb"); //必然输出这个
}

strcat(地址1,地址2)字符串追加

功能:把2追加到 1上,并在末尾补‘\0’ ;

从地址1的\0处 开始追加 ,也就是把地址1的'\0'覆盖

void main()
{
	char s0[10] = "ch"; // 最好给被追加的数组来个长度
	char s1[] = "en";
	strcat(s0, s1);
	puts(s0); //输出 chen	
}
//不一样哦
void main()
{
	char s0[10] = "c\0h"; // 找到\0,直接开始追加
	char s1[] = "hen";
	strcat(s0, s1);
	puts(s0); //输出 chen	
}

void main()
{
	char s1[100] = "aachen", * p;
	p = s1 + 2; //指向 c的地址 等价于 p=&s1[2]
	strcpy(s1, p);// s1里面存放的内容  chen\0en\0
	puts(s1); //输出chen
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小萌新上大分

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

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

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

打赏作者

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

抵扣说明:

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

余额充值