C语言考研机试(自用)


一、注意事项

  • %c是一个格式化转换说明符,用于读取或输出一个字符;%s是字符串
  • %f:表示输出一个浮点数
  • %lf:表示将输入的值解释为双精度浮点数
  • %.2f:表示输出一个浮点数并保留两位小数,对应的变量是y。
  • A=a-32,A的ASCII是65,a是97
  • scanf_s("%c", &a, 1);
  • #include<math.h>
  • sqrt(x);//求平方根
  • abs(x);//绝对值
  • pow(x,y);//x的y次方
  • 最大公约数

欧几里得算法求解两个数的最大公约数

假设两个数是 48 和 18。

48 / 18 = 2余12  18 / 12 = 1余6  12 / 6 = 2余0

当余数为 0 时,停止计算,此时除数 6 就是最大公约数,因此,数48和18,它们的最大公约数为 6。例题:最大公约数和最小公倍数

  • 最小公倍数

常用的方法是利用最大公约数(GCD)来求解。

首先,计算这两个数的最大公约数。使用欧几里得算法,可以求得它们的最大公约数为 6。

使用以下公式来计算最小公倍数:最小公倍数 = (第一个数 × 第二个数) / 最大公约数

最小公倍数 = (12 × 18) / 6 = 36因此,对于12和18,最小公倍数为 36。

  • 闰年  
int RN==year % 400 == 0 || ( year % 4 == 0 && year % 100 != 0)

        例题: 年月日nextday

  • 值传递

在C语言中,参数传递可以通过值传递和引用传递两种方式进行。

值传递是指将变量的值复制一份传递给函数,函数内对该值的修改不会影响main函数中变量的取值。在函数内部修改参数的值不会影响函数外部的变量。

引用传递(指针传递):是指通过传递变量的地址(指针)来操作变量,函数内对该地址的修改会影响原始变量的取值。在函数内部通过指针修改参数的值会影响函数外部的变量。

  • 因子 完数 素数
  • 因子是指能够整除一个数的正整数,例如6的因子包括1、2、3和6。例题:完数和盈数
for(i=1 ; i<n ; ++i)
    {if( n%i == 0) 
         printf ( “ %d ”,i );
}
  • 完数是指一个数恰好等于它的所有因子(不包括它本身)之和的数,例如6是一个完数,因为6的因子是1、2、3,而1+2+3=6。
  • 素数是指大于1的自然数中,除了1和它本身以外没有其它因子的数,也就是只能被1和自身整除的数。素数又称质数,例如2、3、5、7等都是素数

二、新学习的知识

vector动态数组

例题:完数和盈数

#include<stdio.h>
#include <vector>
#include<list>
using namespace std;
int main() {
    //vector 动态数组 类线性表
        //创建动态数组
            vector<int>vec1;//size=0
            vector<int>vec2[10];//size=10
            vector<int>vec3 = { 1,3,5 };//size=3,vec[0]=1下标访问数组
        //尾端插入
            int a = 7;
            vec3.push_back(a);//往动态数组尾部插入
        //遍历
            int size3 = vec3.size();
            for (int i = 0; i < size3; ++i) {
                printf("vec3[i]=%d\n", vec3[i]);
            }

}

iterator迭代器(高级指针)

例题:剩下的树

//iterator 迭代器  作用:获取元素位置(高级指针)
    //创建及遍历
        vector<int>vec4 = { 2,4,6,8,10 };
        vector<int>::iterator it;
        for (it = vec4.begin(); it != vec4.end(); ++it) {
            printf("*it=%d\n", *it);
        }
    //遍历完以后需要重新设置iterator位置
        it=vec4.begin();
    //在迭代器指向位置用insert插入数字55
        vec4.insert(it, 55);
        //insert会改变动态数组的结构,插入完成以后it的指向无意义要重新设置it的位置
        it = vec4.begin();
    //it指向移动可用加法
    it = it + 3;
    //清空数据
    vec4.clear();
    //删除最后一个元素
    vec4.pop_back();
    //删除it所指向位置的元素
    vec4.erase(it);

