目录
前言:临近期末,接下来给大家分享一些经典的编程题,方便大家复习。不一定难,但都是入门的好题,尽可能的吃透彻。因为据说期末考试的题很多来自pta上面的原题。
对于一些语言我是用c++来写的,不妨碍理解,大家把cin,getline看作是c语言中的scanf,把cout, 看作是c语言中的printf ,把#include看作是c的头文件。
循环:
第一题:求满足条件的斐波拉契数:
第二题:求n以内最大k个素数以及他们的和
第三题:英文字母替换加密
第四题:查验身份证
数组:
第一题:
第二题:字符串字母大小写转换编辑
第三题:统计一行文本的单词个数
第四题:求整数序列中出现次数最多的数
第五题:交换最小值和最大值
第六题:求矩阵各行元素之和
函数:
第一题:杨辉三角形
第二题:歌词比赛打分
第三题:数据排序
第四题:近似求PI
第五题:哥德巴赫猜想
第六题:Jack cheng的烦恼3
指针:
第一题:字符串的连接
第二题:删除字符串中数字字符
第三题:输出学生成绩
第四题:删除字符串中指定字母
第五题:用指针方法求10个数最大和最小值之差
博主对大家说的话:
最后的最后还是想给大家说,相信在初学的过程中定然会有些吃力与不理解,但可以适当地取舍,先跳过,把在能力范围内的题目先整懂,相信自己一定能整明白,只是时间问题,就像翁恺老师在视频里说我们大家都是一个脑子,你能搞懂的我也能搞懂。其实我开始在做一些题的时候也很吃力,但当你能力慢慢提高之后再回过头来看这个题,以及之前迷糊的题,你会有新的感悟。相信通过以上题目,大家对c语言基础有了新的理解,感谢大家的阅读,期待下次与你见面。
分析:为什么上这道题,不是因为难而是因为,有一年考到过斐波拉契函数,所以记下来就好,没什么好说的
#include
int fib(int n);
int main() {
int i, n;
scanf("%d", &n);//输入数
for (i = 1;; i++) //让i来自增遍历所有斐波拉契数
{
if (fib(i) > n)
{
printf("%d", fib(i));
break;//一旦大于就跳出循环
}
}
return 0;
}
int fib(int n) //斐波拉契函数
{
if (n <= 2) {
return 1;
}
else {
return fib(n - 1) + fib(n - 2);
}
}
思路:首先要输出不超过n的最大的k个素数,我们就先从n-1开始遍历,然后看输出的格式,肯定要定义一个数组arr来存放这些数字,但数目又是有限的,所以每得到一个素数,k就要减一,当k为0的时候跳出循环,这样思路打开了,然后最后输出的时候注意一下格式,最后一个数字不用输出+,就OK了。
思路:
按步就班,这里我用c++实现,大家用c语言也是一个原理,大家可以定一个字符数组然后用scanf
读取,和
string str;
getline(cin, str);
本质是一样,然后呢,求字符串长度len可以用strlen库函数来实现,cout大家就换成printf输出,在判断是否是字母的语句可以换成用逻辑符号判断,即在首字母和末尾字母的区间里面,然后变成大写的可以换成str[i]-32来实现,变成大写也是同理。总体的思路就是先遍历,然后判断每一个字符是不是字母,如果是那么是大写还是小写,如果不是那么就不动自动输出。
#include
using namespace std;
string newstr(string str);
int main()
{
string str;
getline(cin, str);
str = newstr(str);
cout << str;
return 0;
}
string newstr(string str)
{
int len = str.size();
for (int i = 0; i < len; i++)
{
if (isalpha(str[i]))//是字母
{
if (islower(str[i]))//shi xiao xie
{
str[i] = toupper(str[i]);
if (str[i] == 'Z')
{
str[i] = 'A';
}
else
str[i]++;
}
else
{
str[i] = tolower(str[i]);
if (str[i] == 'z')
{
str[i] = 'a';
}
else
str[i]++;
}
}
}
return str;
}
思路:这道题相对来说还是比较难,一般人写不出除非你是二班的人。
写法还是一个,那就是读懂题意见招拆招。首先身份证不合格有两种一种是前十七个字符有字母另外一种就是第十八位字符为错误。并且要理解加权的意思,最终我们要和验证码来比较,我们可以验证码弄一个数组,把验证码数组的下标当成我们加权求和然后%11的结果来比较是否相同。细节的地方就是在求和的时候,因为sfz是字符数组要减去'0'才是我们计算的数字。
#include
using namespace std;
int main()
{
char str[11] = { '1','0','X','9','8','7','6','5','4','3','2' };//验证吗
char sfz[18];
int jq[17] = { 7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2 };
int n, sum = 0;
cin >> n;
int n1 = n;
int flag = 0;
while (n--)
{
//cin.getline(sfz, 18);//输入身份证
cin >> sfz;
sum = 0;
for (int i = 0; i < strlen(sfz)-2; i++)//
{
if (!(isdigit(sfz[i])))//说明存在字母
{
cout << sfz << endl;
break;
}
else//不存在字母,则计算加权和
{
sum += jq[i] * (sfz[i] - '0');
}
}
if (sfz[17] != str[sum % 11])
{
cout << sfz << endl;;
}
else
flag++;
}
if (n1 == flag)
{
cout << "All passed";
}
return 0;
}
思路:里面的sort你可以换成冒泡排序也是一样的做法,cin你换成scanf,cout换成printf。整体的思路你应该看的明白,注意每一次算一个人的成绩时,要把sum归0,不然就会多算,然后就是要输出,单科平均成绩最大及序号,没必要多开数组,总成绩最大,单科平均就最大,人数都是一样的,然后定义个变量记录下来就ok了
思路:明白大小写转化之间的关系,这里c实现和c++实现都给大家呈现,
#include
#include
int main() {
char s[100];
scanf("%s",s);
for(int i = 0; s[i] != '#'; i++) {
if (s[i] >= 'A' && s[i] <= 'Z') {
s[i] += 32;
}
else if (s[i] >= 'a' && s[i] <= 'z') {
s[i] -= 32;
}
}
for (int i = 0; s[i] != '#'; i++) {
printf("%c",s[i]);
}
return 0;
}
c++:
#include
using namespace std;
int main()
{
string s;
for (int i = 0; s[i] != '#'; i++)
{
if (islower(s[i]))
s[i] = toupper(s[i]);
else if (isupper(s[i]))
s[i] = tolower(s[i]);
}
for (int i = 0; s[i] != '#'; i++) {
printf("%c", s[i]);
}
return 0;
}
这个题要考虑的情况也不少,可能开头就有空格,这里给大家介绍一种简洁的方式istringstream 在这段代码中的作用是将输入的字符串 line 转换为字符串流对象 iss,然后我们可以使用 iss 从中逐个读取单词并进行处理。并且不会将空格读入
#include
using namespace std;
int main()
{
string line;
getline(cin, line);
istringstream iss(line);
int count = 0;
string word;
while (iss >> word)
{
count++;
}
cout << count << endl;
return 0;
}
思路:这题没什么说的,按部就班。用一个计数器,出现一次加一次,两次遍历,如果比最大的次数大就更新。
#include
int main()
{
int n,i,j;
scanf("%d",&n);
int a[10000];
int count=0;
int max=0,maxcount=0;
for(i=0;imaxcount)
{
maxcount=count;
max=a[i];
}
count=0;
}
printf("%d %d",max,maxcount);
return 0;
}
思路:一步步实现,代码大家应该看得懂,看不懂的留言。这是最朴实无华的写法了
#include
int main()
{
int n=0;
int a[10]={0};
int max=0;
int min=0;
int t=0;
scanf("%d",&n);
//将所有数字存入数组a中
for (int i=0;ia[max])
{
max=i;
}
}
//将最大值与元素数组最后一个交换位置
t=a[max];
a[max]=a[n-1];
a[n-1]=t;
//遍历并打印数组a的元素
for(int j=0;j
#include
int main(){
int m, n;
do{
scanf("%d %d", &m, &n);
}while( m<1 || n>6 ); // 确保m,n的范围
int mat[m][n]; // 定义矩阵
for( int i=0; i
思路:要写这个还是要知道这个杨辉三角怎么构成,第一行第一个和每行最后一个都是1,然后中间的项存在a[i][j]=a[i-1][j]+a[i-1][j-1]的规律
void fun(int a[N][N], int n)
{
for (int i = 0; i < n; i++)
{
a[i][0] = 1;
a[i][i] = 1;
for (int j = 1; j < i; j++)
{
a[i][j] = a[i - 1][j] + a[i - 1][j - 1];
}
}
}
思路:还是要知道指针的一些知识,p+i表示指针所指向的对象,看不明白的可以看我指针的博客,复习一下再来整
思路:先找最高然后找最低,用总的减去,然后除总个数减2,
double getScore(int* score, int total)
{
double max = -1, min = 101, sum = 0;
for (int i = 0; i < total; i++)
{
sum += *(score + i);
if (*(score + i) > max)
{
max = *(score + i);
}
if (*(score + i) < min)
{
min = *(score + i);
}
}
return (sum - max - min) / (total - 2);
}
排序算是一个重点,这里给大家介绍两种简单的排序。
一个冒泡排序一个选择排序,有点迷的可以去学一下
冒泡排序:
void fun(int a[], int n)
{
for (int i = 0; i < n - 1; i++)
{
for (int j = 0; j < n - 1 - i; j++)
{
if (a[j] > a[j + 1])
{
int temp=a[j+1];
a[j+1]=a[j];
a[j]=temp;
}
}
}
}
选择排序:
void fun(int a[], int n)
{
int i, j, k;
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
if (a[j] > a[i])
{
k = a[j];
a[j] = a[i];
a[i] = k;
}
}
}
}
思路:题目看似抽象,其实仔细分析还是好整。观察出通项,然后记得每一项都是在前一项的基础上再乘,接着求和即可。
找通项规律,i/(2*i+1);每一项是在前一项的基础上乘
#include
using namespace std;
int main()
{
double i = 1;
double eps, sum = 1;
cin >> eps;
double item = 1;
while (item >= eps)
{
item = item*1.0 * (i / (2 * i + 1));
i++;
sum += item;
}
printf("PI = %.5lf", sum * 2);
return 0;
}
思路:这个题之前讲过,再次搬出来说明它的重要性。这个题其实就是素数的那道题的变式,关键是分解成最小的素数,所以你从2开始遍历,找到最小的就用n-最小的,得到另外一个数,如果这个数也是素数则符合条件跳出
思路:道题也是素数的一个变式,你只需要把n的每一位数提取出来,求和,然后判断是否为素数即可
先让指针s自增,直到他指向\0,然后开始赋值,最后别忘了把\0填上去
//连接两个字符串,思路就是s接受的是str1的地址,t接受的是str2的地址,那么要把t赋值到s的末端,只需
//指向str1的指针s自增到/0的位置,然后把str2赋给str1,同时两种指针向后移动
//char* str_cat(char* s, char* t)
//{
// char* p = s;
// while (*s != '\0')
// {
// s++;
// }
// //出循环的时候s指向的是/0位置
// //开始把str2赋给str1;
// int i = 0;
// while (*(t+i) != '\0')
// {
// *(s+i) = *(t+i);
// i++;
// }
// *(s + i) = '\0';
// return p;
//}
思路:
首先要求得字符串的长度,然后开始遍历,判断是否是数字字符,如果是,就记录当前的位置,将后续的字符往前移动,最后要把i--,原因就是当移动完之后如果不减的话回到循环体i++之后会指向下一个位置,这个时候如果有连续的数字字符,就跳过了这个情况。
void delnum(char* s) {
if (s == NULL) {
return;
}
char digit[10] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
int i = 0;
int len = 0;
while (*(s + len) != '\0') {
len++; // 获取字符串长度
}
for (i = 0; i < len; i++) {
if (*(s + i) >= '0' && *(s + i) <= '9') { // 判断是否为数字字符
int j = i;
while (*(s + j) != '\0') {
*(s + j) = *(s + j + 1); // 将后续字符往前移动
j++;
}
i--;// 需要回退一步,原因就是当是连续字符的时候你回到for循环的时候,你的i又会加1,那么它就不会处理当前的字符,万一当前的字符是数字呢?
}
}
}
思路:按步就班,注意数据类型,
#include
using namespace std;
int main()
{
double n, max = -1, min = 101;
cin >> n;
double sum = 0, avg = 0;
int n1 = n;
while (n--)
{
int score;
cin >> score;
sum += score;
if (score > max)
max = score;
if (score < min)
min = score;
}
avg = sum * 1.0 / n1;
printf("average = %.2lf\nmax = %.2lf\nmin = %.2lf",avg,max,min);
return 0;
}
思路:这道题和前面的删除数字字符类似,唯一要注意的就是要将i--,防止指定的字母是连续的状态,
#include
#include
using namespace std;
int main() {
char a[101] = { 0 };
char* p = a;
scanf("%s", a);
int len = strlen(a);
int i, j;
for (i = 0; i < len; i++) {
if (a[i] == 'a') {
j = i;
while (*(p + j) != '\0') {
*(p + j) = *(p + j + 1);
j++;
}
i--; // 由于删除一个字符,需要将 i 回退一个位置
len--; // 更新字符串长度
}
}
cout << a << std::endl;
return 0;
}
#include
using namespace std;
int main()
{
int arr[10];
int* p = arr;
int min = arr[0], max = arr[0];
for (int i = 0; i < 10; i++)
{
cin >> *(p + i);
if (*(p + i) > max)
max = *(p + i);
if (*(p + i) < min)
min = *(p + i);
}
cout << "difference value = " << max - min;
return 0;
}
然后给大家扩展一下用指针实现冒泡排序