C语言 | 第十三章 | 二维数组 冒泡排序 字符串指针 断点调试

news/2024/10/11 2:37:01/

P 120 数组应用案例 2023/1/29

一、应用案例

案例一:创建一个char类型的26个元素的数组,分别 放置’A’-'Z‘。使用for循环访问所有元素并打印出来。提示:字符数据运算 ‘A’+1 -> ‘B’

#include<stdio.h>void main(){/*创建一个char类型的26个元素的数组,分别 放置'A'-'Z‘。使用for循环访问所有元素并打印出来。提示:字符数据运算 'A'+1 -> 'B*/char arr[26];int i;for(i = 0; i < 26 ; i++){arr[i] = 'A' + i; // 第一个是0,A+0依然是0}for(i = 0; i < 26; i++){printf("arr[%d]=%c\n",arr,arr[i]);}getchar();
}

案例二:请求出一个数组的最大值,并得到对应的下标。

#include<stdio.h>
void main(){/*请求出一个数组的最大值,并得到对应的下标。分析:1.自定义数组大小52.假定第一个元素max= arr[0]就是最大值,然后我们依次和数组后面的数进行比较,如果发现有比max更大的数,就相应的变化,遍历完整个数组,max就是最大数。*/int arr[] = {0,-1,89,99,4};int arrLen = sizeof(arr) / sizeof(int);int max = arr[0];int maxIndex = 0;int i;for(i = 1; i < arrLen; i++){    // 这里 i 的初始值为1;因为为0则是和自己比较没有意义// 发现有比max更大的数,就相应的变化if(arr[i] > max){max  = arr[i];maxIndex = i; // 对应下标就是i,所以把i 赋值即可}}printf("max = %d maxIndex = %d",max,maxIndex); // 99,3getchar();
}

P 121 字符串介绍和内存布局 2023/1/29

一、字符数组的介绍

基本介绍:用来存放字符数组称为字符数组, 看几个案例。

char a[10]; //一维字符数组, 长度为10
char b[5][10]; //二维字符数组, 后面我们详细介绍二维数组
char c[20]={'c', ' ', 'p', 'r', 'o', 'g', 'r', 'a','m'}; // 给部分数组元素赋值

总结:字符数组实际上是一系列字符的集合,也就是字符串(String)。在C语言中,没有专门的字符串变量,没有string类型,通常就用一个字符数组来存放一个字符串。

#include<stdio.h>
void main(){// c是一个一维字符数组,给部分元素赋值char c[20]={'t','o','m'};// 输出printf("%s",c);	  // 输出tomgetchar();
}

二、字符串注意事项

  1. 在 C 语言中,字符串实际上是使用 null 字符 (‘\0’) [null字符就是\0,因为ASCII 0 表示空],终止的一维字符数组。因此,一个以 null 结尾的字符串,包含了组成字符串的字符。【以下为内存布局图】
  2. '\0’是ASCII码表中的第0个字符,用NUL表示,称为空字符。该字符既不能显示,也不是控制字符,输出该字符不会有任何效果,它在C语言中仅作为字符串的结束标志。
  3. 字符数组(字符串)在内存中的布局分析 [案例]。

image-20230129180936276

  1. 思考 char str[3] = {‘a’,‘b’,‘c’} 输出什么? 为什么?
	char c[7]={'t','o','m'}; 
// 正常输出tomchar str[3] = {'a','b','c'};
// 输出a,b,c后,后面可能会出现乱码,一些垃圾值char str[] = {'a','b','c'};
// 不指定长度,输出结果可能同样会出现乱码

分析示意图:

image-20230129182746533

结论:如果在给某个字符数组赋值时,(1)赋给的元素的个数小于该数组的长度,则会自动在后面加 ‘\0’, 表示字符串结束,(2)赋给的元素的个数等于该数组的长度,则不会自动添加 ‘\0’。

P 122 字符指针和内存布局 2023/1/30

一、字符串的访问和遍历

小结:因为字符串的本质就是字符数组,因此可以按照数组的方式遍历和访问某个元素即可, 案例如下:

#include<stdio.h>
#include<string.h>
void main(){// 这种方式定义字符数组不会出现任何的乱码,会自动添加一个\0char greeting[] = "Hello";  int i;int len  = strlen(greeting);  // len = 5printf("\n greeting = %s",greeting);printf("\nlen=%d", len);printf("\n字符串第3个字符是=%c", greeting[2]); // 下标是从0开始的,第三个字符for(i = 0; i < len; i++) {printf("\n%c", greeting[i]);}getchar();
}
  • 内存布局

image-20230130115430132

二、字符串的表示形式

  • 用字符数组存放一个字符串

1 . char str[]=“hello tom”;

2 . char str2[] = {‘h’, ‘e’};

  • 用字符指针指向一个字符串

1 . 比如: char pStr=" hello";*

#include<stdio.h>
void main(){// 使用一个指针pStr,指向一个字符数组char* pStr = "Hello";printf("\n pStr指向的字符串= %s",pStr); // 输出Hellogetchar();
}

2 . 总结:

  • C语言对字符串常量" hello"是按字符数组处理的,在内存中开辟了一个字符数组用来存放字符串常量,程序在定义字符串指针变量str时只是把字符串首地址(即存放字符串的字符数组的首地址)赋给pStr。
  • 内存布局图

image-20230130120200916

  • printf(“%s\n”,str); 可以输出 str 指向的字符串。

三、两种方法表示字符串的讨论

  1. 字符数组由若干个元素组成,每个元素放一个字符;而字符指针变量中存放的是地址(字符串/字符数组的首地址),绝不是将字符串放到字符指针变量中(是字符串首地址)。

  2. 对字符数组只能对各个元素赋值,不能用以下方法对字符数组赋值:

char str[14];   // str 实际是一个常量str=" hello tom"; //错误str[0] = 'i'; //ok ,因为只是找到第一个元素在那里填了一个i而已

内存布局图:

image-20230130131706012

  1. 对字符指针变量,采用下面方法赋值, 是可以的:
#include<stdio.h>
void main(){char* a="yes";// 赋值前的地址:printf("\na本身的地址是%p,指向的地址是%p",&a,a);a=" hello tom";   // 定义一个字符指针变量时,可以多次赋值// 赋值后的地址:printf("\na本身的地址是%p,指向的地址是%p",&a,a);printf("\n%s",a);getchar();
}

image-20230130133405513

内存布局图:

image-20230130132914387

  1. 如果定义了一个字符数组,那么它有确定的内存地址(即字符数组名是一个常量);而定义一个字符指针变量时,它并未指向某个确定的字符数据,并且可以多次赋值 [代码+图解]。

P 123 字符数组注意事项和细节 2023/1/31

一、字符串相关函数回顾

  • 常用字符串函数一览
序号函数目的
1strcpy(s1, s2);复制字符串 s2 到字符串 s1。
2strcat(s1, s2);连接字符串 s2 到字符串 s1 的末尾。
3strlen(s1);返回字符串 s1 的长度。
4strcmp(s1, s2);如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回小于 0;如果 s1>s2 则返回大于 0。
5strchr(s1, ch);返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。
6strstr(s1, s2);返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。
#include<stdio.h>
#include<string.h>void main(){char str1[12] = "Hello";char str2[12] = "World";char str3[12];int len ; /* 复制 str1 到 str3 */strcpy(str3, str1);   // str3内容 "Hello"printf("strcpy( str3, str1) : %s\n", str3 );/* 连接 str1 和 str2 */strcat( str1, str2);printf("strcat( str1, str2): %s\n", str1 );  // "Hello world"/* 连接后,str1 的总长度 */len = strlen(str1);   // 因为进行了连接,所以总长度应该是10,10个字符printf("strlen(str1) : %d\n", len );if(strcmp(str1, str2)<0){printf("小于0");}else{printf("大于0");}getchar();
}

