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。分别实现 两个数 的 加法、减法、乘法。要求:
- 在main函数下方 书写函数定义。
- 在main函数中 调用自定义函数。并打印输出计算结果。
- 在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;
}