一、注意事项
- %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; }