二、字符数组使用注意事项和细节

  1. 程序中往往依靠检测 ‘\0’ 的位置来判定字符串是否结束,而不是根据数组的长度来决定字符串长度。因此,字符串长度不会统计 ‘\0’, 字符数组长度会统计 [案例]。

  2. 在定义字符数组时应估计实际字符串长度,保证数组长度始终大于字符串实际长度,否则,在输出字符数组时可能出现未知字符。

  3. 系统对字符串常量也自动加一个’\0’作为结束符。例如"C Program”共有9个字符,但在内存中占10个字节,最后一个字节’\0’是系统自动加上的。(通过sizeof()函数可验证)。

  4. 定义字符数组时,如果 给的字符个数 比 数组的长度小,则系统会默认将剩余的元素空间,全部设置为 ‘\0’, 比如 char str[6] = “ab” , str内存布局就是[a] [b] [ \0 ] [\0] [\0] [\0]。

  5. 字符数组定义和初始化的方式比较多,比如:

#include<stdio.h>void main(){char str1[ ]={"I am happy"}; // 默认后面加 '\0'char str2[ ]="I am happy"; // 省略{}号 ,默认后面加 '\0'char str3[ ]={'I',' ','a','m',' ','h','a','p','p','y'}; // 字符数组后面不会加 '\0', 可能有乱码char str4[5]={'C','h','i','n','a'}; //字符数组后面不会加 '\0', 可能有乱码char * pStr = "hello";		 // OK, 使用一个指针pStr,指向一个字符数组printf("\n str1 = %s",str1);printf("\n str1 = %s",str2);printf("\n str1 = %s",str3);printf("\n str1 = %s",str4);getchar();
}

