学习C语言第五天

2020/7/7 22:00

喧闹任其喧闹,自有我自为之,
我自风情万种,与世无争。

冒泡排序

在这里插入图片描述

//数组的冒泡排序
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <Windows.h>

int main(void)
{
	int arr[] = { 33,44,67,79,34,66,25,77,22,4,7 };
	int num = sizeof(arr) / sizeof(arr[0]);
	int temp;
	for (size_t i = 0; i < num - 1 ; i++)
	{
		for (size_t j = 0; j < num - 1 - i ; j++)
		{
			if (arr[j] > arr[j+1])
			{
				temp = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = temp;
			}
		}
	}
	for (size_t i = 0; i < num; i++)
	{
		printf("%d ", arr[i]);
	}
	system("pause");
	return EXIT_SUCCESS;
}

二维数组

  • 二维数组是多个一维数组的集合。
int arr[3][5] =
{
    {1,2,3,4,5}, //第一行
    {2,3,4,5,6}, //第二行
    {3,4,5,6,7}  //第三行
};
arr[2][2] ------->5
arr[1][3] ------->5

基本使用

定义语法

类型名 数组名[行数][列数] = {};
int arr[2][3] = 
{
    {6, 9, 1},
    {4, 7, 5}
};
int arr[3][4] = { {6, 8, 19, 2}, {44, 76, 81, 2}, {3, 6, 9, 11} };

打印

