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

news2024/11/25 19:08:45

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.自定义数组大小5
	2.假定第一个元素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,3
	getchar();
}

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);	  // 输出tom
	getchar();
}

二、字符串注意事项

  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'}; 
// 正常输出tom

	char 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(){
	// 这种方式定义字符数组不会出现任何的乱码,会自动添加一个\0
	char greeting[] = "Hello";  
	int i;
	int len  = strlen(greeting);  // len = 5
	printf("\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); // 输出Hello
	getchar();
}

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){

	// 先找到中间这个数midVal
	int midIndex = (leftIndex + rightIndex) / 2;  // 比如数组大小为5,左下标(0+5)/2=2.5取整为2
	int 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,但第六个下标为5
	if(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;

	//全部初始化 0
	for(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]); // 输出全部地址
		}
// 地址是连续分部的,虽然看着换行了,第二行的第一个元素地址是上一行最后加4
		printf("\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 = 12
   int 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个班,所以+1
			scanf("%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.coloradmin.cn/o/2201111.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【优选算法之BFS】No.15--- 经典BFS解决FloodFill算法和解决最短路问题

文章目录 前言一、BFS解决FloodFill算法示例&#xff1a;1.1 图像渲染1.2 岛屿数量1.3 岛屿的最⼤⾯积1.4 被围绕的区域 二、BFS解决最短路问题2.1 迷宫中离⼊⼝最近的出⼝2.2 最⼩基因变化2.3 单词接⻰2.4 为⾼尔夫⽐赛砍树 前言 &#x1f467;个人主页&#xff1a;小沈YO. &a…

Linux高级编程_31_消息队列

文章目录 消息队列作用&#xff1a;特点&#xff1a;消息队列限制值&#xff1a;注意&#xff1a;命令&#xff1a;ftok函数作用&#xff1a;语法&#xff1a; msgget函数作用&#xff1a;语法&#xff1a; msgsnd函数作用&#xff1a;语法&#xff1a; msgrcv函数作用&#xf…

QT实现QInputDialog中文按钮

这是我记录Qt学习过程心得文章的第三篇&#xff0c;主要是为了方便QInputDialog输入框的使用&#xff0c;通过自定义的方式&#xff0c;按钮中文化&#xff0c;统一封装成一个函数&#xff0c;还是写在了Skysonya类里面。 实现代码&#xff1a; //中文按钮文本输入对话框 QSt…

【gRPC】1—gRPC是什么

gRPC是什么 ⭐⭐⭐⭐⭐⭐ Github主页&#x1f449;https://github.com/A-BigTree 笔记链接&#x1f449;https://github.com/A-BigTree/Code_Learning ⭐⭐⭐⭐⭐⭐ 如果可以&#xff0c;麻烦各位看官顺手点个star~&#x1f60a; &#x1f4d6;RPC专栏&#xff1a;https://b…

鸿蒙--播放器状态控制

各个页面共享同一个播放状态&#xff0c;而且可以互相控制&#xff0c;如果传递来传递去会非常的麻烦&#xff0c;但是他们都是Tabs组件内的&#xff0c;我们在index页面提供一个状态&#xff0c;在各个组件接收即可 创建两个子组件&#xff0c;一个是播放控制的子组件&#xf…

1. Oracle 安装报错——环境变量过长

文章目录 1. 报错详细信息2. 解决方案2.1 方案一&#xff1a;修改配置文件cvu_prereq.xml2.2 方案二&#xff1a;修改环境变量配置 1. 报错详细信息 安装 Oracle 过程中&#xff0c;在执行 “先决条件检查” 时报错&#xff1a; 报错内容&#xff1a; This test checks wheth…

【自然语言处理】(3) --RNN循环神经网络

文章目录 RNN循环神经网络一、传统神经网络的问题二、RNN的基本结构三、计算过程4. RNN的局限 总结 RNN循环神经网络 循环神经网络&#xff08;RNN&#xff0c;Recurrent Neural Network&#xff09;是一种用于处理序列数据的神经网络模型。其关键特性在于网络节点&#xff08…

现代数字信号处理I-P2概率论学习笔记

目录 学习视频链接&#xff1a; 1. 三要素及关系 2. 期望和方差的定义及基本性质 2.1 期望&#xff08;均值&#xff09;定义&#xff1a; 在实际工作中很难获得随机变量的分布或者概率密度&#xff0c;用矩描述随机变量 2.2 期望基本性质&#xff1a; 2.3 方差定义 2.…

Android Studio Koala Feature Drop 稳定版现已推出

作者 / Android Studio 产品经理 Sandhya Mohan Android Studio Koala Feature Drop (2024.1.2) 现已推出&#xff01;&#x1f428; &#x1f517; Android Studio https://developer.android.google.cn/studio 今年早些时候&#xff0c;我们宣布每个 Android Studio 动物版本…

10月9日笔记(域内用户登录凭据窃取)

缺&#xff1a;BloodHound自动化分析域环境未实现&#xff08;环境问题&#xff09; 获取常见应用软件凭据 为了扩大可访问的范围&#xff0c;测试人员通常会搜索各种常见的密码存储位置&#xff0c;以获取用户凭据。一些特定的应用程序可以存储密码&#xff0c;以方便用户管…

python的特殊方法——魔术方法

前言 __init__(self[]) ​编辑 __call__(self [, ...]) __getitem__(self, key) __len__(self) __repr__(self) / __str__(self) __add__(self, other) __radd__(self, other) 参考文献 前言 官方定义好的&#xff0c;以两个下划线开头且以两个下划线结尾来命名的方法…

PostgreSQL学习笔记四:GUI管理工具

PostgreSQL 是一款广泛使用的开源关系数据库管理系统&#xff0c;拥有许多图形用户界面&#xff08;GUI&#xff09;工具来帮助用户更高效地管理数据库。以下是一些流行的 PostgreSQL 管理工具&#xff1a; pgAdmin&#xff1a; 一个流行的开源 PostgreSQL GUI 工具&#xff0c…

处理“navicat premium 2003 - 无法在 192.168.10.140 上连接到 MySQL 服务器(10060“未知错误“)”的问题:

以下是一些可能的解决方法来处理“navicat premium 2003 - 无法在 192.168.10.140 上连接到 MySQL 服务器&#xff08;10060"未知错误"&#xff09;”的问题&#xff1a; **一、检查 MySQL 服务状态** 1. 确认 MySQL 服务是否正在运行。你可以在服务器上通过任务管…

Django makemigrations时出现TypeError: ‘module‘ object is not iterable

使用Python 3.11、Django 5.1.2 写完model进行makemigrations时出现报错 报错的最下面提到了我自己创建的一个应用里的urls.py&#xff0c;尝试着给里面加上一个列表 然后问题解决了。。。 不知道为什么 makemigrations的时候会去检查urls。。。

mybatisPlus对于pgSQL中UUID和UUID[]类型的交互

在PGSQL中&#xff0c;有的类型是UUID和UUID[]这种类型&#xff0c;在mybatis和这些类型交互的时候需要手动设置类型处理器才可以&#xff0c;这里记录一下类型处理器的设置 /*** UUID类型处理器*/ public class UUIDTypeHandler extends BaseTypeHandler<UUID> {/*** 获…

Kubernetes中的pod管理及优化

华子目录 什么是pod1.创建自主式pod&#xff08;生产不推荐&#xff09;优点缺点示例1示例2示例3示例4 2.利用控制器管理pod&#xff08;推荐&#xff09;应用版本的更新 3.利用yaml文件部署应用优点3.1yaml配置文件参数3.2如何获取资源帮助 yaml文件编写示例1.运行简单的单个容…

实现std::sort,replace,fill,accumulate,equal等函数

std::sort /// <summary>/// std::sort 是从小到大排列的/// </summary>/// <typeparam name"IteratorClass"></typeparam>/// <typeparam name"ComparingFunctions"></typeparam>/// <param name"itBegin&qu…

PAT甲级-1150 Travelling Salesman Problem

题目 题目大意 旅行商问题是NP-hard问题&#xff0c;即没有多项式时间内的解法&#xff0c;但是可以验证答案是否正确。给定一个无向图&#xff0c;判断简单环&#xff0c;复杂环和非环。对应“TS simple cycle”、“TS cycle”、“Not a TS cycle”。还要求出环的最小路径权值…

力扣11-盛最多水的容器

题目 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明&#xff1a;你不能倾斜容器。…

DAY28||39.组合总数 |40.组合总和Ⅱ |131.分割回文串

39.组合总数 题目&#xff1a;39. 组合总和 - 力扣&#xff08;LeetCode&#xff09; 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以…