P 124 冒泡排序分析和实现 2023/1/31

一、排序算法

介绍:排序也称排序算法(Sort Algorithm),排序是将一组数据,依指定的顺序进行排列的过程。

排序的分类:

  1. 内部排序:指将需要处理的所有数据都加载到**内部存储器(内存)**中进行排序。

  2. 外部排序法:数据量过大,无法全部加载到内存中,需要借助外部存储进行排序。

二、冒泡排序

基本介绍:冒泡排序(Bubble Sorting)的基本思想是:通过对待排序序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就象水底下的气泡一样逐渐向上冒。

结论:因为排序的过程中,各元素不断接近自己的位置,如果一趟比较下来没有进行过交换,就说明序列有序,因此要在排序过程中设置一个标志flag判断元素是否进行过交换。从而减少不必要的比较。

  • 冒泡排序应用实例

案例:我们举一个具体的案例来说明冒泡法。我们将五个无序的数:{3, 9, -1, 10, -2}使用冒泡排序法将其排成一个从小到大的有序数列。

分析过程:

// 	冒泡排序的过程(从小到大) ===> 分析过程(思路) ===》 代码原始数组{3, 9, -1, 10, -2}1轮排序:
(1)  3,9-1,10-2
(2) 3,-1,9,10,-2
(3) 3,-1,9,10,-2
(4)3,-1,9,-2,10  // 第1大的数就移动到最后2轮排序:
(1) -1,3,9,-2,10
(2)-1,3,9,-2,10
(3)-1,3,-2,9,10 //第2大的数就移动适当位置3轮排序:
(1)-1,3,-2,9,10
(2)-1,-2,3,9,10 第3大的数就移动适当位置4轮排序:
(1) -2,-1,3,9,10//第4大的数就移动适当位置
排序结束
// 是不需要进行第五轮的比较,因为四个数都已经找到合适的位置了

将上述的分析过程然后写成代码:

#include<stdio.h>void main(){int arr[] = {3,9,-1,10,-2};// 因为每次排序几乎一样,因此,我们可以使用for循环处理int j;int t;  // 临时变量// 第一轮排序:for(j = 0; j < 4; j++){// 如果前面的数大于后面的数就,交换if(arr[j] > arr[j+1]){t = arr[j];arr[j] = arr[j+1];arr[j+1] = t;}}// 输出看看第一轮排序的的情况 for(j = 0 ; j < 5 ; j++){printf("%d ",arr[j]);}printf("\n");// 第二轮排序:for(j = 0; j < 3; j++){  // 第二轮比较3次就可以了,因为前一轮最大数已经固定了// 如果前面的数大于后面的数就,交换if(arr[j] > arr[j+1]){t = arr[j];arr[j] = arr[j+1];arr[j+1] = t;}}for(j = 0 ; j < 5 ; j++){printf("%d ",arr[j]);}printf("\n");// 第三轮排序:for(j = 0; j < 2; j++){  // 第二轮比较2次就可以了,因为前两轮已经固定两个数// 如果前面的数大于后面的数就,交换if(arr[j] > arr[j+1]){t = arr[j];arr[j] = arr[j+1];arr[j+1] = t;}}for(j = 0 ; j < 5 ; j++){printf("%d ",arr[j]);}printf("\n");// 第四轮排序:for(j = 0; j < 1; j++){  // 第二轮比较2次就可以了// 如果前面的数大于后面的数就,交换if(arr[j] > arr[j+1]){t = arr[j];arr[j] = arr[j+1];arr[j+1] = t;}}for(j = 0 ; j < 5 ; j++){printf("%d ",arr[j]);}printf("\n");getchar();
} 

代码优化:

// 因为每次排序几乎一样,因此,我们可以使用for循环处理
#include<stdio.h>void main(){int arr[] = {3,9,-1,10,-2,-11,989};// 因为每次排序几乎一样,因此,我们可以使用for循环处理int j;int i;int t;  // 临时变量int arrLen = sizeof(arr) / sizeof(int);  // 数组的大小,通过计算得到,这样就很方便,可以随意改变数组大小for(i = 0 ; i < arrLen-1 ; i++){  // 这里可以写活,刚好等于数组的大小减1// 第一层循环就是总的轮数for(j = 0; j < arrLen-1-i; j++){// 第二层循环就是执行交换,进行轮中的排序// 如果前面的数大于后面的数就,交换if(arr[j] > arr[j+1]){   // 从大到小,把大于改成小于就可以了t = arr[j];arr[j] = arr[j+1];arr[j+1] = t;}}// 获取每一轮循环后的结果for(j = 0 ; j < arrLen ; j++){printf("%d ",arr[j]);}printf("\n"); // 每一轮循环输出结果后换行}getchar();
}

函数优化处理:

#include<stdio.h>// 冒泡排序的函数:
void bubbleSort(int arr[],int arrLen){// 因为每次排序几乎一样,因此,我们可以使用for循环处理int j;int i;int t;  // 临时变量for(i = 0 ; i < arrLen-1 ; i++){  // 这里可以写活,刚好等于数组的大小减1// 第一层循环就是总的轮数for(j = 0; j < arrLen-1-i; j++){// 第二层循环就是执行交换,进行轮中的排序// 如果前面的数大于后面的数就,交换if(arr[j] > arr[j+1]){   // 从大到小,把大于改成小于就可以了t = arr[j];arr[j] = arr[j+1];arr[j+1] = t;}}// 获取每一轮循环后的结果for(j = 0 ; j < arrLen ; j++){printf("%d ",arr[j]);}printf("\n"); // 每一轮循环输出结果后换行}
}void main(){int j;int arr[] = {3,9,-1,10,-2,-11,};int arrLen = sizeof(arr) / sizeof(int);  // 数组的大小,通过计算得到,这样就很方便,可以随意改变数组大小bubbleSort(arr,arrLen);  // 数组默认是地址传递(指针)getchar();
}

总结: 以上案例的优化过程总结了前面所学,进行了一个综合。

P 125 顺序查找和二分查找 2023/2/1

一、基本介绍

在C中,我们常用的查找有两种

1) 顺序查找

2) 二分查找(默写)【比较重要】

  • 案例演示:

二、顺序查找

案例一:有一个数列:{23, 1, 34,89, 101},猜数游戏:从键盘中任意输入一个数,判断数列中是否包含该数,

【顺序查找】要求: 如果找到了,就提示找到,并给出下标值, 找不到提示 没有。

#include<stdio.h>int seqSearch(int arr[], int arrLen, int val){int i;for(i = 0; i < arrLen ; i++){if(val == arr[i]){return i;}}// 如果在for循环中,没有执行到return,说明没有找到return -1; // 可以返回一个-1,因为下标是没有-1的
}void main(){/*有一个数列:{23, 1, 34,89, 101},猜数游戏:从键盘中任意输入一个数,判断数列中是否包含该数,【顺序查找】要求: 如果找到了,就提示找到,并给出下标值, 找不到提示 没有。*/// 分析思路://1. 按照数组进行数组进行遍历,如果相等则找到。int arr[] = {23,1,34,89,101};int arrLen = sizeof(arr) / sizeof(int);int index = seqSearch(arr,arrLen,-101); // 将形参传入进去,返回值用index进行接收if(index != -1){printf("找到了下标为%d",index);}else{printf("没有找到");}getchar();
}

三、二分查找

案例二:请对一个有序数组进行【二分查找】 {1,8, 10, 89, 1000, 1234} ,输入一个数看看该数组是否存在此数,并且求出下标,如果没有就提示"没有这个数"
二分查找的前提是,该数组是一个有序数组。