int main(void)
{
	int arr[3][4] = { {6, 8, 19, 2}, {44, 76, 81, 2}, {3, 6, 9, 11} };
	// 行
	for (size_t i = 0; i < 3; i++)
	{
		// 列
		for (size_t j = 0; j < 4; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");  // 打印完一行数据,换行。
	}
	return 0;
}

特性

  • 数组大小
printf("二维数组的大小:%u\n",sizeof(arr));
  • 一行大小
printf("一行的大小:%u\n", sizeof(arr[0]));
  • 一个元素的大小
printf("一个元素的大小:%u\n",sizeof(arr[0][0]));
  • 行数
//行数 = 数组的总大小/一行大小
printf("行数:%u\n",sizeof(arr)/sizeof(arr[0]));
  • 列数
//列数 = 一行的总大小/一个元素的大小
printf("列数:%u\n",sizeof(arr[0]/arr[0][0]));
  • 地址合一
    • 数组名 == 数组首行地址 == 数组首元素地址
printf("arr = %p\n", arr);
printf("arr[0] = %p\n", arr[0]);   // 第一个元素。—— 一维数组。
printf("&arr[0][0] = %p\n", &arr[0][0]);

初始化

常规初始化

int arr[2][3] = 
{
    {6, 9, 1},
    {4, 7, 5}
};
int arr[3][4] = { {6, 8, 19, 2}, {44, 76, 81, 2}, {3, 6, 9, 11} };
int arr[3][4] = { 6, 8, 19, 2, 4, 76, 81, 2, 3, 6, 9, 11 };

不完全初始化

int arr[3][5] = {{2, 7}, {4, 8, 1}, {1, 9}};   // 未被初始化的值,默认为 0
int arr[3][5] = {{2, 7}, {4, 8, 1}}; 【重点】 	// 未被初始化的值,默认为 0
int arr[3][5] = {0};   【重点】 // 初始化一个全部为 0 的数组。

不完全指定行列初始化

  • 初始化二维数组,至少要指定列值。行值可以省略。
// 一维数组,可以如此定义
int arr[] = {1, 6, 8};

// 二维数组,不可以如此定义
int arr[][] = { {2, 3}, {3, 55, 19}, {1, 4, 16, 79} };

// 定义二维数组时,至少指定列值。
int arr[][4] = { 2, 3, 3, 55, 19, 1, 4, 16, 79 };【重点】

练习

  • 求出5名学生3门功课的总成绩。(一个学生的总成绩。一门功课的总成绩)
int main(void)
{
	int scores[5][3];   // 描述 5 个学生、3门功课。

	int row = sizeof(scores) / sizeof(scores[0]);
	int col = sizeof(scores[0]) / sizeof(scores[0][0]);

	//printf("请输入5名学生的3门功课:\n");

	// 获取 5名学生,3门功课总成绩。
	for (size_t i = 0; i < row; i++)  // 循环一次,取一个学生。
	{
		for (size_t j = 0; j < col; j++)	// 循环一个一科成绩。
		{
			(void)scanf("%d", &scores[i][j]);
		}
	}
	printf("\n--------------------------------\n");

	// 打印获取到的 5名学生, 3门功课。
	/*
	for (size_t i = 0; i < row; i++)  // 循环一次,取一个学生。
	{
		for (size_t j = 0; j < col; j++)	// 循环一个一科成绩。
		{
			printf("%d ", scores[i][j]);
		}
		printf("\n");
	}
	*/

	// 获取学生的总成绩
	int sum = 0;

	for (size_t i = 0; i < row; i++)  // 循环一次,取一个学生。
	{
		sum = 0;  // 清零 sum 变量,用来累加一个学生的成绩。
		for (size_t j = 0; j < col; j++)	// 循环一次一科成绩。
		{
			sum += scores[i][j];  // 将一个学生的每科成绩累加到 sum上。
		}
		printf("第%d个学生的总成绩为:%d\n", i, sum);
	}

	// 求一门功课的总成绩。
/*
语  数 英
88 99 100
75 76 77
81 89 93
65 72 88
94 92 59
*/
// 99 + 88 + 94 == scores[0][1] + scores[3][2] + scores[4][0]
/*
88 + 75 + 81 + 65 + 94
	scores[0][0] +
	scores[1][0] +
	scores[2][0] +
	scores[3][0] +
	scores[4][0] +
99 + 76 + 89 + 72 + 92
	scores[0][1] +
	scores[1][1] +
	scores[2][1] +
	scores[3][1] +
	scores[4][1] +
*/
	// 第几门功课
	for (size_t i = 0; i < col; i++) 
	{
		sum = 0;  
		// 第几个学生
		for (size_t j = 0; j < row; j++)	
		{
			sum += scores[j][i];
		}
		printf("第%d门功课的总成绩为:%d\n", i, sum);
	}

	return 0;
}

多维数组(了解)

int arr[3][3][3] = 
{
    {
       //列
        {1, 3, 5},  //行
        {1, 3, 5},
        {1, 3, 5}
    },  // 第一层	
    {
        {1, 3, 5},
        {1, 3, 5},
        {1, 3, 5}
    },  // 第二层
    {
        {1, 3, 5},
        {1, 3, 5},
        {1, 3, 5}
    }	// 第三层
};

for (size_t i = 0; i < 3; i++)  // 层
{
    for (size_t j = 0; j < 3; j++)  // 行
    {
        for (size_t k = 0; k < 3; k++)  // 列
        {
            printf("%d ",arr[i][j][k]);
        }
        printf("\n");
    }
    printf("\n");
}

int arr[2][3][5] = {1, 3, 6, 8, 9, 0, 33, 2, 2, 88, 52, 13, 7, 44};
int arr[][3][5] = {1, 3, 6, 8, 9, 0, 33, 2, 2, 88, 52, 13, 7, 44};

数组名 == 数据首层地址 == 首行地址 == 首元素地址。

函数

函数的作用

  • 提高代码的服用率
  • 提高代码的模块化组织性

函数分类

  • 系统库函数(C语言标准库)
    • 引入头文件——函数声明。(没有具体实现)
    • 根据函数形式调用函数——函数调用
    • C语言标准库里存放函数的具体实现(gcc的链接阶段引入C标库)——函数定义
  • 用户自定义函数
    • 函数的具体实现——函数定义
    • 使用自定义函数——函数调用

使用函数

  • 函数定义、函数调用、函数声明

函数定义

  • 主要包含:函数原型 + 函数体
    • 函数原型:
      • 返回值类型 + 函数名 + 形参列表(形式参数列表:类型名 变量名)
    • 函数体:
      • {} + 函数功能具体实现代码
  • 举例:
int add(int a, int b)  // 本行为 函数原型。
{
    int ret = a + b;
    return ret;
}

void bubble_sort(int arr[], int n)  // 本行为 函数原型。
{ // 函数体起始
	for (size_t i = 0; i < n - 1; i++)
	{
		for (size_t j = 0; j < n - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
} // 函数体结束。

函数调用

  • 语法
    • 函数名 + 实参列表(实际参数列表)
      • 实参列表:必须严格按照函数原型中的形参列表来传参
      • 参数的类型、个数、顺序都必须完全一致
  • 举例:
// 有函数定义如下
int add(int a, int b)  
{
    int ret = a + b;
    return ret;
}
// 调用此函数
add(10, 20);  // 【方法1】
int ret = add(3, 5); // 【方法2】
int m = 4, n = 9;
int ret = add(m, n); // 【方法3】

// 有函数定义如下
int test(char ch, short b, int arr[], float f) 
{
    //具体功能实现。
}
// 调用此函数
int ret = test('m', 10, arr, 3.14f);  // 正确调用

// 错误调用!顺序不一致
int ret = test(3.14, arr, 'm', 10);  
// 错误调用!个数不一致
int ret = test('n', 10, arr);  
// 错误调用!函数调用,实参中,不允许出现类型名。
int ret = test(char 'm', short 10, int [] arr, float 3.14f);

函数声明

  • 语法:
    • 函数原型 + “ ; ”
// 有函数定义如下
int add(int a, int b)  
{
    int ret = a + b;
    return ret;
}
// 函数声明
int add(int a, int b);  或者  int add(int, int);

void bubble_sort(int arr[], int n);  或者 void bubble_sort(int [], int); 
    
int test(char ch, short b, int arr[], float f); 
或者
int test(char ,short, int [], float);
  • 要求,编译器必须在函数调用之前,见过函数定义。否则,需要函数声明。

如果没有函数定义,也没有函数声明,编译器会做隐式声明。

做隐式声明时,认为所有的函数返回值都是 int。

exit函数

  • exit()函数,用来终止整个C语言程序,参数代替程序退出值。
exit(0);  // 0 代表程序正常终止
exit(1);  // 1 代表程序非正常终止
  • return 关键字。给函数做返回。
    • 在main函数中,return 和 exit() 功能相同。终止 C程序。

    • 不在 main函数中, return 只能做返回,不能终止 C程序。
      在这里插入图片描述在这里插入图片描述

多文件编程

  • 创建头文件在这里插入图片描述

  • 添加头文件守卫:防止头文件被重复包含

    • 方法1:

      #pragma once
      
    • 方法2:

      #ifndef _HEAD_H_
      #define _HEAD_H_
      
      // 其他头文件的引入include 、宏定义、函数声明、类型定义、全局变量定义和声明
      
      #endif
      
  • 举例:

    // #pragma once   // 防止头文件被重复包含:头文件守卫。
    
    // C标准提供的 防止头文件被重复包含 方法。—— 任何平台、任何版本编译器都可以使用。
    #ifndef _HEAD_H_
    #define _HEAD_H_
    
    // 其他头文件的引入include 、宏定义、函数声明、类型定义、全局变量定义和声明
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <time.h>
    
    // 宏定义
    #define PI 3.1415926
    
    // 函数声明
    int add(int a, int b);
    int sub(int a, int b);
    
    #endif 
    
  • 引入自定义头文件,使用 “” 包裹头文件名。

    #define _CRT_SECURE_NO_WARNINGS
    
    #include "head.h"  // 引入自定义头文件。使用 “”
    
    int main(void)
    {
    	//int ret = add(10, 20);
    	//printf("%d + %d = %d\n", 10, 20, ret);
    
    	// 函数调用
    	printf("%d + %d = %d\n", 10, 20, add(10, 20));
    	printf("%d - %d = %d\n", 10, 20, sub(10, 20));
    
    	return 0;
    }
    

字符串

int arr[10];
short arr[10];
long long arr[10];

char arr[10]; 

字符数组和字符串的区别

  • C语言中,没有 “字符串” 数据类型。使用字符数组模拟字符串。

    // 字符数组
    char str[5] = {'h', 'e', 'l', 'l', 'o'};
    
    // 字符串
    char str[6] = {'h', 'e', 'l', 'l', 'o', '\0'}; 【书写麻烦】
    char str[6] = "hello"; 	【书写简单】
    char str[] = "hello";	【书写简单】
    
  • C语言中,用 “” 包裹的一串字符,称之为 “字符串”。 自动隐含有 ‘\0’ 结束标记。

字符串输出

  • printf 函数结合 %s 格式匹配符进行输出。==**
  • 如果该字符串没有 \0 结束标记,printf函数,输出不终止。继续向后输出相邻内存中的数据,直到遇见 \0 为止。
    在这里插入图片描述

其他格式匹配符

  • 输出字符串在这里插入图片描述
  • 输出 % 符
// % 用转义字符转义无效。用 % 本身转义自己。
如:输出【10 % 3 = 1】到屏幕。

printf("10 % 3 = 1\n");		【错误】
printf("10 \% 3 = 1\n");	【错误】
printf("10 %% 3 = 1\n");  	【正确】

编程练习

1.已知二维数组 int arr[3][5] = {{2, 3, 54, 56, 7 }, {2, 67, 4, 35, 9}, {1, 4, 16, 3, 78}}; 输出最大值。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <Windows.h>

int main(void)
{
	int arr[3][5] = { {2, 3, 54, 56, 7 }, {2, 67, 4, 35, 9}, {1, 4, 16, 3, 78} };
	int row = sizeof(arr) / sizeof(arr[0]);
	int col = sizeof(arr[0]) / sizeof(arr[0][0]);
	int max = arr[0][0];
	int temp;
	for (size_t i = 0; i < row; i++)
	{
		for (size_t j = 0; j < col; j++)
		{
			int max_exc = arr[i][j];
			if (max < max_exc)
			{
				temp = max_exc;
				max = temp;
				max_exc = max;
			}
		}
	}
	printf("该二维数组最大值为:%d\n", max);
	system("pause");
	return EXIT_SUCCESS;
}

2.自定义 函数 add、sub、mul。分别实现 两个数 的 加法、减法、乘法。要求:

  1. 在main函数下方 书写函数定义。
  2. 在main函数中 调用自定义函数。并打印输出计算结果。
  3. 在main函数 调用之前,写出函数声明。
    【提示】:想额外多写除法的同学,函数不要叫 div, 会与系统函数冲突。可以叫dive。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <Windows.h>

int main(void)
{
	double add(double, double);
	double sub(double, double);
	double mul(double, double);
	double dive(double, double);

	printf("%.2lf\n", add(10.5, 11.7));
	printf("%.2lf\n", sub(10.5, 11.7));
	printf("%.2lf\n", mul(10.5, 11.7));
	printf("%.2lf\n", dive(10.5, 11.7));
	system("pause");
	return EXIT_SUCCESS;
}
double add(double a, double b)
{
	return a + b;
}
double sub(double a, double b)
{
	return a - b;
}
double mul(double a, double b)
{
	return a * b;
}
double dive(double a, double b)
{
	return a / b;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值