list双向链表

#include<list>
//list 双向链表
    //创建链表
    list<int>ls1 = { 1,3,5,7,9 };
    list<int>::iterator it = ls1.begin();
    //链表不支持随机访问,不能用"+",可以用自增
    ++it;
    ++it;
    //删除迭代器it所知位置元素
    ls1.erase(it);
    for (it = ls1.begin(); it != ls1.end(); ++it) {
        printf("*it=%d\n", *it);
    }

 样例代码

#include<stdio.h>
#include <vector>
#include<list>
using namespace std;
int main() {
    
    //vector 动态数组 类线性表
        //创建动态数组
            vector<int>vec1;//size=0
            vector<int>vec2[10];//size=10
            vector<int>vec3 = { 1,3,5 };//size=3,vec[0]=1下标访问数组
        //尾端插入
            int a = 7;
            vec3.push_back(a);//往动态数组尾部插入
        //遍历
            int size3 = vec3.size();
            for (int i = 0; i < size3; ++i) {
                printf("vec3[i]=%d\n", vec3[i]);
            }
    
    //iterator 迭代器  作用获取元素位置(高级指针)
        //创建及遍历
            vector<int>vec4 = { 2,4,6,8,10 };
            vector<int>::iterator it;
            for (it = vec4.begin(); it != vec4.end(); ++it) {
                printf("*it=%d\n", *it);
            }
        //遍历完以后需要重新设置iterator位置
            it=vec4.begin();
        //在迭代器指向位置用insert插入
            vec4.insert(it, 55);
            int size4 = vec4.size();
            for (int i = 0; i < size4; ++i) {
                printf("vec4[i]=%d\n", vec4[i]);
            }
            //insert会改变动态数组的结构,插入完成以后it的指向无意义
            //要重新设置it的位置
            it = vec4.begin();
        //it指向移动可用加法
        it = it + 3;
        //清空数据
        vec4.clear();

        //删除最后一个元素
        printf("-----------------\n");
        it = vec3.begin();
        vec3.pop_back();
        for (it = vec3.begin(); it != vec3.end(); ++it) {
            printf("*it=%d\n", *it);
        }
        //删除某一位置元素
        printf("-----------------\n");
        it = vec3.begin();
        vec3.erase(it);
        for (it = vec3.begin(); it != vec3.end(); ++it) {
            printf("*it=%d\n", *it);
        }

       
    //list 双向链表
        //创建链表
        list<int>ls1 = { 1,3,5,7,9 };
        list<int>::iterator it = ls1.begin();
        //链表不支持随机访问,不能用"+",可以用自增
        ++it;
        ++it;
        //删除迭代器it所知位置元素
        ls1.erase(it);
        for (it = ls1.begin(); it != ls1.end(); ++it) {
            printf("*it=%d\n", *it);
        }
}

优缺点 

vector创建的动态数组,是一个顺序表,支持随机存取,故具有顺序表的特性,移动可用加法

在尾端进行插入和删除操作较为方便,但是在数组中间进行插入删除时,效率低!

因此不建议使用vce.erase()删除和vec.inster(it,99)插入

相反,list创建的是链表,用它的进行插入和删除操作很方便!

需要注意的是,链表不支持随机访问,不能用"+",可以用自增

三、机试题目练习

1、字母变换

//1-编写程序,由键盘输入一个小写英文字母,并显示该字母及对应的大写字母
#include<stdio.h>
using namespace std;
int main() {
	char a,b;
	scanf_s("%c",&a,1);//而后面的1表示最大读取字符数目。这个参数用于限制输入的字符数目,以防止缓冲区溢出。
	//有助于确保输入的字符数量不会超出变量所能存储的范围,从而防止缓冲区溢出漏洞。
	b = a - 32;
	printf("%c%c\n", a, b);

	return 0;
}

2、求最大公约数和最小公倍数