#include<stdio.h>// 二分查找:
int binarySearch(int arr[], int leftIndex, int rightIndex, int findVal){// 先找到中间这个数midValint midIndex = (leftIndex + rightIndex) / 2;  // 比如数组大小为5,左下标(0+5)/2=2.5取整为2int midVal = arr[midIndex];   // 中间值//如果leftIndexf > rightIndex ,说明这个数组都比较过,但是没有找到。// 因为:leftIndex是在逐渐向右边移动,rightIndex是逐渐向左边移动,所以如果左边大于右边,// 就说明已经将整个数组范围全部查找完但是没有找到。if(leftIndex > rightIndex){return -1;  // !!!}// 如果midVal > finVal说明 应该在midVal的左边去查找if(midVal > findVal){binarySearch(arr,leftIndex,midIndex-1,findVal); // !!! 函数递归,递归相当于缩小范围进行查找// 如果midVal < finaVal说明 应该在midVal的右边去查找}else if(midVal < findVal){binarySearch(arr,midIndex+1,rightIndex,findVal); // 在右边查找,右边索引不变,左边索引加一}else{return midIndex;  // 返回该数的下标}}
void main(){/*请对一个有序数组进行二分查找 {1,8, 10, 89, 1000, 1234} ,输入一个数看看该数组是否存在此数,并且求出下标,如果没有就提示"没有这个数"。二分查找的前提是,该数组是一个有序数组*/int arr[]= {1,8, 10, 89, 1000, 1234};int arrLen = sizeof(arr) / sizeof(int);int index = binarySearch(arr, 0 ,arrLen-1,-1234);  // 这里长度-1,因为下标从0开始,得到长度是6,但第六个下标为5if(index != -1){printf("index = %d",index);}else{printf("没有找到");}getchar();// 思路分析:// 比如我们要查找的数是findVal// 1.先找到 数组中间这个数midVal,和finVal比较// 2.如果midVal > finVal说明 应该在midVal的左边去查找// 3.如果midVal < finVal说明 应该在midVal的右边去查找// 4. 如果midVal == findVal ,说明找到// 5. 如果leftIndexf > rightIndex ,说明这个数组都比较过,但是没有找到
}

P 126 二维数组的基本使用 2023/2/1

一、基本介绍

多维数组我们介绍二维数组。

  • 应用场景

比如我们开发一个五子棋游戏,棋盘就是需要二维数组来表示。如图:

image-20230201161024628

二、入门案例

**案例一:**请用二维数组输出如下图形。

image-20230201162349511

#include<stdio.h>
void main () {// a[4][6]  :表示的是一个4行6列的二维数组// (1)先定义在初始化:int a[4][6]; // 没有初始化,则是分配的内存垃圾值(不确定的值)int i, j;//全部初始化 0for(i = 0; i < 4; i++) {      // 先遍历行for(j = 0; j < 6; j++) {  //  在遍历列a[i][j] = 0;}}a[1][2] = 1;a[2][1] = 2;a[2][3] = 3;// 输出二维数组for(i = 0; i < 4; i++) {for(j = 0; j < 6; j++) {//printf("a[%d][%d]=%d ", i, j, a[i][j]);printf("%d ", a[i][j]);}printf("\n");}

相关地址输出:

	//看看二维数组的内存布局printf("\n二维数组a的首地址=%p", a);printf("\n二维数组a[0]的地址=%p", a[0]);printf("\n二维数组a[0][0]的地址=%p", &a[0][0]);printf("\n二维数组a[0][1]的地址=%p", &a[0][1]);//将二维数组的各个元素得地址输出printf("\n");for(i = 0; i < 4; i++) {printf("a[%d]的地址=%p ", i, a[i]);   // 输出a[0-4]的地址for(j=0; j < 6; j++) {printf("a[%d][%d]的地址=%p ", i, j , &a[i][j]); // 输出全部地址}
// 地址是连续分部的,虽然看着换行了,第二行的第一个元素地址是上一行最后加4printf("\n");	}getchar();
}

内存分析图:

image-20230201170914734

总结:

  1. 语法: 类型 数组名[大小] [大小],比如: int a [2] [3];
  1. 二维数组在内存的存在形式,各个元素的地址是连续分布的,即在前一个元素基础上+4(int类型)。

三、直接初始化

  • 定义 类型 数组名[大小] [大小] = {{值1,值2…},{值1,值2…},{值1,值2…}};
    或者 类型 数组名[大小] [大小] = { 值1,值2,值3,值4,值5,值6 …};

image-20230201171744020

P 127 二维数组的应用案例 2023/2/2

一、应用案例

案例一:请使用灵活的方式遍历如下数组 :

int map[3][3] = {{0,0,1},{1,1,1},{1,1,3}};

#include<stdio.h>void main(){int  map[3][3] = {{0,0,1},{1,1,1},{1,1,3}};// 遍历// 先得到行// 1. sizeof(map) 得到这个map数组的大小 9 * 4 = 36// 2. sizeof(map[0]) 得到map中,第一行有多大 3 * 4 = 12int rows = sizeof(map) / sizeof(map[0]);  // 3个元素//printf("rows = %d",rows);// 得到列int cols = sizeof(map[0]) / sizeof(int);  // 一行的大小是12,int占4字节,除以4可以得到列。 sizeof([0][0])int i;int j;for(i = 0; i < rows; i++){for(j = 0; j < cols; j++){printf("%d ",map[i][j]);}printf("\n");}getchar();
}

案例二:int arr[3][2]={{4,6},{1,4},{-2,8}};遍历该二维数组,并得到和?

#include<stdio.h>void main(){int arr[3][2]={{4,6},{1,4},{-2,8}};int i,j;int sum = 0;int rows = sizeof(arr) / sizeof(arr[0]);int column = sizeof(arr[0]) / sizeof(int);for(i = 0; i < rows ; i++){for(j = 0; j < column ; j++){printf("%d ",arr[i][j]);sum += arr[i][j];  // 定义一个sum,每次累加}printf("\n");}printf("sum=%d",sum);  // 21 getchar();
}

案例三:定义二维数组,用于保存三个班,每个班五名同学成绩,并求出每个班级平均分、以及所有班级平均分【 数据要求从控制台输入 】

