目录
1. 水仙花数
#指一个三位数,其各个数字立方和等于该数本身,例:153,13+53+33=15313+53+33=153
#include <stdio.h>
#include <math.h>
int main()
{
for(int i = 100;i < 100000;i++){
int wei = 0;// 位数
int j = 0;//j:代替i,防止i变化
j = i;
//位数计算
while(j > 0){ //判断到最后
wei++;
j /= 10; //除数运算例如123/10 得出12余3
}
//各 位值 计算
int sum = 0; //sum:总和
int num = 0; //num:代替i,防止i变化
num = i;
int mo = 0; //各位数值
while(num > 0){
mo = num%10; //取余获取位数值
sum += pow(mo, wei); //pow函数
num /=10;
}
if(sum == i){
printf("位数是%d,水仙花数是%d\n",wei,sum);
}
}
return 0;
}
/*
{
int num,i;
for(i = 100;i <1000;i++){
num = i;
int sum = 0;
while(num > 0){
int mo = num%10;
sum += mo*mo*mo;
num /= 10;
}
if(sum == i){
printf("水仙花数是%d\n",sum);
}
}
return 0;
}
*/
2. 冒泡排序法
#通过多次遍历待排序的元素,每次比较相邻的两个元素,将较大(或较小)的元素交换至右侧,逐渐将最大(或最小)的元素“浮”到最右侧(或最左侧),直至所有元素都按序排列。
#include <stdio.h>
int main()
{
int arr[] = {24,244,222,333,2};
int i,j;
int len;
int tmp;
len = sizeof(arr)/sizeof(arr[0]); //确认arr大小
for(i = 0;i<len-1;i++){
for(j = 0;j < len -1-i;j++){ //选出最小的放在最后边
if(arr[j] > arr[j+1]){
tmp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = tmp;
}
}
}
for(i = 0;i < len;i++){
printf("%d ", arr[i]);
}
return 0;
}
//封装函数冒泡
#include <stdio.h>
void sort_arr(int arr[])
{
int i,j,tmp;
for(i = 0;i < 4;i++){
for(j = 0;j < 5-i-1;j++){
if(arr[j] > arr[j+1]){
tmp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = tmp;
}
}
}
printf("排序后\n");
for(i = 0;i < 5;i++){
printf("%d ",arr[i]);
}
}
int main()
{
int arr[5];
printf("please input 5 data\n");
for(int i = 0;i < 5;i++){
scanf("%d",&arr[i]);
}
printf("排序前\n");
for(int i = 0;i < 5;i++){
printf("%d ",arr[i]);
}
sort_arr(arr);
return 0;
}
3. 二维数组找最大数以及所在行列
#由一维数组组成的数组
#include <stdio.h>
int main()
{
int arr[3][4] = {23,34,4,123,34,123,34,494,444,211,111,1}; //可以不写行,但是要写列
int max = arr[0][0];
int i,j;
int max_i,max_j;
for(i = 0;i < 3;i++){
for(j = 0;j < 4;j++){
if(arr[i][j] > max){
max = arr[i][j];
max_i = i;
max_j = j;
}
}
}
for(i = 0;i < 3;i++){
for(j = 0;j < 4;j++){
printf("%d\t",arr[i][j]);
}
putchar('\n');
}
printf("最大数是%d,在第%d行,%d列",max,max_i+1,max_j+1);
return 0;
}
4. 嵌套函数示例
#在一个函数内部定义另一个函数的情况
#include <stdio.h>
int getbig(int a,int b)
{
int max;
max = (a > b)?a:b;
return max;
}
int getmax(int a,int b,int c,int d)
{
int max;
max = getbig(a,b);
max = getbig(max,c);
max = getbig(max,d);
return max;
}
int main()
{
int a,b,c,d,max;
puts("输入四个数字");
scanf("%d%d%d%d",&a,&b,&c,&d);
max = getmax(a,b,c,d);
printf("最大的数字是%d",max);
return 0;
}
5. 递归函数求学生年龄以及阶乘
#指在函数内部调用自身的函数
#include <stdio.h>
int getfac(int fac);
int getage(int num); //函数声明 当函数体在调用前时需要,函数的声明最好在文件的顶部
int main()
{
int age;
int num;
puts("你想知道第几个学生的年龄\n");
scanf("%d",&num);
age = getage(num);
printf("他的年龄是%d\n",age);
int fac;
int number;
puts("你想知道数字几的阶乘\n");
scanf("%d",&number);
fac = getfac(number);
printf("阶乘结果是%d\n",fac);
return 0;
}
int getage(int num){
int data;
if(num == 1){
data = 10;
}else {
data = getage(num-1)+2;
}
return data;
}
int getfac(int number){
int fac;
if(number == 1){
fac = 1;
}else {
fac = getfac(number-1)*number;
}
return fac;
}
6. 函数指针
#函数指针是指向函数的指针变量
#include <stdio.h>
// 定义一个函数max,返回x和y中的较大者
int max(int x, int y){
return x > y ? x : y;
}
int main() {
int (*p)(int, int) = &max; // p 是函数指针,指向具有相同参数和返回值的函数max
int a, b, c, d;
printf("输入三个数: "); // 提示用户输入三个数
// 从用户输入中获取三个整数值
scanf("%d %d %d", &a, &b, &c);
// 与直接调用函数等价,d = max(max(a, b), c)
d = p(p(a, b), c);
// 输出最大的数字
printf("最大的数字是: %d\n", d);
return 0; // 程序正常终止
}
/*
详解每行代码:
1. #include <stdio.h>: 包含标准输入输出库的头文件。
2. int max(int x, int y): 定义了一个名为max的函数,它接受两个整型参数x和y,并返回较大的那个数。
3. int main() {: 主函数的开始。
4. int (*p)(int, int) = &max;: 声明了一个指向函数的指针p,并将其初始化为指向函数max的指针。&操作符用于获取函数的地址,但在这里可以省略,因为函数名本身就是函数的地址。
5. int a, b, c, d;: 声明了四个整型变量a、b、c、d。
6. printf("输入三个数: ");: 输出提示信息,提示用户输入三个数。
7. scanf("%d %d %d", &a, &b, &c);: 从用户输入中获取三个整数值,并分别赋值给变量a、b、c。
8. d = p(p(a, b), c);: 通过函数指针p调用max函数,计算a和b中的较大者,然后再计算出这个较大者和c中的较大者,并将结果赋值给d。
9. printf("最大的数字是: %d\n", d);: 输出变量d的值,即最大的数。
10. return 0;: 返回0,表示程序正常终止。
/*
7. 指针函数
#指返回指针的函数,也可以说是一个返回指针的函数指针
#include <stdio.h>
#include <stdlib.h>
//动态分配一个包含5个整数的数组,并对数组中的元素进行赋值,然后输出数组中的元素,并最后释放动态分配的内存
int* createArray(int size) {
int* arr = (int*)malloc(size * sizeof(int)); // 使用malloc动态分配内存
return arr; // 返回指向动态分配数组的指针
}
int main() {
int* arrayPtr; // 声明一个指向整型的指针变量
arrayPtr = createArray(5); // 调用指针函数,获取指向动态分配数组的指针
for (int i = 0; i < 5; i++) {
arrayPtr[i] = i; // 给动态分配的数组赋值
}
for (int i = 0; i < 5; i++) {
printf("%d ", arrayPtr[i]); // 输出数组中的元素
}
free(arrayPtr); // 释放动态分配的内存
return 0;
}
/*
详细解释:
1. #include <stdio.h> 和 #include <stdlib.h>: 这两行代码是预处理器指令,用于包含标准输入输出和动态内存分配函数的头文件。
2. int* createArray(int size) {: 这是一个函数定义,函数名为createArray,它接受一个整型参数size,并返回一个指向整型的指针。
3. int* arr = (int*)malloc(size * sizeof(int));: 在createArray函数中,使用malloc动态分配了一个大小为size个整型的内存块,并将其地址赋值给指针变量arr。函数malloc返回void类型的指针,因此需要进行类型转换为int类型。分配内存空间以存储整型数据。
4. return arr;: 函数createArray返回指向动态分配数组的指针arr。
5. int* arrayPtr;: 在main函数中声明一个指向整型的指针变量arrayPtr。
6. arrayPtr = createArray(5);: 调用createArray函数,获取指向动态分配数组的指针,并将其赋值给arrayPtr。
7. arrayPtr[i] = i;: 使用循环对动态分配的数组赋值。
8. printf("%d ", arrayPtr[i]);: 打印数组中的元素。
9. free(arrayPtr);: 释放动态分配的内存空间,以避免内存泄漏。
10. return 0;: 返回0,表示程序正常执行结束。
*/
8. 函数传值调用
#传递数值,调用的函数中数值交换不影响main中数值,单纯的传递两个数值
#include <stdio.h>
void exchage(int a,int b)
{
int tmp;
tmp = a;
a = b;
b = tmp;
printf("void_a的数值是%d 地址是%p ",a,&a);
printf("void_b的数值是%d 地址是%p ",b,&b);
putchar('\n');
}
int main()
{
int a = 10;
int b = 20;
printf("传递数值前\n");
printf("a的数值是%d 地址是%p ",a,&a);
printf("a的数值是%d 地址是%p ",b,&b);
putchar('\n');
putchar('\n');
exchage(a,b);
putchar('\n');
printf("传递数值后\n");
printf("a的数值是%d 地址是%p ",a,&a);
printf("a的数值是%d 地址是%p ",b,&b);
return 0;
}
9. 函数引值调用
#传递main中变量地址,在调用函数中将地址内数值改变,从而改变了main中变量数值
#include <stdio.h>
void exchage(int *a,int *b)
{
int tmp;
tmp = *a; //更换了地址内的数值,地址不变
*a = *b;
*b = tmp;
printf("void_a的数值是%d 地址是%p ",*a,a);
printf("void_b的数值是%d 地址是%p ",*b,b);
putchar('\n');
}
int main()
{
int a = 30;
int b = 20;
printf("传递数值前:\n");
printf("a的数值是%d 地址是%p ",a,&a);
printf("a的数值是%d 地址是%p ",b,&b);
putchar('\n');
putchar('\n');
exchage(&a,&b);
putchar('\n');
printf("传递数值后:\n");
printf("a的数值是%d 地址是%p ",a,&a);
printf("a的数值是%d 地址是%p ",b,&b);
return 0;
}
10. 回调函数
#由别人的函数执行时调用你实现的函数
#include <stdio.h>
#include <stdlib.h>
void fill_arr(int *arr, size_t data, int (*getdata)(void))
//接受一个整型指针 arr,一个 size_t 类型的整数 data,和一个返回整型的
// 函数指针作为参数。函数通过调用传递的函数指针 getdata 来填充传入的整型数组 arr。
{
for(size_t i = 0;i < data;i++)
arr[i] = getdata();//调用传递的函数指针
}
//rand 是C标准库中的一个函数,用于生成一个介于0和RAND_MAX之间的伪随机整数。
int getdata(void)
{
return rand();
}
int main()
{
int arr[5];
int i;
fill_arr(arr,5,getdata);
for(i = 0;i < 5;i++){
printf("数值为%d\n",arr[i]);
}
return 0;
}
11. 指针数组
#是一个数组,其中每个元素都是指针
#include <stdio.h>
const int MAX = 3;
int main()
{
int arr[] = {1,5,11};
int i;
for(i = 0;i < MAX;i++){
printf("arr[%d]= %d\n",i,arr[i]);
}
int j;
int *ptr[MAX];//int *ptr[MAX]; == int* ptr[MAX];
int arr1[3] = {2,6,14};
for(j = 0;j < MAX;j++){
ptr[j] = &arr1[j]; //取arr地址赋值给指针ptr
}
for(j = 0;j < MAX;j++){
printf("ptr[%d]= %d\n",j,*ptr[j]); //指针取值需要用*
}
return 0;
}
12. 数组指针
#数组指针本身是一个指针,指向整个数组,而不是数组中的单个元素。通常用于处理多维数组。
#include <stdio.h>
void printArray(int (*arrPtr)[3], int rows) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", arrPtr[i][j]);
}
printf("\n");
}
}
int main() {
int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
int (*ptr)[3] = arr;
printArray(ptr, 2);
return 0;
}
13.二级指针
#指向指针的指针,常用于存储和管理不同类型或不同数量的数据结构。
#include <stdio.h>
int main()
{
int a = 10;
printf("a的数值是:%d,地址是:%p\n",a,&a);
int *p;
p = &a;
printf("通过p取出的数值是:%d, p存放的地址是:%p, 存放p的地址是%p\n",*p,p,&p);
int **p1;
p1 = &p;
printf("通过p1取出的数值是%d, p1指向p存放的地址是:%p, pi存放的地址是:%p, 存放p1的地址是%p\n",**p1,*p1,p1,&p1);
return 0;
}
14. 对几个班级不同个数学生计算分数
#include <stdio.h>
#include <stdlib.h>
//函数声明
void assignment(int arrclass[],int num);
void printscore(int arr[],int num);
float getaverage(int arr[], int num);
void manage(int classnum)//班级循环计算函数
{
for(int i = 0;i < classnum;i++){
int numstudents; //学生个数
printf("Enter the number of students in class %d: ", i + 1);//输入班级学生个数
scanf("%d", &numstudents);
//动态分配了numstudents * sizeof(int)个字节大小的内存空间,将其首地址赋值给指针变量arrclass
//malloc函数返回的是void*类型的指针,(int *)是将指针强制转换为指向整型的指针
int *arrclass = (int *)malloc(numstudents * sizeof(int));
//处理内存分配失败
if (arrclass == NULL) {
printf("Memory allocation failed. Exiting...\n");
exit(1);
}
printf("current calss number %d\n",i+1);
assignment(arrclass,numstudents);//赋值
printscore(arrclass,numstudents);//打印
float average = getaverage(arrclass,numstudents);//计算平均分
printf("classone %d average scora is %.2f\n",i+1,average);
free(arrclass); // 释放动态分配的内存
}
}
void assignment(int arrclass[],int num)
{
int i;
printf("please input student score\n");
for(i = 0;i < num; i++){
scanf("%d",&arrclass[i]);
}
}
void printscore(int arr[],int num)
{
int i = 0;
for(i =0;i < num;i++){
printf("student(%d)score is %d \n",i,arr[i]);
}
}
float getaverage(int arr[], int num)
{
int sum = 0;
float average;
for(int i = 0;i < num;i++){
sum += arr[i];
}
average = (float)sum/num;
return average;
}
int main()
{
int classnum;
//确认有几个班级
printf("Please enter the number of classes for which you want to calculate the average score \n");
scanf("%d", &classnum);
manage(classnum);
return 0;
}
或者
#include <stdio.h>
int main() {
int numClasses, numStudents, i, j;
float average, sum;
// 询问用户要处理几个班级的学生
printf("请输入要处理几个班级的学生: ");
scanf("%d", &numClasses);
for (i = 1; i <= numClasses; i++) {
sum = 0; // 每个班级的学生成绩总和初始化为0
// 获取当前班级有几个学生
printf("请输入第%d个班级有几个学生: ", i);
scanf("%d", &numStudents);
printf("请输入第%d个班级%d位学生成绩:\n", i, numStudents);
for (j = 1; j <= numStudents; j++) {
float score;
printf("请输入第%d位学生的成绩: ", j);
scanf("%f", &score);
sum += score; // 累加成绩到总和
}
average = sum / numStudents; // 计算平均成绩
printf("第%d个班级的平均分为: %.2f\n", i, average);
}
return 0;
}
15. 选择排序
#在未排序的序列中选择最小(或最大)的元素,然后将其放置在已排序序列的末尾
#include <stdio.h>
void selectionSort(int arr[], int n) {
int i, j, minIndex, temp;
// 外层循环遍历数组
for (i = 0; i < n - 1; i++) {
// 假设当前位置是最小值的索引
minIndex = i;
// 在未排序部分中找到最小元素的索引
for (j = i + 1; j < n; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
// 将未排序部分中的最小元素与当前位置交换
if (minIndex != i) {
temp = arr[minIndex];
arr[minIndex] = arr[i];
arr[i] = temp; //保证每次i循环后 arr[i]是最小的
}
}
}
int main() {
// 定义一个整数数组
int arr[] = {64, 34, 25, 12, 22, 11, 90};
// 获取数组长度
int n = sizeof(arr) / sizeof(arr[0]);
// 输出未排序数组
printf("Unsorted array: \n");
for(int i = 0; i < n; i++){
printf("%d ", arr[i]);
}
printf("\n");
// 调用选择排序函数对数组进行排序
selectionSort(arr, n);
// 输出排序后的数组
printf("Sorted array: \n");
for(int i = 0; i < n; i++){
printf("%d ", arr[i]);
}
return 0;
}
16.内存操作
#include <stdio.h>
int main()
{
int a = 10;
printf("memory is %p\n",&a);
volatile unsigned int *p = (volatile unsigned int*)0x7fffffffd964;
printf("memory is %p\n",p);
return 0;
}
在 int main() 函数中:
int a = 10;:定义了一个整数变量 a 并初始化为10。
printf("memory is %p\n", &a);:使用%p格式说明符打印变量 a 的内存地址,即 &a将显示 a 变量在内存中的地址。
volatile unsigned int *p = (volatile unsigned int*)0x7fffffffd964;:声明了一个 volatile 修饰的无符号整型指针变量 p,并将其指向内存地址 0x7fffffffd964。
printf("memory is %p\n", p);:同样打印了指针 p 指向的内存地址。
volatile 关键字:
在C语言中,volatile 是一个类型限定符,表示变量的值可能在程序的其他地方被修改,因此编译器不应该对这个变量的存取进行优化。
在这段代码中,使用 volatile 关键字修饰指针 p,表明 p 指向的内存地址可能会发生变化。
注意事项:
直接操作内存地址是一项高级操作,不应该随意进行。确保了解清楚内存地址的情况,避免访问非法内存区域。在实际开发中,应谨慎使用类似直接操作内存地址的技术,以确保程序的稳定性和安全性。