# NENU 程序设计基础C语言 PTA(1~5章)
这里是大一入学的一门必修,会实现最最基础的C语言内容。
# 前言
作为初学者,可以去各种平台上学习C语言的语法。
善用搜索引擎、代码论坛(CSDN、稀土掘金、stack overflow)、AI(国内的kimi、文心一言、通义千问)进行学习。
可以学习笔者的代码风格,也可以不学习,但是推荐代码里的符号,例如+-*/=的前后都加上空格。
代码换行要注意,以及括号换行也要注意,请尽量保持一种代码风格,不要出现如下这种代码:
#include<stdio.h> int main() { int n; scanf("%d",&n); for(int i = 1;i <= n;i++){ printf("%d",i);} for(int i = n;i >= 1;i--){ for(int j = 1;j <= i;j++) {if(j < i) printf("%d ",j); } printf("\n"); } }
注意学会看报错信息,error开头的那种,不了解就先去搜索,明白”提问的艺术“。
有些字符数组的处理需要用到头文件<string.h>,有些用到根号sqrt计算的需要用到头文件<math.h>。
# 3-1 输出倒三角图案
# 思路:
这道题我们就按照输出格式里的要求输出倒三角形就好,非常的容易~
# 代码C语言:
#include<stdio.h>
int main(){
printf("* * * *\n * * *\n * *\n *");
return 0;
}
# 3-2 计算摄氏温度
# 思路:
这里我们要创建题目里需要的变量:摄氏温度c与华氏温度f,并且都是整型 int 的数据。
然后通过公式计算,输出即可。
# 代码C语言:
#include<stdio.h>
int main(){
int f,c;
scanf("%d",&f);
c=5*(f-32)/9;
printf ("Celsius = %d",c);
return 0;
}
# 3-3 整数四则运算
# 思路:
用变量a和b读入两个正整数,然后把加减乘除分别输出即可。【记得按格式写】
# 代码C语言:
#include<stdio.h>
int main(){
int a,b;
scanf("%d%d",&a,&b);
printf("%d + %d = %d\n",a,b,a+b);
printf("%d - %d = %d\n",a,b,a-b);
printf("%d * %d = %d\n",a,b,a*b);
printf("%d / %d = %d\n",a,b,a/b);
return 0;
}
# 3-4 3个整数平均值
# 思路:
读入三个整数,然后输出平均值。
我们就直接(a+b+c)/3.0即可,因为我们最后要的是浮点数类型的数据。如果直接(a+b+c)/3,(a+b+c)是整型,3是整型,最后得到的计算结果还是整型的。比如明明(1+1+1)= 3,但是(1+1+1)/ 4 得到的结果是0,因为3/4对于整型数据来说,会变成0。
所以我们除以3.0,让数据变成 整型 / 浮点型,最后结果也会被转变成浮点型。
%f是默认输出6位小数,所以我们直接输出就行。
我们用double处理计算,比float的精度高【可以认为是准确度高一点】,可以避免一些无谓的错误。
# 代码C语言:
#include<stdio.h>
int main(){
int a,b,c;
double aver;
scanf("%d%d%d",&a,&b,&c);
aver=(a+b+c)/3.0;
printf("aver=%f",aver);
return 0;
}
# 3-5 输出个位数字
# 思路:
我们想要输出一个数字的个位数上的数字,有各种方法。
但是最简单的方法就是,对10进行求余。
打个比方,一个数字998244353,我们把它除以10的结果就是99824435,那余数是多少?余数就是3,也就是我们要的个位数。
所以这道题我们直接把 输入的数字 % 10 之后的数字输出就可以。
# 代码C语言:
#include<stdio.h>
int main(){
int a;
scanf("%d",&a);
printf("%d",a % 10);
return 0;
}
# 4-1 计算分段函数[1]
# 思路:
这道题目我们就分支判断x是否为0,然后正常计算就可以。
这里我们可以用float或者double来处理,都可以。 如果是float,读入用 %f ;如果是double,读入用 %lf 来处理。
下方代码以double类型为例。
# 代码C语言:
#include<stdio.h>
int main(){
double x,y;
scanf("%lf",&x);
if(x!=0){
y = 1 / x;
printf("f(%.1f) = %.1f",x,y);
}
else{
y = 0;
printf("f(%.1f) = %.1f",x,y);
}
return 0;
}
# 4-2 高速公路超速处罚
# 思路:
这道题的题目看着会有点棘手,但是只要搞明白数据怎么处理,倒也简单。
根据题目的意思就是,我们读入速度和限速,然后判断速度是否 ≥超过10%的限速 或者 ≥超过50%的限速,然后对应不同的输出。
这道题我们还要注意,如果要输出百分号的话,就这样写:%%
例如输出:60%,我们可以写成 printf("60%%");
这道题我们以float为例。
# 代码C语言:
#include<stdio.h>
int main(){
float v1,v2,p;
scanf("%f%f",&v1,&v2);
// p 存储我们超速了多少的百分比
p=(v1 - v2) / v2 * 100;
if (p>=50)
printf("Exceed %.0f%%. License Revoked",p);
else if (p>=10)
printf("Exceed %.0f%%. Ticket 200",p);
else
printf("OK");
return 0;
}
# 4-3 三天打鱼两天晒网
# 思路:
这道题就是个小计算题而已,我们直接把 天数%5 即可。
这样就当于把所有的天都分成很多个5天来看,如果余数是1、2、3说明是三天打鱼,如果余数是4、0说明是两天晒网。
# 代码C语言:
#include<stdio.h>
int main(){
int n,t;
scanf("%d",&n);
t = n % 5;
if(t == 4 || t == 0) printf("Drying in day %d",n);
else printf("Fishing in day %d",n);
return 0;
}
# 4-4 用天平找小球
# 思路:
找到唯一的不同,我们就排除法嘛,如果ab相同,则输出c,如果ac相同,则输出b,如果bc相同,则输出a。
# 代码C语言:
#include<stdio.h>
int main(){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(a == b) printf("C");
if(c == b) printf("A");
if(a == c) printf("B");
return 0;
}
# 4-5 装睡
# 思路:
这道题就是一个人一个人判断,我们判断一个就输出一个。
所以我们读入了每个人的数据之后,就进入if里判断,然后如果满足就输出即可。
# 代码C语言:
#include<stdio.h>
int main(){
char a[10];
int n,b,c,i;
scanf("%d",&n);
for (i = 0;i < n;i++){
scanf("%s%d%d",a,&b,&c);
if( b<15 || b>20 || c<50 || c>70 ){
printf("%s\n",a);
}
}
return 0;
}
# 5-1 求平方根序列前N项和
# 思路:
这道题注意使用double,否则精度可能不够。
这道题我们从1枚举到n,然后sqrt之后加到sum上就行。
# 代码C语言:
#include<stdio.h>
#include<math.h>
int main(){
double sum = 0;
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++){
sum += sqrt(1.0 * i);
}
printf("sum = %.2f",sum);
return 0;
}
# 5-2 求阶乘序列前N项和
# 思路:
这道题可以用双循环或者单循环。
双循环就是,外层用一个sum存储和,内层有个循环把单个阶乘计算一次。
单循环就是,我们观察到阶乘是有递推关系的,第二个阶乘的结果等于第一个阶乘的结果 × 2,第三个阶乘的结果等于第二个阶乘的结果 × 3……第 i 个阶乘的结果等于第 i - 1 个阶乘的结果 × i。所以我们可以用temp变量每次存储最后一个阶乘的结果,然后每个循环更新一下。
# 代码C语言 双循环版:
#include<stdio.h>
int main(){
int sum = 0;
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++){
// temp 用来存储临时数据
int temp = 1;
for(int j = 1;j <= i;j++){
temp = temp * j;
}
sum += temp;
}
printf("%d",sum);
return 0;
}
# 代码C语言 单循环版:
#include<stdio.h>
int main(){
int sum = 0;
int temp = 1;
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++){
// temp 用来存储当前阶乘算到的结果
temp *= i;
sum += temp;
}
printf("%d",sum);
return 0;
}
# 5-3 求e的近似值
# 思路:
这道题是上面这道题的变形,直接看看代码参考吧~
# 代码C语言 双循环版:
#include<stdio.h>
int main(){
double sum = 1;
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++){
// temp 用来存储临时数据
int temp = 1;
for(int j = 1;j <= i;j++){
temp = temp * j;
}
sum += 1.0 / temp;
}
printf("%.8f",sum);
return 0;
}
# 代码C语言 单循环版:
#include<stdio.h>
int main(){
double sum = 1;
int temp = 1;
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++){
// temp 用来存储当前阶乘算到的结果
temp *= i;
sum += 1.0 / temp;
}
printf("%.8f",sum);
return 0;
}
# 5-4 打印菱形图案
# 思路:
这道题的基本思路就是分析,每一行有多少个空格、多少个星号。
比如看样例,n = 7,第一行有6个空格,1个星号,第二行有4个空格,3个星号,第三行有2个空格5个星号,第四行有7个星号。
这样,上半部分我们就分析完了,空格数是从n - 1开始每次 -2,星号+空格数 = n。
下半部分的分析交给读者,其实就是反过来而已。
由此,我们便可以完成这道题。
# 代码C语言:
#include<stdio.h>
int main(){
int n;
scanf("%d",&n);
// 中位线位置
int middle = (n + 1) / 2;
// 上半部分
for(int i = 1;i <= middle;i++){
for(int j = 1;j <= n + 1 - 2 * i;j++){
printf(" ");
}
for(int j = 1;j <= 2 * i - 1;j++){
printf("* ");
}
printf("\n");
}
// 下半部分
for(int i = middle + 1;i <= n;i++){
for(int j = 1;j <= 2 * i - 1 - n;j++){
printf(" ");
}
for(int j = 1;j <= 2 * n - 2 * i + 1;j++){
printf("* ");
}
printf("\n");
}
return 0;
}
# 5-5 猴子吃桃问题
# 思路:
这道题我们倒着想。
假设第n天只剩1个,那么n - 1天不就是有2 * (1 + 1) = 4个吗?
我们根据这样的规律,可以推出,前一天的2 * (后一天 + 1),一路推到第一天即可。
这里是n到2,而不是n到1,因为如果我们推到1的时候,算出来的其实是第0天的结果,但是我们不用算到第0天。
如果循环是n - 1到1也可以,反正循环只进行n - 1次即可。
# 代码C语言:
#include<stdio.h>
int main(){
int n;
scanf("%d",&n);
int ans = 1;
for(int i = n;i >= 2;i--){
ans = 2 * (ans + 1);
}
printf("%d",ans);
return 0;
}
# 5-6 打印水仙花数
# 思路:
这道题我们就按题目的思路来即可,比如把个十百位都拆出来,然后判断是否符合。
当然你可以枚举个十百位的值,每个都是0 ~ 9(除了百位是1 ~ 9),然后看看是否符合。
当然,这道题其实可以偷懒,直接输出样例即可。
# 代码C语言 思路一:
#include<stdio.h>
int main(){
for(int i = 100;i <= 999;i++){
int ge = i % 10;
int shi = (i % 100 - ge) / 10;
int bai = i / 100;
if(i == ge*ge*ge + shi*shi*shi + bai*bai*bai){
printf("%5d",i);
}
}
return 0;
}
# 代码C语言 思路二:
#include<stdio.h>
int main(){
for(int i = 1;i <= 9;i++){
for(int j = 0;j <= 9;j++){
for(int k = 0;k <= 9;k++){
if(i * 100 + j * 10 + k == i*i*i + j*j*j + k*k*k){
printf("%5d",i * 100 + j * 10 + k);
}
}
}
}
return 0;
}
# 代码C语言 偷懒版:
#include<stdio.h>
int main(){
printf(" 153 370 371 407");
return 0;
}
# 5-7 求整数的位数及各位数字之和
# 思路:
这道题的思路蛮重要的,注意学习。
我们怎么统计一个数字有几位?
思路一:我们每次除以10便可以拿出一位数字,这样我们就可以每次都拿到一个数字进行处理,直到数字n变为0.
思路二:我们可以把数字看作是一个字符串1234,我们把这个字符串逐位进行处理,便可以得到结果。
注意!如果是字符串的处理,我们要用string.h头文件里的函数哦~
# 代码C语言 思路一:
#include<stdio.h>
int main(){
int n;
scanf("%d",&n);
int sum = 0;
// cnt 记录数字位数
int cnt = 0;
while(n){
sum += n % 10;
n /= 10;
cnt++;
}
printf("%d %d",cnt,sum);
return 0;
}
# 代码C语言 思路二:
#include<stdio.h>
#include<string.h>
int main(){
char str[100];
scanf("%s",str);
int sum = 0;
// strlen 可以得到字符串长度
int len = strlen(str);
// 字符串从下标0的位置开始存储
for(int i = 0;i < len;i++){
sum += str[i] - '0';
}
printf("%d %d",len,sum);
return 0;
}
# 5-8 逆序输出数的各位数字
# 思路:
这道题我们也是两个思路,和上一道题差不多,读者自行领悟~
# 代码C语言 思路一:
#include<stdio.h>
int main(){
int n;
scanf("%d",&n);
while(n){
printf("%d",n % 10);
n /= 10;
}
return 0;
}
# 代码C语言 思路二:
#include<stdio.h>
#include<string.h>
int main(){
char str[100];
scanf("%s",str);
// strlen 可以得到字符串长度
int len = strlen(str);
// 字符串的下标从0到len - 1
for(int i = len - 1;i >= 0;i--){
printf("%c",str[i]);
}
return 0;
}
# 5-9 小于m的最大的10个素数
# 思路:
判断素数的办法很重要!
我们判断素数的办法就是,让当前数字与比其小的数字(比其根号还小)的数字做比,看看能不能整除,如果整除说明这个数字有因数,就不是素数,反之就是素数。
我们在2~m之间的数字逆序查找即可。
详细请看代码学习!
# 代码C语言:
#include<stdio.h>
#include<math.h>
int main(){
int m;
scanf("%d",&m);
// cnt 记录我们输出的素数的数量
int cnt = 0;
for(int i = m - 1;i >= 2;i--){
// 此时i就是我们要判断的数字
// 我们开始判断是不是素数
// 我们可以用一个变量来存储我们的判断,我们默认这个数字是素数,即flag = 1
int flag = 1;
for(int j = 2;j <= sqrt(i);j++){
// 如果能被整除
if(i % j == 0){
// 说明这一定不是素数,我们不管
flag = 0;
}
}
// flag = 1即为素数的情况,这里可以简写成if(flag)
if(flag == 1){
cnt++;
printf("%6d",i);
}
if(cnt >= 10) break;
}
}