#include<stdio.h>void main(){/*定义二维数组,用于保存三个班,每个班五名同学成绩,并求出每个班级平均分、以及所有班级平均分【 数据要求从控制台输入 】*/// 分析:// 1 .创建一个scores[3][5]// 2. 遍历,给赋值// 3. 再次遍历统计总分和平均分// 4. 最后输出double score[3][5]; //int rows = sizeof(score) / sizeof(score[0]),cols = sizeof(score[0]) / sizeof(double), i, j; // //classTotalScore 各个班级总成绩, totalScore 所有学生成绩double totalScore = 0.0, classTotalScore = 0.0;  // 定义所有班级总成绩、个各班的成绩for (i = 0; i < rows; i++ ) {for (j = 0; j < cols ; j++ ) {score[i][j] = 0.0;  // 初始化}}//遍历给每个学生输入成绩for (i = 0; i < rows; i++ ) {for (j = 0; j < cols ; j++ ) {printf("请输入第 %d 个班的 第 %d 个 学生的成绩", i + 1, j + 1); // 下标从0开始,但是没有第0个班,所以+1scanf("%lf", &score[i][j]);}}// 显示成绩情况for(i = 0; i < rows ; i++){for(j = 0 ; j < cols; j++){printf("%.2f  ",score[i][j]);}printf("\n");}// 统计各个班的总成绩,和所有学生的总成绩for(i = 0; i < rows; i++){classTotalScore = 0.0; // 每次清0,这样才能统计每个班的总分for(j = 0; j < cols; j++){classTotalScore += score[i][j];}printf("\n 第%d个班的平均成绩时%.2f",i+1,classTotalScore/cols);totalScore += classTotalScore;   //  将该班级的总分,累积到totalScore}printf("\n 所有学生的总成绩是 %.2f ,平均成绩%.2f",totalScore,totalScore/(rows * cols)); // 平均成绩=总成绩/人数(rows * cols)getchar();getchar();
} 

image-20230202124408624

P 128 二维数组的注意事项和细节 2023/2/2

一、注意事项

  1. 可以只对部分元素赋值,未赋值的元素自动取“零”值【案例】。
#include<stdio.h>int main(){int a[4][5] = {{1},{2},{3},{1}};  // 每行后面是没有赋值的//{1}等价于 {1,0,0,0,0} int i,j;for(i = 0; i < 4; i++){for(j = 0; j < 5; j++){printf("%d ",a[i][j]);}printf("\n");}getchar();
}

image-20230202170107381

  1. 如果对全部元素赋值,那么第一维的长度可以不给出(二维数组可以省略行)。比如:
int a[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; 
可以写为: 
int a[][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};  // 是等价于前面的写法
  1. 二维数组可以看作是由一维数组嵌套而成的;如果一个数组的每个元素又是一个数组,那么它就是二维数组。
// 二维数组a[3][4]可看成三个一维数组,它们的数组名分别为 a[0]、a[1]、a[2]。
// 这三个一维数组都有 4 个元素,如,一维数组 a[0] 的元素为 a[0][0]、a[0][1]、a[0][2]、a[0][3]

image-20230202171022644

P 129 断点调试介绍和快捷键 2023/2/3

一、需求引入

引入:在开发中,程序员发现一个非常诡异的错误,怎么看源代码都发现不了这个错误,这时老程序员就会温馨提示,可以使用断点调试,一步一步的看源码执行的过程,从而发现错误所在。

基本介绍:断点调试是指自己在程序的某一行设置一个断点,调试时,程序运行到这一行就会停住,然后你可以一步一步往下调试,调试过程中可以看各个变量当前的值,出错的话,调试到出错的代码行即显示错误,停下。然后程序可以进行分析从而找到这个Bug。

二、断点调试的快捷键

F5开始调试、执行到下一个断点
F11逐句执行代码,会进入到函数体
F10逐过程执行(遇到函数,不会进入到函数体)
Shift+F11跳出(跳出某个函数,跳出前会将该函数执行完)
Shiit+F5终止调试

P 130 断点调试应用案例(1)2023/2/3

一、应用案例

案例一:看一下变量的变化情况等:(逐过程执行代码……)

#include<stdio.h>
void main() {int sum = 0;int i = 0;for(i = 0; i < 10; i++) {sum += i;printf("\n i=%d", i);printf("\n sum=%d", sum);}printf("退出for循环了~~");
}

image-20230203125254302

image-20230203125503125

image-20230203125659108


http://www.ppmy.cn/news/1537223.html

相关文章

Linux云计算 |【第四阶段】RDBMS1-DAY5

主要内容&#xff1a; 试图概述&#xff08;创建视图VIEW、修改、查看、删除&#xff09;、变量&#xff08;全局变量、会话变量、用户变量、局部变量&#xff09;、存储过程&#xff08;创建、调用、删除存储过程&#xff09;、流程控制结构&#xff08;分支结构&#xff1a;…

蓝桥杯【物联网】零基础到国奖之路:十二. TIM

蓝桥杯【物联网】零基础到国奖之路:十二. TIM 第一节 理论知识第二节 cubemx配置 第一节 理论知识 STM32L071xx器件包括4个通用定时器、1个低功耗定时器&#xff08;LPTIM&#xff09;、2个基本定时器、2个看门狗定时器和SysTick定时器。 通用定时器&#xff08;TIM2、TIM3、…

vue3常用组件通信方法

title: vue3常用组件通信方法 date: 2024-10-06 15:00:54 tags: vue3 组件通信 一、父传子—defineProps 1.父亲 通过属性传值 2.儿子 通过defineProps接收相关的数据 二、子传父 1&#xff09;使用defineExposeref 1.子组件 在子组件中使用defineExpose先暴露出来 2.父…

【C++篇】虚境探微:多态的流动诗篇,解锁动态的艺术密码

文章目录 C 多态详解&#xff08;进阶篇&#xff09;前言第一章&#xff1a;多态的原理1.1 虚函数表的概念1.1.1 虚函数表的生成过程 1.2 虚表的存储位置 第二章&#xff1a;动态绑定与静态绑定2.1 静态绑定2.1.1 静态绑定的实现机制&#xff1a;2.1.2 示例代码&#xff1a; 2.…

软件项目开发流程与团队分工整体认知——基于《信息系统项目管理师教程》(需求分析、系统设计、开发、测试、部署与运维、开发工具与管理软件)

文章目录 1、信息系统项目管理师教程——精简说明2、软件工程开发流程与团队分工详解2.1 需求分析2.2 系统设计2.3 开发2.4 测试2.5 部署与运维 3、开发工具与管理软件4、总结 1、信息系统项目管理师教程——精简说明 在《信息系统项目管理师教程》中&#xff0c;有一些章节对…

JavaGuide(3)

一、项目背景与简介 JavaGuide由GitHub用户Snailclimb开发并维护&#xff0c;是一个全面而深入的Java学习资源库。它旨在为Java初学者和有经验的开发者提供一个系统的学习路径和丰富的资源&#xff0c;帮助他们系统地学习和巩固Java及相关技术知识。 二、项目内容与特点 Jav…

Linux / Steam deck 解压问题/解压失败

一般我们使用ark软件打开压缩包可能会显示“压缩包为空”或者“无法打开其内容”&#xff0c;但是放在Windows系统中又能正常解压 我们可以用命令行来正确解压 第一步&#xff0c;安装p7zip&#xff0c;过程中如果需要输入密码&#xff0c;正常盲输入&#xff0c;按回车即可 …

请描述一下数据库的负载测试和压力测试。请简要描述不同类型的联接(如内联接、左外联接、右外联接、全外联接等)。

请描述一下数据库的负载测试和压力测试。 一、数据库的负载测试 定义&#xff1a; 负载测试是通过模拟实际用户量和操作情况来评估数据库系统的性能和稳定性的过程。它主要通过逐步增加系统负载&#xff0c;测试系统性能的变化&#xff0c;并最终确定在满足性能指标的情况下&a…