前言
注明:本篇文章非原创部分,均已指明出处
该博仅为卑微大学牲程序设计基础期末备考,主要参考PTA习题集、中国大学MOOC、B站以及CSDN文章。若有冒犯,敬请批评指正,不胜感激!
提示:以下是本篇文章正文内容,案例仅供参考
一、一些基础概念
注明:就遇到的问题总结,后续将持续补充
(一)、循环结构
请看VCR➡️三种循环语句的详解和使用
(二)、函数
1、strlen函数
计算的是字符串str的长度,从字符的首地址开始遍历,以 ‘\0’ 为结束标志,然后将计算的长度返回,计算的长度并不包含’\0’。
注意: 当计算长度时,只有遇到’\0’才会停止计算,同时计算的长度不包含’\0’。使用时,应该检查字符数组是否以’\0’为结束标志。
(三)、指针
呃……难评。
二、PTA题目集中存在疑惑的实验
1、IP地址转换
将32位二进制码表示的IP地址转换为十进制格式表示的IP地址输出
#include <stdio.h>
#include<string.h>
#include <math.h>
int main()
{
char s[40];
gets(s);
for(int i=0;i<4;i++)
{
int j=0;
for(int q=0;q<8;q++)
{
j+=(s[i*8+q]-'0')*pow(2,8-q-1);
}
if(i==0) printf("%d",j);
else printf(".%d",j);
}
return 0;
}
原理:由于IP地址由4个8位字段组成,每个字段的取值范围是0-255。每个字段都可以看作是256进制表示的一个数字。所以,
IP地址 = 第1个字段 * 256^3 + 第2个字段 * 256^2 + 第3个字段 * 256^1 + 第4个字段 * 256^0。
因为IP地址由4段构成,所以要遍历四次(i从3开始),将遍历的次数标识看成指数,通过以上公式,通过math.pow(256, i),得出每个字段所对应的权重。
(例:第一个字段对应的权重是 :256^3)
2、汉诺塔问题
#include <stdio.h>
void hanoi(int n, char one, char two, char three );
int main() {
int m;
scanf("%d", &m);
getchar();
char a, b, c;
scanf("%c %c %c", &a, &c, &b);
hanoi(m, a, b, c);
}
void hanoi(int n, char one, char two, char three) {
if (n == 1)
printf("1: %c -> %c\n", one, three);
else {
hanoi(n - 1, one, three, two);
printf("%d: %c -> %c\n", n, one, three);
hanoi(n - 1, two, one, three);
}
}
3、打印月历
#include <stdio.h>
int main()
{
int year,month;
scanf("%d %d",&year,&month);
int n=0;
for(int y=1;y<year;y++)
{
int leap=y%100!=0&&y%4==0||y%400==0;
n+=leap?366:365;
}
int month_days[]={0,31,28,31,30,31,30,31,31,30,31,30,31,};
for(int m=1;m<month;m++)
n+=month_days[m];
int leap_year=year%100!=0&&year%4==0||year%400==0;
if(month>2&&leap_year)
n++;
n++;
int weekday_1st=n%7;
int days_of_month=month_days[month];
if(month==2&&leap_year)
days_of_month=29;
printf("Sun Mon Tue Wed Thu Fri Sat\n");
for(int i=0;i<weekday_1st;i++)
printf(" ");
for(int d=1;d<=days_of_month;d++)
{
printf("%3d",d);
if((d+weekday_1st)%7==0)
printf("\n");
else if(d<days_of_month)
printf(" ");
}
if((days_of_month+weekday_1st)%7!=0)
printf("\n");
return 0;
}
只是觉得这道题因吹斯汀!
4、字符串的连接
使用指针方式实现两个字符串的连接(不能使用strcat函数)
#include <stdio.h>
int fun(char *str1,char *str2)
{
while(*str1)//指向元素为空时跳出循环,即str1指向数组str1的末尾后一位
{
str1++;//指针自增,指向下一个元素,指导数组末最后一位
}
while(*str2)
{
*str1=*str2;//str2数组的最后一后赋于str1数组末尾后一位的空位
str1++;//指针后移
str2++;
}
*str1='\0';//puts遇到'\0'才会停止打印
}
int main()
{
int fun(char *str1,char *str2);
char str1[80],str2[80];
gets(str1);
gets(str2);
fun(str1,str2);
puts(str1);
}
5、实数排序
#include<stdio.h>
#include<stdlib.h>
double order(double *p, int n,double *k);
int main()
{
double a[10],b[10];
int n,i;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%lf", &a[i]);
}
order(a,n,b);
for(i=0;i<n;i++)
{
if(i==n-1)
{
printf("%.2lf", b[n-1]);
}
else
{
printf("%.2lf ",b[i]);
}
}
printf("\n");
return 0;
}
double order(double *p,int n,double *k)
{
int m=0;
int i,t;
for (i=0;i<n;i++)
{
for (t=0;t<n;t++)
{
if(*(p+i)<*(p+t))
{
m++;
}
}
*(k+m)=*(p+i);
m=0;
}
}
其实我悟了。
6、使用函数实现字符串复制
将字符串 t 中从第 m 个字符开始的全部字符复制到字符串 s 再输出
#include<stdio.h>
#include<string.h>
void strmcpy(char *s, char *t, int m)
{
int i, j;
j = 0;
for (i = m - 1; t[i] != '\0'; i++)
{
s[j++] = t[i];
}
s[j] = '\0';
}
void main()
{
void strmcpy(char* s, char* t, int m);
char s[10], t[10];
int m, repeat, n;
scanf("%d", &repeat);
getchar();
for (n = 0; n < repeat; n++)
{
gets(t);
scanf("%d", &m);
getchar();
if (strlen(t) < m)
{
printf("error input");
}
else
{
strmcpy(s, t, m);
puts(s);
}
}
}
7、猴子选大王
#include <stdio.h>
int main()
{
int n,a[1000];
int cnt,i,j,k;
scanf("%d",&n);
for(i=0;i<=n;i++)
{
a[i]=i;
}
cnt=1;
i=0;
j=1;
while(a[i]==0)
{
i++;
if(i>n)
{
i=0;
}
}
while(cnt<n)
{
if(j==3)
{
a[i]=0;
cnt++;
}
j++;
if(j>3)
{
j=1;
}
i++;
if(i>n)
{
i=0;
}
while(a[i]==0)
{
i++;
if(i>n)
{
i=0;
}
}
}
for(k=0;k<=n;k++)
{
if(a[k])
{
printf("%d",a[k]);
}
}
return 0;
}
8、出租
引用:能力有限,该题直接搬运
感谢chenmoan大大
#include<stdio.h>
#include<string.h>
int main()
{
int phone[11];
int a[10],b[10];
int i,j=0,k=0;
memset(a,-1,sizeof(a));
memset(b,-1,sizeof(b));
char s[11];
scanf("%s",s);
for(i=0;i<11;i++)
{
phone[i]=s[i]-'0';
a[phone[i]]++;
}
printf("int[] arr = new int[]{");
for(i=9;i>=0;i--)
{
if(a[i]>=0)
{
b[j++]=i;
k++;
}
}
for(i=0;i<k;i++)
{
printf("%d",b[i]);
if(i<k-1) printf(",");
}
printf("};\nint[] index = new int[]{");
for(j=0;j<11;j++)
{
for(i=0;i<10;i++)
{
if(phone[j]==b[i])
{
printf("%d",i);
break;
}
}
if(j<10) printf(",");
else printf("};");
}
return 0;
}
9、统计大写字母
输入一串字符,统计其中大写字母A-Z各出现多少次
无厘头,救救孩子吧!
10、检查密码
引用:纯属摆烂,该题参考
[感谢薛定谔的糖c大大]
写一个密码合法性检查的小功能
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int n,i,j,l,s,x,z,flag;
scanf("%d",&n);
getchar();
for(i=0;i<n;i++){
char aw[100];
flag=0;
s=0;
x=0;
z=0;
gets(aw);
l=strlen(aw);
if(l<6){
printf("Your password is tai duan le.\n");
}
else{
for(j=0;j<l;j++){
if(aw[j]>=65&&aw[j]<=90||aw[j]>=97&&aw[j]<=122||aw[j]>=48&&aw[j]<=57||aw[j]==46){
if(aw[j]==46) x++;
if(aw[j]>=48&&aw[j]<=57) s++;
if(aw[j]>=65&&aw[j]<=90||aw[j]>=97&&aw[j]<=122) z++;
continue;
}
else{
flag=1;
printf("Your password is tai luan le.\n");
break;
}
}
if(flag==0){
if(s+x==l) printf("Your password needs zi mu.\n");
else if(z+x==l) printf("Your password needs shu zi.\n");
else printf("Your password is wan mei.\n");
}
}
}
return 0;
}
三、传说中的重点考点
1、水仙花数
判断一个三位数是否为水仙花数
选择结构
#include <stdio.h>
int main()
{
int N;
scanf("%d",&N);
int a,b,c;
a=N/100;
b=(N%100)/10;
c=N%10;
if(N>=100&&N<=999)
{
if(N==a*a*a+b*b*b+c*c*c)
{
printf("Yes");
}
else
{
printf("No");
}
}
else
{
printf("Invalid Value.");
}
return 0;
}
按递增顺序输出所有N位水仙花数,每个数字占一行
循环结构
#include <stdio.h>
int pow(int x, int n) {
int sum = 1;
for ( int i = 0; i < n; i++ ) {
sum *= x;
}
return sum;
}
int main() {
int n, sum;
scanf("%d", &n);
int max = pow(10, n), min = pow(10, n - 1);
while ((min++) < max) {
sum = 0;
for (int j = min; j != 0; j *= 0.1)
sum += pow((j % 10), n);
if (sum == min)
printf("%d\n", min);
}
return 0;
}
2、素数
注:非有效代码,只可意会不可言传
暴力法
遍历的所有大于 1 且小于 n 的整数,判断 n 是否可以被这些数整除,如果不存在可以整除的数,则为素数;否则为合数。
for (int i = 2; i < n; ++i)
{
if (n % i == 0)
{
return 0;
}
}
return 1;
试除法
遍历从 1 到 √n 的所有整数。如果 n 有一个大于 √n 的约数 d,那么必定存在一个小于或等于 √n 的约数 n/d。
for (int i = 2; i <= n / i; ++i)
{
if (n % i == 0)
{
return 0;
}
}
return 1;
以i=n/i形式开方,可以提高运行速度。
埃氏筛
基本思路:给定要筛数值的范围 n ,从2开始,将每个素数的倍数标记成合数。如果一个数没有被之前的数标记,那它一定是素数。
欧拉筛
沿用埃氏筛的思路,但不再只筛除素数的倍数,合数的倍数也会进行标记。
bushi ~ 这两种方法品品就得了。
统计素数并求和
循环结构
#include <stdio.h>
int main()
{
int count=0,sum=0;
int M,i,N;
scanf("%d %d",&M,&N);
for(M;M<=N;M++)
{
for(i=2;i<M;i++)
{
if(M%i==0)
break;
}
if(M!=1&&i==M)
{
count++,sum=sum+M;
}
}
printf("%d %d",count,sum);
return 0;
}
判断一个给定的正整数是否素数
函数
#include <stdio.h>
#include <math.h>
int A(int n)
{
int j;
int judge=1;
if(n==1) judge=0;
else{
for(j=2;j<=sqrt(n);j++){
if(n%j==0){
judge=0;
break;
}
}
}
return judge;
}
int main()
{
int N,n;
scanf("%d",&N);
for(int i=0;i<N;i++)
{
scanf("%d",&n);
if(A(n))
{
printf("Yes\n");
}
else
{
printf("No\n");
}
}
return 0;
}
3、斐波那契数列
兔子繁衍问题
循环结构
#include <stdio.h>
int f(int n) {
if (n == 1 || n == 2)
return 1;
else
return f(n - 1) + f(n - 2);
}
int main() {
int n, month;
scanf("%d", &n);
for (month = 1; f(month) < n; month++);
printf("%d", month);
return 0;
}
计算斐波那契数列第n项的值
函数
#include <stdio.h>
double fun(int n)
{
double a[61];
int i;
a[1]=1;a[2]=1;
for(i=3;i<=n;i++)
a[i]=a[i-1]+a[i-2];
return a[n];
}
int main()
{
int n;
scanf("%d",&n);
printf("%.0f\n",fun(n));
return 0;
}
4、最大公约数和最小公倍数
求两个给定正整数的最大公约数和最小公倍数
循环结构
#include <stdio.h>
int main()
{
int M,N,Max,Min;
int a,b,c;
scanf("%d %d",&M,&N);
a=M;
b=N;
while(c=M%N,c!=0)
{
M=N;
N=c;
}
printf("%d %d",Max=N,Min=a/N*b);
return 0;
}
四、去年考题编程部分
保命!:以下题解为白痴思考模式,代码纯纯人工手打,不可参考
1、统计单词数量
#include <stdio.h>
#include <ctype.h>
int main()
{
char ch;
int flag=1;
int cnt=0;
while((ch=getchar())&&ch!='\n')
{
if((isalpha(ch))&&flag)
{
flag=0;
cnt++;
}
else if(!(isalpha(ch)))
{
flag=1;
}
}
printf("%d",cnt);
}
isalpha字母判断函数
头文件:ctype.h
功能:判断字符是否是字母类的(alphabetic),包括:a(ASCII值:97)-z(122) 和 A(65)-Z(90) 。
不是字母类的,返回值0;是字母类的,返回非0值。
2、输入正整数m,判断m是否是素数
注意: 1不是素数,记得单独讨论。
3、水仙花数求和
#include <stdio.h>
int main()
{
int N;
int a,b,c;
int i,sum;
scanf("%d",&N);
for(i=100,i<100;i++)
{
a=i%10;
b=i/10%10;
c=i/100;
if(a*a*a+b*b*b+c*c*c==i)
{
sum+=i;
}
}
printf("%d",sum);
return 0;
}
其实这道题也可以只在脑子里过一遍滴~
4、排序
关于冒泡排序和选择排序
方法一:选择排序
#include <stdio.h>
int main()
{
int N;
int i,j,t;
int a[100];
scanf("%d",&N);
for(i=0;i<N;i++)
{
scanf("%d",&a[i]);
}
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
if(a[i]>a[j])
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
}
for(i=0;i<N-1;i++)
{
printf("%d",a[i]);
}
printf("%d\n",a[N-1]);
return 0;
}
方法二:冒泡排序
#include <stdio.h>
#include <stdlib.h>
int main()
{
int N;
int i,j,t;
int a[100];
scanf("%d",&N);
for(i=0;i<N;i++)
{
scanf("%d",&a[i]);
}
for(i=1;i<N;i++)
{
for(j=0;j<=N-i-1;j++)
{
if(a[j]>a[j+1])
{
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}
for(i=0;i<N-1;i++)
{
printf("%d",a[i]);
}
printf("%d\n",a[N-1]);
return 0;
}
5、逆序整数
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
int main()
{
int n,i;
char a[200]={0},b[200]={0};
scanf("%d\n",&n);
scanf("%s\n%s\n"),&a,&b);
bool flag=true;
for(i=0;i<n;i++)
{
if(a[i]!=b[n-1-i])
{
flag=false;
break;
}
}
if(flag)
{
printf("%s and %s are reverse."a,b);
}
else
{
printf("%s and %s are not reverse."a,b);
}
return 0;
6、求圆的周长和面积
so easy!妈妈再也不用担心我的学习了!
所有题都按这个标准来,OK?
7、字符统计
#include <stdio.h>
int main()
{
int cnt[255]={0};
char str[500];
int i;
gets(str);
for(i=0;str[i]!='\0';++i)
cnt[str[i]]++;
for(i=0;i<255;i++)
if(cnt[i]!=0)
printf("%c:%d\n",i,cnt[i]);
return 0;
}
8、两数之差的绝对值
#include <stdio.h>
int main()
{
int T,i;
int a[100],b[100],c[100];
scanf("%d",&T);
for(i=0;i<T;i++)
{
scanf("%d %d",&a[i],&b[i]);
}
for(i=0;i<T;i++)
{
if(a[i]>=b[i])
{
c[i]=(a[i]-b[i]);
}
else
{
c[i]=(b[i]=a[i]);
}
printf("%d\n",c[i]);
}
return 0;
}
9、统计各个数据个数
EOF在C标准函数库中表示文件结束符(end of file)。在while循环中以EOF作为文件结束标志。
当上面的程序运行时,如果不加" != EOF",那么这个程序就是个死循环,会一直运行下去;加上" != EOF"后该程序就不是死循环了,如果在终端不进行输入该程序会自动结束(while的意思就是说当当前输入缓存还有东西时就一直读取,直到输入缓存中的内容为空时停止)。
10、统计单词
#include <stdio.h>
#include <string.h>
int main()
{
char a[10000];
gets(a);
int i,word;
int len=strlen(a);
for(i=1;i<len;i++)
{
if(a[i]==' '&&a[i-1]!=' ')
{
word++;
}
}
if(a[len-1]!=' ')
{
word++;
}
printf("%d",word);
return 0;
}
11、统计字符个数
#include <stdio.h>
int main()
{
char c;
int letter,space,digit,other;
while((c=getchar())!='\n')
{
if((c>='a'&&c<='z')||c>='A'&&c<='Z')
{
letter++;
}
else if(c==' ')
{
space++;
}
else if(c>='0'&&c<='9')
{
digit++;
}
else
{
other++;
}
}
printf("letter=%d\nspace=%d\ndigit=%d\nother=%d\n",letter,space,digit,other);
return 0;
}
12、排序
13、字符串比较
别问,我也不知道14题离家出走到哪里了。
15、两数的排序
#include <stdio.h>
void Sort(int *x,int *y);
{
int temp;
if(*x>*y)
{
temp=*x;
*x=*y;
*y=temp;
}
printf("After sort:%d %d",*x,*y);
}
void Sort(int *pa,int *pb);
int main()
{
int a,b;
scanf("%d %d",&a,&b);
Sort(&a,&b);
return 0;
}
16、无符号整数的内部结构
#include <stdio.h>
int main()
{
unsinged int v;
scanf("%u",&v);
printf("%x\n",v);
unsinged char *p=(unsinged char*)&v;
for(int i=0;i<4;i++)
{
printf("%x",p[i]);
if(i!=3)
{
printf(" ");
}
}
return 0;
}
unsinged表示无符号数,当定义一个数值型字段中添加该约束,表示该字段的数据没有符号,可以变相增加长度。
17、输出不重复的数组元素
#include <stdio.h>
int main()
{
int n,a[20];
int i,j;
for(i=0;i<n;&a[i])
{
scanf("%d",&a[i]);
}
if(n>=1)
{
printf("%d",a[0]);
}
for(i=1;i<n;i++)
{
for(j=0;j<i;j++)
{
if(a[i]==a[j])
{
break;
}
}
if(j==i)//双重遍历只输出下标相同的
{
printf(" %d",a[i]);
}
}
return 0;
}
18、求出1到n之间所有奇数的阶乘值
#include <stdio.h>
int main()
{
int n;
int i = 0,j = 1;
scanf("%d",&n);
for (i = 1; i <= n;i++)
{
int k = 1;
if (i % 2 != 0)
{
for (j = 1; j <= i; j++)
{
k = k * j;
}
printf("%d! = %d\n", i, k);
}
}
return 0;
}
19、求长方体的体积
#include <stdio.h>
double V(double l,double w,double h)
{
double V;
V=l*w*h;
return V;
}
void main( )
{
double l,w,h;
double V;
scanf("%f %f %f",&l,&w,&h);
printf("%.2lf",V(l,w,h));
return 0;
}
20、求1!+2!+……+ n!
仅简单计算阶乘和
#include<stdio.h>
int main()
{
int N,S=0,T=1;
scanf("%d",&N);
for(int i=1;i<=N;i++)
{
T*=i;
S+=T;
}
printf("%d",S);
return 0;
}
#include <stdio.h>
long fact(int n)
{
if(n<0)
return 0;
else if(n==0||n==1)
return 1;
else
return n*fact(n-1);
}
int main(void)
{
int i, n;
double sum;
scanf("%d", &n);
sum = 0;
for(i = 1; i <= n; i++){
sum = sum + fact(i);
}
printf("%.0f\n", sum);
return 0;
}
21、斐波那契数列
#include <stdio.h>
int fib(int n)
{
if (n == 1 || n == 2)
return 1;
if (n >= 3)
return fib(n - 1) + fib(n - 2);
}
int main(void)
{
int n;
scanf("%d",&n);
printf("%d",fib(n));
return 0;
}
总结
在此特别感谢LRT大美女!姐,你,是我唯一的神!
虽然review和preview只有个p的区别,但是真正的大学牲敢于直面崭新的课本,加油鸭!