//输入两个正整数 m 和 n,求其最大公约数和最小公倍数。
#include<stdio.h>
int main() {
	int num1, num2, a, b,temp;
	scanf_s("%d,%d", &num1, &num2);
	if (num1 < num2) {
		temp = num1;
		num1 = num2;
		num2 = temp;

	}
		a = num1;
		b = num2;
	//求最大公约数a
	while (b != 0) {
		temp = a % b; a = b; b = temp;
	}
	printf("最大公约数是%d\n", a);
	printf("最小公倍数是%d\n", (num1 * num2) / a);//最小公倍数= (num1*num2)/a
	return 0;
}

3、菱形图像打印

#include<stdio.h>
#include<string.h>
int main() {
	char str[100] = { 0 };//设为终止符0
	int n;
	scanf_s("%d", &n);
	int i = 0;//行号
	for (i = 0; i <= n; ++i) {
		int j = 0;
		memset(str, 0, 100);//清空字符串
		for (j = 0; j < 2 * n - 2 * i; ++j) {
			str[j] = ' ';
		}
		for (int k = 0; k <= i; ++k) {
			str[j] = '0' + k;
			str[j + 1] = ' ';
			j = j + 2;
		}
		for (int k = i - 1; k >= 0; --k) {
			str[j] = '0' + k;
			str[j + 1] = ' ';
			j = j + 2;
		}
		printf("%s\n", str);
	}
	for (i = n + 1; i <= 2 * n; ++i) {
		int j = 0;
		memset(str, 0, 100);
		for (j = 0; j < 2 * i - 2 * n; ++j) {
			str[j] = ' ';
		}
		for (int k = 0; k <= 2 * n - i; ++k) {
			str[j] = '0' + k;
			str[j + 1] = ' ';
			j = j + 2;
		}
		for (int k = 2 * n - i - 1; k >= 0; --k) {
			str[j] = '0' + k;
			str[j + 1] = ' ';
			j = j + 2;
		}
		printf("%s\n", str);
	}
	return 0;
}

 4、叠筐问题

#include<stdio.h>
#include<string.h>
int main() {
	int n;//筐的最大长度
	char in, out;//内外层
	char str[50][50] = { 0 };
	while (scanf_s("%d %c %c", &n, &in, &out) != EOF) {
		int i = 0;//层数
		char current = in;//当前需要打印的字符
		memset(str, 0, sizeof(str));
		for (i = 0; i < n / 2; ++i) {
			int x, y;//二维坐标
			//打印上行
			for (x = n / 2 - i, y = n / 2 - i; y <= n / 2 + i; ++y) {
				str[x][y] = current;
			}
			//打印下行
			for (x = n / 2 + i, y = n / 2 - i; y <= n / 2 + i; ++y) {
				str[x][y] = current;
			}
			//打印左列
			for (x = n / 2 - i, y = n / 2 - i; x <= n / 2 + i; ++x) {
				str[x][y] = current;
			}
			//打印右列
			for (x = n / 2 - i, y = n / 2 + i; x <= n / 2 + i; ++x) {
				str[x][y] = current;
			}
			if (in == current) {
				current = out;
			}
			else {
				current = in;
			}
			int p, q;
			for (p = 0; p < n; ++p) {
				for (q = 0; q < n; ++q) {
					printf("%c", str[p][q]);
				}
			}
		}
	}
	return 0;
}

5、年月日nextday

#include<stdio.h>
#include<string.h>
using namespace std;
void NextDay(int &y,int &m,int &d) {
	int dayofmonth[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	int RN = (y % 400 == 0) || (y % 4 == 0 && y % 100 != 0);
	if (RN) {
		dayofmonth[2] = 29;
	}
	else {
		dayofmonth[2] = 28;
	}
	d++;
	if (d > dayofmonth[m]) {
		m++;
		d = 1;
		if (m == 13) {
			y++;
			m = 1;
		}
	}
	//printf("NextDay =%d %d %d\n", y, m, d);
}
//计算日期累加
int main() {
	int n;//n为机组数据
	scanf_s("%d", &n);
	for (int k = 0; k < n; ++k) {

		int y, m, d, plusday;
		scanf_s("%d%d%d%d", &y, &m, &d, &plusday);
			for (int i = 1; i <= plusday; i++) {
				NextDay(y, m, d);
			}
			printf("加上后的日期为%04d-%02d-%02d", y, m, d);
		
	}
	return 0;
}


//计算天数转换为年月日
//int main() {
//	int y, n;
//	while (scanf_s("%d%d", &y, &n) != EOF) {
//		int next = 1;
//		int curmonth = 1;
//		int curday = 1;
//		while (1) {
//			if (n == next) {
//				break;
//			}
//			else {
//				NextDay(y, curmonth, curday);
//				next++;
//			}
//		}
//		printf("%04d-%02d-%02d\n", y,curmonth,curday);
//	}
//	return 0;
//}

//计算下一天
//int main() {
//	int y, m, d;
//	while (scanf_s("%d%d%d", &y, &m, &d) != EOF) {
//		NextDay(y, m, d);
//	}
//	return 0;
//}

6、完数和盈数

题号: 牛客KY20 完数VS盈数

知识点: 动态数组vector的创建、添加、遍历;因子求解办法

题目: 个数如果恰好等于它的各因子(该数本身除外)子和,如:6=3+2+1。则称其为“完数”;若因子之和大于该数,则称其为“盈数”。 求出2到60之间所有“完数”和“盈数”。

#include<stdio.h>
#include<vector>
using namespace std;
//计算因子之和
int Funyinzi_sum(int i) {
	int sum = 0;
	for (int j = 1; j < i; j++) {
		if (i % j == 0) {
			sum = sum + j;
		}
	}
	return sum;
}
int main() {	
	//创建两个动态数组,用于分别保存完数和盈数
	vector<int>wanshu;
	vector<int>yingshu;
	for (int i = 2; i <= 60; i++) {
		int sum = Funyinzi_sum(i);
		if (i == sum) {
			wanshu.push_back(i);
		}
		else if (i < sum) {
			yingshu.push_back(i);
		}

	}
	printf("E:");
	int sizew = wanshu.size();
	for (int i = 0; i < sizew; ++i) {
		printf(" %d", wanshu[i]);
	}
	printf("\n");
	printf("G:");
	int sizey = yingshu.size();
	for (int i = 0; i < sizey; ++i) {
		printf(" %d", yingshu[i]);
	}
	return 0;
}

7、剩下的树

题号:牛客KY25 剩下的树

知识点: 动态数组vector的创建、添加、遍历;迭代器iterator进行遍历

题目: 有一个长度为整数L(1 <= L <= 10000)的马路,可以想象成数轴上长度为L的一个线段,起点是坐标原点,在每个整数坐标点有一棵树,即在0, 1, 2...L共L + 1个位置上有L + 1棵树。
现在要移走一些树,移走的树的区间用一对数字表示,如 100 200表示移走从100到200之间(包括端点)所有的树。可能有M(1 <= M <= 100)个区间,区间之间可能有重叠。现在要求移走所有区间的树之后剩下的树的个数。
两个整数L(1<=L<=10000)和M(1<=M<=100)。     接下来有M组整数,每组有一对数字。

#include<stdio.h>
#include<vector>
#include<iterator>
#include<list>
using namespace std;
int main() {
	int L,M;
	scanf_s("%d%d", &L, &M);
	//创建一个长度为L+1的动态数组,并将每个元素置为0
	vector<int>malu;
	for (int i = 0; i <= L; ++i) {
		malu.push_back(0);
	}
	int left, right;
	for (int i = 1; i <= M; ++i) {
		scanf_s("%d %d", &left,&right);
		//删除操作,将数组清除的地方置为1
		for (int i = left; i <= right; ++i) {
			malu[i] = 1;
		}
	}

	//创建迭代器,用于遍历数组
	vector<int>::iterator it;
	it = malu.begin();
	int sum = 0;
	for (it = malu.begin(); it != malu.end(); ++it) {
		if (*it == 0) {
			sum++;
		}
	}
	printf("%d\n", sum);
	return 0;
}

8、

  • 40
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值