江苏大学考研885程序设计 - 编程题笔记

it2024-08-16  38

江苏大学考研专业课编程题

这个暂时还不能完全放出来!万一被对手看到了怎么办! --2020.10.3 √文件操作模板字符串操作√编程题【迭代法】迭代法求 x = a x=\sqrt{a} x=a 牛顿切线公式计算 a 的立方根迭代法求方程的根求自然对数的底e求 PI 的近似值 √编程题【递归】勒让德多项式切比雪夫多项式递归求 x^n组合数 C~n~^k^斐波那契数列Hermite 多项式 编程题【简单算法】√降序数√计算数学表达式√亲密数对双胞胎数模拟双目运算符求车牌号*一元二次方程求解小球自由落体**蛇形数组正整数水仙花数学生成绩*矩阵的鞍点大小写字符转换完数字符串统计整数求和公式模拟选举*打印图案ASCII 排序(选择、冒泡)√判断素数与分解行最小与列最小矩阵翻转扑克牌 编程题 - 结构体*统计学生成绩*计算天数学生成绩管理

江苏大学考研885程序设计 - 填空选择知识点

这个暂时还不能完全放出来!万一被对手看到了怎么办! --2020.10.3

√文件操作模板

读取文件1内容写到文件2(字符串):fgetc(fp1)

hello world! #include<stdio.h> int main() { FILE *fp1, *fp2; // fp1读取文件,fp2写入文件 // 打开文件,出错则提示 if ((fp1 = fopen("hello.txt", "r")) == NULL) { printf("cannot open file\n"); return 0; } if ((fp2 = fopen("result.txt", "a")) == NULL) { printf("cannot open file\n"); return 0; } char ch[100]; int i = 0; while ((ch[i++] = fgetc(fp1)) != EOF) { fprintf(fp2, "%c", ch[i-1]); // 文件1内容写到文件2 } // 关闭文件,出错则提示 if (fclose(fp1) != 0) printf("file close error\n"); if (fclose(fp2) != 0) printf("file close error\n"); return 0; }

读取文件内容(数字):fscanf(fp, "%d %d %d", &a, &b, &c);

5 25 3 0 2 6 0 0 0 1 1 8 #include<stdio.h> int main() { FILE *fp; if ((fp = fopen("Coefficient.txt", "r")) == NULL) { printf("cannot open Cofficient.txt\n"); return 0; } int a, b, c; int i = 0; while (fscanf(fp, "%d %d %d", &a, &b, &c) != EOF) { i++; printf("i=%d, a=%d, b=%d, c=%d\n", i, a, b, c); } if (fclose(fp) != 0) printf("close Cofficient.txt error"); return 0; }

字符串操作

scanf() :可以输入多种类型的数据。

getchar():用于输入单个字符;puchar(c):用于输出单个字符。

char a = getchar(); putchar(a); putchar('\n');

gets():获取一行数据,并作为字符串处理。

注:gets() 能读取含有空格的字符串,而 scanf() 不能

char str[30]; char *string = str; //一定要先将指针变量初始化 gets(string); //也可以写成gets(str); printf("%s\n", string); //输出参数是已经定义好的“指针变量名” return 0;

遍历字符串3种方法:

#include <stdio.h> #include <string.h> #define MAX_SIZE 1024 int main() { char src[MAX_SIZE] = {0}; printf("Please input string : "); gets(src); // for循环字符数组 int len = strlen(src); for (int i = 0; i < len; i++) { printf("%c",src[i]); } printf("\n"); // while循环字符数组 int i = 0; while (src[i] != '\0') { printf("%c", src[i]); i++; } printf("\n"); // while循环字符指针 char *p = src; while(*p != '\0') { printf("%c", *p); p++; } printf("\n"); return 0; }

字符转数字:'9' - '0' = 9,单个数字字符 - ‘0’,即变成数字类型;

#include <stdio.h> #define MAX_SIZE 1024 int my_atoi(char *str) { int result = 0, flag = 1; // 处理负号 if (*str == '-') { flag = -1; str++; } while (*str != '\0') { if (*str >= '0' && *str <= '9') result = result * 10 + (*str - '0'); else break; str++; } return result * flag; } int main() { char str[MAX_SIZE] = {0}; int result; printf("Please input string : "); gets(str); result = my_atoi(str); printf("result = %d\n", result); return 0; }

√编程题【迭代法】

迭代法求 x = a x=\sqrt{a} x=a

题目: 用迭代法求 x = a x=\sqrt{a} x=a 求平方根的迭代公式为: x n + 1 = 1 2 ( x n + a x n ) x_{n+1}=\frac{1}{2}\left(x_n+\frac{a}{x_n}\right) xn+1=21(xn+xna) 要求前后两次求出的 x 的差的绝对值小于 1 0 − 5 10^{-5} 105

下面给出 使用 do{} while 和 不使用的 两种代码:

#include<stdio.h> #include<math.h> int main() { float a, x0, x1 = 1; printf("enter a number:"); scanf("%f", &a); do { x0 = x1; x1 = (x0 + a / x0) / 2; } while (fabs(x1 - x0) >= 1e-5); printf("The square root of %f is %f\n", a, x1); return 0; } #include<stdio.h> #include<math.h> int main() { float a, x0, x1; printf("Please enter number a:"); scanf("%f", &a); x0 = a / 2; // 初始化, 非0常数 x1 = (x0 + a / x0) / 2; while(fabs(x1 - x0) >= 1e-5) { x0 = x1; x1 = (x0 + a / x0) / 2; } printf("The square root of %f is %f\n", a, x1); return 0; } Please enter number a:5 The square root of 5.000000 is 2.236068

关于初值的解释:用牛顿迭代法解方程,理论上初值可以是任意值。但是如果初值选得好,收敛得就快。当然程序所需要的内存更低,费时更少了。

牛顿切线公式计算 a 的立方根

利用牛顿切线公式计算数 a(不为0)的立方根。根据牛顿公式,其第 n+1 次近似根与第 n 次近似根满足: x n + 1 = ( 2 x n 3 + a ) / ( 3 x n 2 ) x_{n+1} = (2x^3_n + a) / (3x_n^2) xn+1=(2xn3+a)/(3xn2)。要求相邻两次近似根的差的绝对值小于等于 1 0 − 6 10^{-6} 106 时停止。初次迭代近似值 x 0 x_0 x0 取值为 1。

#include<stdio.h> #include<math.h> #define EPS 1e-6 // 迭代精度为10^-6 int main() { double x1=1, x0, a; // 初次迭代近似值取1 printf("请输入要开方的数:"); scanf("%lf", &a); do{ x0 = x1; x1 = (2*pow(x0,3) + a) / (3*pow(x0,2)); // x1 = 2 * x0 / 3 + a / (3 * x0 * x0); // 拆分优化 } while (fabs(x1 - x0) >= EPS); printf("%lf 的立方根近似为 %7.5lf\n", a, x1); return 0; }

迭代法求方程的根

解非线性方程 f ( x ) = 0 f(x) = 0 f(x)=0 的牛顿迭代公式是: x n + 1 = x n − f ( x n ) f ′ ( x n ) x_{n+1} = x_n - \frac {f(x_n)} {f'(x_n)} xn+1=xnf(xn)f(xn) 其中, f ′ ( x n ) f'(x_n) f(xn) f ( x ) f(x) f(x) 的导数。编写程序,用该方法求方程 f ( x ) = x 41 + x 3 + 1 = 0 f(x) = x^{41} + x ^3 + 1 = 0 f(x)=x41+x3+1=0 在 x0 = -1 附近的近似根。要求相邻两次近似根的差的绝对值小于 10-6 时停止。

#include<stdio.h> #include<math.h> int main() { double f, f1, x0, x1 = -1; do { x0 = x1; f = pow(x0, 41) + pow(x0, 3) + 1; f1 = 41 * pow(x0, 40) + 3 * pow(x0, 2) + 1; x1 = x0 - f / f1; } while (fabs(x0 - x1) >= 1e-6); printf("近似根为:%lf", x1); return 0; }

求自然对数的底e

对于一个充分大的正整数 n,自然对数的底 e 可以由 ( 1 + 1 n ) n (1 + \frac 1 n) ^n (1+n1)n 公式近似求出。即: e ≈ ( 1 + 1 n ) n ( n 为 充 分 大 的 正 整 数 ) e \approx (1 + \frac 1 n)^n (n为充分大的正整数) e(1+n1)n(n) 编程序计算 n 从 1 开始连续变化所对应的 e 值,直到相邻零次 e 值之差的绝对值小于 10-6 为止。要求打印出最后的 e 值和对应的 n。

#include<stdio.h> #include<math.h> int main() { double e0, e1 = 2.7; // e1=2会出问题 int n = 1; do { e0 = e1; e1 = pow(1 + 1.0/n, n); n++; } while(fabs(e0 - e1) >= 1e-6); printf("result: e = %lf, n = %d", e1, n); return 0; }

求 PI 的近似值

利用数学公式求 π \pi π 的近似值。公式是: π 4 ≈ 1 − 1 3 + 1 5 − 1 7 + . . . \frac \pi 4 \approx 1 - \frac 1 3 + \frac 1 5 - \frac 1 7 + ... 4π131+5171+... 直到最后一项的绝对值小于等于 10-6 为止。

for循环 写法:

#include<stdio.h> #include<math.h> int main() { double flag = 1.0; // 控制+1或-1 double sum = 0.0; for (int i = 1; ; i+=2) { sum += flag / i; flag = (flag == 1.0 ? -1.0 : 1.0); if (fabs(1.0 / i) <= 1e-6) break; } printf("pi = %10.8lf", 4*sum); return 0; }

while循环写法:

#include<stdio.h> #include<math.h> int main() { int i = 1; double flag = 1.0; // 控制+1.0或-1.0 double sum = 0.0; while(1) { sum += flag / i; flag = (flag == 1.0 ? -1.0 : 1.0); if (fabs(1.0 / i) <= 1e-6) break; i += 2; }; printf("pi = %10.8lf", 4*sum); return 0; }

√编程题【递归】

勒让德多项式

P n ( x ) = { 1 n = 0 x n = 1 ( ( 2 n − 1 ) x P n − 1 ( x ) − ( n − 1 ) P n − 2 ( x ) ) / n n > 1 P_n(x) = \left\{\begin{matrix} &1 & n=0 \\ & x & n=1 \\ & ((2n-1)xP_{n-1}(x)-(n-1)P_{n-2}(x))/n & n > 1 \end{matrix}\right. Pn(x)=1x((2n1)xPn1(x)(n1)Pn2(x))/nn=0n=1n>1

#include<stdio.h> double p(int n, double x) { if (n == 0) return 1; else if (n == 1) return x; else if (n > 1) return ((2 * n - 1) * x * p(n - 1, x) - (n - 1) * p(n - 2, x)) / n; return 0; } int main() { int n; double x; printf("请输入整数 n, 实数 x:\n"); scanf("%d %lf", &n, &x); printf("计算结果是: %lf:\n", p(n, x)); return 0; }

切比雪夫多项式

已知:切比雪夫多项式如下: T n ( x ) = { 1 ( n = 0 ) x ( n = 1 ) 2 x T n − 1 ( x ) − T n − 2 ( x ) ( n ⩾ 2 ) T_n(x) = \left\{\begin{matrix} & 1 & (n=0) \\ & x & (n=1) \\ & 2xT_{n-1}(x) - T_{n-2}(x) & (n\geqslant 2)\end{matrix}\right. Tn(x)=1x2xTn1(x)Tn2(x)(n=0)(n=1)(n2) 编写一程序,输入 n,x,并将 0~n u的所有 Tn(x) 的值输出到文件 tdat.txt 中。

#include<stdio.h> double T(int n, double x) { if (n==0) return 1; else if(n==1) return x; else return 2*x*T(n-1, x) - T(n-2, x); } int main() { FILE *fp; if ((fp = fopen("tdat.txt", "w+")) == NULL) { printf("cannot open file\n"); return 0; } int n; double x; printf("请输入 n, x 的值: "); scanf("%d %lf", &n, &x); for(int i = 0; i <= n; i++) { printf("%d %lf\n", i, T(i,x)); fprintf(fp, "%d %lf\n", i, T(i, x)); } if (fclose(fp) != 0) printf("close file error"); return 0; }

递归求 x^n

设计一个递归函数, 求 x 的 n 次幂; 主函数通过键盘输入 x 和 n 的值,并输出 x^n 的值。(假设 x 为实数, n 为 正整数)

#include<stdio.h> double xn(double x, int n) { if (n == 0) return 1; if (n == 1) return x; return x * xn(x, n-1); } int main() { double x; int n; printf("请输入 x 和 n 的值:"); scanf("%lf %d", &x, &n); printf("x^n = %lf", xn(x, n)); }

组合数 Cnk

已知组合数的递归定义如下所示,编写递归程序求 Cnk 的值(n,k 由键盘输入)。

#include<stdio.h> int cnk(int n, int k) { if (n == k || k == 0) return 1; else if (0 < k && k < n) { return cnk(n - 1, k - 1) + cnk(n - 1, k); } else { printf("error\n"); return -1; } } int main() { int n, k; printf("please input n, k: "); scanf("%d %d", &n, &k); printf("result = %d", cnk(n, k)); return 0; }

斐波那契数列

用递归计算斐波那契数列第 n 项,该数列可以表示成: f ( n ) = { 1 n = 1 1 n = 2 f ( n − 1 ) + f ( n − 2 ) n > 2 f(n) = \left\{\begin{matrix} & 1 & n = 1 \\ & 1 & n = 2 \\ &f(n-1)+f(n-2) & n > 2\end{matrix}\right. f(n)=11f(n1)+f(n2)n=1n=2n>2

#include<stdio.h> // 斐波那契数列 int fib(int n) { if (n == 1) return 1; if (n == 2) return 2; return fib(n - 1) + fib(n - 2); } int main() { FILE *fp; if ((fp = fopen("fab.txt", "w")) == NULL) { printf("cannot open file\n"); return 0; } int sum = 0; for (int i = 1; i <= 20; i++) { sum += fib(i); printf("%d\n", fib(i)); } printf("sum(1,20) = %d", sum); fprintf(fp, "%d", sum); if (fclose(fp) != 0) printf("close file error"); return 0; }

Hermite 多项式

H n ( x ) = { 1 n = 0 2 x n = 1 2 x H n − 1 ( x ) − 2 ( n − 1 ) H n − 2 ( x ) n > 1 H_n(x) = \left\{\begin{matrix} & 1 & n = 0 \\ & 2x & n = 1 \\ & 2xH_{n-1}(x) - 2(n-1)H_{n-2}(x) & n > 1 \end{matrix}\right. Hn(x)=12x2xHn1(x)2(n1)Hn2(x)n=0n=1n>1

#include<stdio.h> int hermite(int n, int x) { if (n == 0) return 1; if (n == 1) return 2*x; if (n > 1) return 2*x*hermite(n-1, x) - 2*(n-1)*hermite(n-2, x); return 0; } int main() { int n, x; printf("please input n,x:"); scanf("%d %d", &n, &x); printf("result = %d", hermite(n, x)); return 0; }

编程题【简单算法】

√降序数

编写一个程序,判断给定自然数 n 是否为降序数。降序数是指对于 n=d1d2d3,dk 有 di>=di+1(i=1,2,…,k-1)。例如,1、876 和 6643 是降序数,而 67549 不是降序数。

#include<stdio.h> // 判断是否为降序数的方法 int isDrop(int n) { int a = 0, b = 0; while (n != 0) { a = n % 10; // 右1 b = (n / 10) % 10; // 右2 if (a > b && (n/10) != 0) // 右1 > 右2 return 0; // 不是降序数 n = n / 10; // 去掉一位 } return 1; // 是降序数 } int main() { int n; printf("请输入一个自然数n:"); scanf("%d", &n); isDrop(n) ? printf("%d 是降序数", n) : printf("%d 不是降序数", n); return 0; }

下面这样也可以:

// 判断是否为降序数的方法 int isDrop(int n) { int a = 0, b = 0; while (n != 0) { if (n < 10) return 1; a = n % 10; // 右1 b = (n / 10) % 10; // 右2 if (a > b) return 0; // 右1 > 右2, 则不是降序数 n = n / 10; // 去掉一位 } return 1; // 是降序数 }

无敌精简版:

// 判断是否为降序数的方法 int isDrop(int n) { while (n) { if (n < 10) return 1; if (n % 10 > n / 10 % 10) return 0; // 右1 > 右2, 不是降序数 n = n / 10; // 去掉一位 } return 1; // 是降序数 }

√计算数学表达式

定义一个函数,计算并返回如下算式的值: T = 4.25 ( a + b ) + l n ( a + b + a + b + 1 a + b ) 4.25 c + l n ( c + c + 1 c ) T = \frac {4.25(a+b) + ln(a+b + \sqrt{a+b} + \frac {1} {a+b})} {4.25c + ln(c + \sqrt{c} + \frac {1} {c})} T=4.25c+ln(c+c +c1)4.25(a+b)+ln(a+b+a+b +a+b1) 在主函数中,输入10组实数 a、b、c 的值,并将这10组 a、b、c 的值和上式计算结果写入文件 data.txt 中,同时输出到屏幕上。要求每一组值在文件和屏幕上均占一行。

#include<stdio.h> #include<math.h> double funcT(double a, double b, double c) { double t1 = 4.25 * (a + b) + log(a + b + sqrt(a + b) + 1 / (a + b)); double t2 = 4.25 * c + log(c + sqrt(c) + 1 / c); return t1 / t2; } int main() { FILE *fp; if ((fp = fopen("data.txt", "w+")) == NULL) { printf("cannot open file\n"); return 0; } int i = 0; double a, b, c; while (i++ < 10) { scanf("%lf %lf %lf", &a, &b, &c); printf("a=%.4lf, b=%.4lf, c=%.4lf, T=%.4lf\n", a, b, c, funcT(a, b, c)); fprintf(fp, "a=%.4lf, b=%.4lf, c=%.4lf, T=%.4lf\n", a, b, c, funcT(a, b, c)); } if (fclose(fp) != 0) printf("file close error\n"); return 0; }

√亲密数对

求 2 到 500 之间的所有亲密数对并保存到文件 data.txt 中。亲密数对的定义为:如果 M 的因子(包括 1,但不包括自身)之和为 N,且 N 的因子之和为 M,则称 M 与 N 为一对亲密数。

#include<stdio.h> // 判断是否存在亲密数对,如果是返回对应数字;否则返回0 int isFriendly(int M) { int N = 1, M2 = 1; for (int i = 2; i <= M/2; i++) if (M % i == 0) N += i; for (int i = 2; i <= N/2; i++) if (N % i == 0) M2 += i; return M == M2 ? N : 0; } int main() { int N = 0; FILE *fp; if ((fp = fopen("data.txt", "w+")) == NULL) { printf("cannot open file\n"); return 0; } for (int M = 2; M <= 500; M++) { N = isFriendly(M); // 判断是否是亲密数 if (N) { // (N != -1) && (N < M) printf("M=%3d, N=%3d\n", M, N); fprintf(fp, "M=%3d, N=%3d\n", M, N); } } if (fclose(fp) != 0) printf("file close error\n"); return 0; }

双胞胎数

若两素数之差为 2,则称两素数为双胞胎数。求出 [2, 300] 之内: (1)所有素数并保存到文件 prime.txt 种 (2)有多少对双胞胎数 (3)最大的一对双胞胎数

素数即质数,是指在大于 1 的自然数中,除了 1 和它本身以外不再有其他因数的自然数。

#include<stdio.h> // 判断某个数是否是素数 int isPrimeNum(int n) { for (int i = 2; i <= n/2 ; i++) if (n % i == 0) return 0; // 不是素数 return 1; // 是素数 } int main() { FILE *fp; int max = 0, count = 0; if ((fp = fopen("prime.txt", "w")) == NULL) { printf("cannot open file\n"); return 0; } for (int i = 2; i <= 300; i++) { if (isPrimeNum(i)){ fprintf(fp, "%d\n", i); if ((i+2 <= 300) && isPrimeNum(i+2)) { max = i; count++; } } } printf("共有 %d 对双胞胎数\n", count); printf("最大的一对双胞胎数为: (%d, %d)", max, max+2); if (fclose(fp) != 0) printf("file clsoe error\n"); return 0; }

模拟双目运算符

编写一个根据用户键入的两个操作数和一个双目运算符,由计算机输出结果的程序。

/* 编写一个根据用户键入的两个操作数和一个双目运算符,由计算机输出结果的程序。 双目运算符: * / % + - */ #include<stdio.h> int operate(int a, int b, char s) { switch (s) { case '+' : return a + b; case '-' : return a - b; case '*' : return a * b; case '/' : return a / b; case '%' : return a % b; default : printf("error!\n"); return 0; } } int main() { int a, b; char s; scanf("%d %c %d", &a, &s, &b); printf("%d %c %d = %d", a, s, b, operate(a, b, s)); return 0; }

求车牌号

一辆卡车违反交通规则,撞人逃跑。现场三人目击事件,但都没记住车号,只记下了车号的一些特征。甲说:牌照的前两位数字是相同的;乙说:牌照的后两位数字是相同的;丙是位数学家,他说:四位的车号刚好是一个整数的平方。请根据以上线索求出车号。

知识点:定义变量时有个隐含的类型转换。

int t = sqrt(8000); // 隐含的类型转换 printf("%d\n", t); // 89 printf("%d\n", sqrt(8000)); // -2105675310 printf("%d\n", (int)sqrt(8000)); // 89

代码:

#include<stdio.h> #include<math.h> int main() { for (int i = 1111; i < 9999; i+=11) // 保证后两位是相同的 if ((i/1000)==(i/100%10) && (int)sqrt(i)*(int)sqrt(i)==i) printf("车号是: %d\n", i); return 0; }

下面这么写也可以:

int main() { for (int i = 1111; i < 9999; i+=11) { // 保证后两位是相同的 int t = sqrt(i); // 定义变量时有隐含的类型转换 if ((i / 1000) == (i / 100 % 10) && t * t == i) printf("车号是: %d\n", i); } return 0; }

*一元二次方程求解

已知文件 Coefficient.txt 中存有多个方程 ax2 + bx + c = 0 中系数 a, b, c 的值,数据按行排列,编写程序求出方程的解,并将结果写入到 result.txt 文件中,要求考虑 a, b, c 各种取值情况。

Coefficient.txt 内容举例:

5 25 3 0 2 6 0 0 0 1 1 8 ......

本题知识点:文件操作读取与写入

#include<stdio.h> #include<math.h> int main() { FILE *fp1, *fp2; if ((fp1 = fopen("Coefficient.txt", "r")) == NULL) { printf("cannot open Cofficient.txt\n"); return 0; } if ((fp2 = fopen("result.txt", "w")) == NULL) { printf("cannot open thie result.txt\n"); return 0; } double a, b, c, x1, x2, delta; int i = 0; while (fscanf(fp1, "%lf %lf %lf", &a, &b, &c) != EOF) { i++; printf("i=%d: a=%.2lf, b=%.2lf, c=%.2lf\n", i, a, b, c); if (a != 0) { // a!=0 一元二次方程组,讨论根的情况 delta = b * b - 4 * a * c; if (delta < 0) { fprintf(fp2, "i=%d: %s\n", i, "no result"); } else { x1 = (-b + sqrt(delta)) / (2 * a); x2 = (-b - sqrt(delta)) / (2 * a); fprintf(fp2, "i=%d: x1=%.2lf, x2=%.2lf\n", i, x1, x2); } } else { // a == 0 一元一次方程组,讨论b,c的情况 if (b != 0) { // a==0 && b!=0 fprintf(fp2, "i=%d, x=%.2lf\n", i, -c / b); } else { // a==0 && b==0 if (c == 0) // a==0 && b==0 && c==0 任意数字都是解 fprintf(fp2, "i=%d: %s\n", i, "everything"); else // a == 0 && b==0 && c!=0 无解 fprintf(fp2, "i=%d: %s\n", i, "no solution"); } } } if (fclose(fp1) != 0) printf("close Cofficient.txt error"); if (fclose(fp2) != 0) printf("close result.txt error"); return 0; }

小球自由落体

一球从 100 米高度自由落下,每次落地后反弹回原高度的一半;再落下,求它在第 10 次落地时,共经过多少米?第 10 次反弹多高?

#include<stdio.h> int main() { double height = 100, sum = 0; for (int i = 1; i <= 10; i++) { if (i == 1) { // 第1次落体不用加反弹 sum += height; } else { // 第2次以后的落体都要加上一次反弹高度 sum += 2*height; } height /= 2; } printf("sum: %lf\n", sum); printf("10th height: %lf", height); return 0; }

**蛇形数组

编写程序,实现将自然数 1,2···,N2 按蛇形方式存入 N 阶方阵。例如,当 N=3 和 N=4 时的矩阵份别如下图所示。

N = 3 N = 4 6 7 9 7 13 14 16 2 5 8 6 8 12 15 1 3 4 2 5 9 11 1 3 4 10

从 an,0 开始到 a0,n 为止 (n = N -1) 顺序填入自然数,交替地对每一斜列从左上元素向右下元素或从右下元素向左上元素存数。

#include <stdio.h> #define SIZE 100 int main() { int n; int i = 0; // 行 int j = 0; // 列 // k代表数组移动方向 int k = 1; // k=1 → k=2 ↙ k=3 ↓ k=4 ↗ int data[SIZE][SIZE] = {0}; data[0][0] = 1; printf("please input N:"); scanf("%d", &n); while (i != n - 1 || j != n - 1) { // i == j == n-1 即到达数组右下角 if (k == 1) { // → data[i][j+1] = data[i][j] + 1; j++; if (i == n - 1) k = 4; // data位于矩阵的最下面一行时, k变为4 else k = 2; // data位于矩阵的第一行时, k变为2 } else if (k == 2) { // ↙ data[i + 1][j - 1] = data[i][j] + 1; j--;i++; if (j == 0 && i != n - 1) k = 3; // data位于矩阵的第一列时,k变为3 else if (i == n - 1) k = 1; // data位于矩阵的最下面一行时,k变为1 else k = 2; // data位于矩阵其它位置时,k仍为2 } else if (k == 3) { // ↓ data[i + 1][j] = data[i][j] + 1; i++; if (j == n - 1) k = 2; // data位于矩阵的第一列时,k变为4 else k = 4; // data位于矩阵的最后一列时,k变为2 } else if (k == 4) { // ↗ data[i - 1][j + 1] = data[i][j] + 1; i--;j++; if (i == 0 && j != n - 1) k = 1; // data位于矩阵的第一行时,k变1 else if (j == n - 1) k = 3; // data位于矩阵的最后一列时,k变为3 else k = 4; // data位于矩阵其它位置时,k仍为4 } } //显示矩阵 for (int a = 0; a < n; a++) { for (int b = 0; b < n; b++) printf("%d\t", data[a][b]); printf("\n"); } return 0; } please input N:5 1 2 6 7 15 3 5 8 14 16 4 9 13 17 22 10 12 18 21 23 11 19 20 24 25 please input N:7 1 2 6 7 15 16 28 3 5 8 14 17 27 29 4 9 13 18 26 30 39 10 12 19 25 31 38 40 11 20 24 32 37 41 46 21 23 33 36 42 45 47 22 34 35 43 44 48 49

正整数

给出一个不多于 5 位的正整数,要求:①求出它是几位数;②分别打印出每一位数字;③按逆序打印出各位数字,例如原数 321,应输出 123。

#include<stdio.h> #define SIZE 5 int main() { int n, count = 0; int number[SIZE]; // 数组初始化每一位为-1 for (int i = 0; i < SIZE; i++) { number[i] = -1; } printf("请输入一个不超过%d位的正整数:", SIZE); scanf("%d", &n); while (n != 0) { number[count++] = n % 10; n /= 10; } printf("这是 %d 位数\n", count); printf("正序输出:"); for (int i = SIZE-1; i >= 0; i--) { if (number[i] == -1) continue; printf("%d", number[i]); } printf("\n"); printf("逆序输出: "); for (int i = 0; i < SIZE; i++) { if (number[i] == -1) break; printf("%d", number[i]); } return 0; }

水仙花数

打印出所有的 “水仙花数”,所谓 “水仙花数” 是指一个 3位数,其各位数字立方和等于该数本身。例如,153是一水仙花数,因为 153 = 13 + 53 + 33

#include<stdio.h> #include<math.h> int main() { int ge, shi, bai; for (int i = 100; i <= 999; i++) { ge = i % 10; shi = i / 10 % 10; bai = i / 100; if (pow(ge, 3) + pow(shi, 3) + pow(bai, 3) == i) { printf("%d\n", i); } } return 0; }

学生成绩

输入 10 个学生 5门课的成绩,分别用函数求:①每个学生平均分;②每门课的平均分;③找出最高的分数对应的学生和课程;④求平均分方差。写出完整成绩。 $$ \sigma = \frac 1 n \sum {x_i}^2 -

\begin{bmatrix} \frac {\sum xi} n \end{bmatrix}^2 $$ xi 为某一学生的平均分。

#include<stdio.h> #define M 3 #define N 5 int main() { int a[M][N]; double sums[M]; for (int i = 0; i < M; i++) { printf("please input stu%d scores:", i+1); for (int j = 0; j < N; j++) { scanf("%d", &a[i][j]); } } int maxScore = 0, ci = 0, cj = 0; for (int i = 0; i < M; i++) { double sum = 0; for (int j = 0; j < N; j++) { sum += a[i][j]; if (maxScore < a[i][j]) { // 找出最高分,并记录数组下标 maxScore = a[i][j]; ci = i; cj = j; } } sums[i] = sum / N; printf("stu%d average score:%.2lf\n", i+1, sums[i]); } printf("maxCourse: student%d's %dth course - %d\n", ci+1, cj+1, maxScore); double res = 0; for (int i = 0; i < M; i++) { res += (sums[i]/N) * (sums[i]/N); } res = res / N; for (int i = 0; i < M; i++) { res -= (sums[i] / N / N) * (sums[i] / N / N); } printf("MSN is %.2lf", res); return 0; }

*矩阵的鞍点

求矩阵中所有的鞍点。如果在 m 行 n 列矩阵中的元素 A(i, j) 既是第 i 行中的最大值,又是第 j 列中的最小值,则称 A(i, j) 为矩阵的鞍点。

思路:遍历矩阵每行元素:先找出行最大,然后判断该点是否为列最小。

#include<stdio.h> #define M 3 #define N 4 int main() { int a[M][N]; // 初始化M*N矩阵 for (int i = 0; i < M; i++) { printf("请输入第 %d 行的元素:", i+1); for (int j = 0; j < N; j++) { scanf("%d", &a[i][j]); } } int iMax = -1, jMin = 99999; for (int i = 0; i < M; i++) { int k = 0, p = 0; // 行最大 for (int j = 0; j < N; j++) { if (a[i][j] > iMax) { iMax = a[i][j]; k = j; } } // 列最小 for (int o = 0; o < M; o++) { if (a[o][k] < jMin) { jMin = a[o][k]; p = o; } } if (iMax == jMin) printf("a[%d][%d] 是 鞍点\n", p, k); } return 0; }

大小写字符转换

设计函数,将小写英文字符变为对应的大写字符。

#include<stdio.h> // 小写转大写 char convertc2C(char c) { return c - 'a' + 'A'; } // 大写转小写 char convertC2c(char c) { return c - 'A' + 'a'; } int main() { char c; printf("please input char c:"); scanf("%c", &c); printf("result: %c\n", convertc2C(c)); getchar(); printf("please intput char c:"); scanf("%c", &c); printf("result: %c\n", convertC2c(c)); return 0; }

完数

编程求 1000 之内的所有 ”完数“。所谓 ”完数“ 是指一个数恰好等于它的包括 1 在内的所有不同因子之和。例如,6 是完数,因为 6 = 1 + 2 + 3。

#include<stdio.h> int perfectNum(int n) { int sum = 0; for (int i = 1; i < n; i++) { if (n % i == 0) sum += i; // 因子和相加 } if (sum == n) return 1; // 本身=因子和,是完数 return 0; } int main() { for (int i = 1;i <= 1000; i++) { if (perfectNum(i)) printf("%d ", i); } return 0; }

字符串统计整数

输入一个字符串,内有数字和非数字字符,如:

A123x456$%1789>3500tab587

将其中连续的数字字符作为一个整数,依次存放到一数组 a 中。例如,123 放在 a[0],456 放在 a[1],…,统计共有多少个整数,并输出这些整数。

#include<stdio.h> #include<string.h> #define MAX_SIZE 50 // 0的ASCII是48 // 字符串转数字 int my_atoi(char *str) { int res = 0; while (*str != '\0') { if (*str >= '0' && *str <= '9') res = res * 10 + (*str - '0'); else break; str++; } return res; } int main() { int a[MAX_SIZE]; char str[MAX_SIZE]; printf("please intput string:"); scanf("%s", str); // gets(str); char *p = str; int count = 0; while (*p != '\0') { if (*p >= '0' && *p <= '9') { a[count++] = my_atoi(p); while (*p >= '0' && *p <= '9') p++; } p++; } printf("total: %d\n", count); for (int i = 0; i < count; i++) { printf("%d ", a[i]); } return 0; }

求和公式

∑ k = 1 100 k + ∑ k = 1 50 k 2 + ∑ k = 1 10 1 k \sum_{k=1}^{100} k + \sum_{k=1}^{50} k^2 + \sum_{k=1}^{10} \frac 1k k=1100k+k=150k2+k=110k1

#include<stdio.h> int main() { float k = 1.0, sum = 0; while (k <= 100) { if (k <= 10) sum += 1/k; if (k <= 50) sum += k*k; sum += k; k++; } printf("res: %lf\n", sum); return 0; }

模拟选举

编程模拟选举过程。假定 4 位候选人 zhang、wang、li、zhao,代号分别为 1、2、3、4。选举人直接键入候选人代号,1~4之外的整数视为弃票权,-1为终止标志。打印各位候选人的得票以及当选者(得票数超过选票总数一半)的名单。

#include<stdio.h> int main() { int c[4] = {0}, count = 0, abandon = 0; char name[4][10] = {"zhang", "wang", "li", "zhao"}; int t = 0; printf("voting start!\n"); while (t != -1) { // 投票 count++; printf("please choose: 1-zhang, 2-wang, 3-li, 4-zhao\n"); scanf("%d", &t); switch(t) { case 1 : c[0]++; break; case 2 : c[1]++; break; case 3 : c[2]++; break; case 4 : c[3]++; break; default : abandon++; break; } } printf("voting end!\n\n"); for (int i = 0; i < 4; i++) { if (c[i] > count/2) { printf("success: %s - %d\n", name[i], c[i]); continue; } printf("%s - %d\n", name[i], c[i]); } return 0; }

*打印图案

编程打印如下图形,中间一行英文字母由输入得到,图形应随输入的英文字母的变化而变化。例如输入英文字母 A 得到的图形为:

A

输入英文字母 B 得到的图形为:

A BBB A

输入英文字母 D 得到的图形为:

A BBB CCCCC DDDDDDD CCCCC BBB A #include<stdio.h> int main() { char c; printf("please input one char:"); c = getchar(); int t = c - 'a' + 1; // 将输入字母转化为数字,a-1,b-2,c-3,d-4.... for (int i = 1; i <= 2*t-1; i++) { // 总行数 2t-1,例如d有7行 if (i <= t) { // 上半部分(包括中间) for (int k = 0; k < t-i; k++) printf(" "); // 空格 for (int j = 1; j <= 2 * i - 1; j++) { // 第1行1个,第2行3个,第3行5个.... printf("%c", 'a' + i - 1); } printf("\n"); } else if (i > t) { // 下半部分 for (int k = 0; k < (i-t); k++) printf(" "); // 空格 for (int j = 1; j <= 2 * t - 1 - 2 * (i - t); j++) { printf("%c", c - (i - t)); } printf("\n"); } } return 0; }

ASCII 排序(选择、冒泡)

用 选择法 或 冒泡法 对 输入的 50 个字符(按 ASCII 由小到大)进行排序。

#include<stdio.h> #define SIZE 10 // 冒泡排序 void bubbleSort(char strs[]) { char tmp; for (int i = SIZE - 1; i > 0; i--) { for (int j = 0; j < i; j++) { if (strs[j] < strs[j+1]) { tmp = strs[j]; strs[j] = strs[j + 1]; strs[j + 1] = tmp; } } } } // 选择排序 void selectionSort(char strs[]) { for (int i = SIZE - 1; i > 0; i--) { int max = 0, tmp; for (int j = 0; j<= i; j++) { if (strs[j] > strs[max]) { max = j; } } tmp = strs[i]; strs[i] = strs[max]; strs[max] = tmp; } } int main() { char strs[SIZE] = {0}; printf("please input some chars:"); scanf("%s", strs); // bubbleSort(strs); selectionSort(strs); for (int i = 0; i < SIZE; i++) { printf("%c ", strs[i]); } return 0; }

√判断素数与分解

编写一个函数 int prism(int n),函数的功能为判定 n 是否为素数(所谓素数是指能够被 1 和自身整除外不能被其他任何数整除的数),如果 n 为素数则返回指 1,否则返回 0。把一个大于 4 的偶数分解为两个素数和的形式,并且把分解的结果写入一个磁盘文件 result.dat 中。(如 8 = 3 + 5)

#include<stdio.h> // 判断素数 int prism(int n) { for (int i = 2; i <= n/2; i++) if (n % i == 0) return 0; return 1; } int main() { FILE *fp; if ((fp = fopen("result.dat", "a")) == NULL) { printf("cannot open result.dat\n"); return 0; } int n; printf("please input n:"); scanf("%d", &n); if (prism(n)) { // 是素数 printf("%d is prime number\n", n); } else if (n <= 4 || n%2==1) { // <=4 或是 奇数 printf("%d is not prime number and cannot split it\n", n); } else { // 分解为两个素数之和 printf("%d is not prime number but it can be split\n", n); for (int i = 2; i < n/2; i++) { if (prism(i) && prism(n-i)){ printf("%d = %d + %d\n", n, i, n-i); fprintf(fp, "%d = %d + %d\n", n, i, n-i); } } } if (fclose(fp) != 0) printf("close result.dat error\n"); return 0; }

行最小与列最小矩阵

求一个 n 阶方阵中满足条件:“它在行上是最小的,在列上是最小的” 所有元素,并输出元素值及所在的位置:如果没有满足上述条件的元素,请输出 “NO FIND”。例如,一个 n = 5 的方针如下:

11 4 2 7 8 5 9 23 1 25 3 22 21 18 15 17 16 24 12 6 13 10 19 20 14

输出结果是:2(1, 3),1(2, 4),3(3, 1), 6(4, 5)。其中,2(1, 3) 表示 2 是满足条件的元素,其所在位置是 第 1行,第 3 列,其他含义相同。

#include<stdio.h> #define N 5 int main() { int a[N][N]; printf("please input %dx%d matrix:", N, N); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { scanf("%d", &a[i][j]); } } printf("\n"); int ci = 0, cj = 0; for (int i = 0; i < N; i++) { // 这个的位置要放在循环内部,每次循环都需要重新初始化 int iMin = 999999, jMin = 999999; // 找列最小 for (int j = 0; j < N; j++) { if (a[i][j] < iMin) { iMin = a[i][j]; ci = i; cj = j; } } // 找列最小 for (int k = 0; k < N; k++) { if (a[k][cj] < jMin) jMin = a[k][cj]; } // 行最小 等于 列最小 if (iMin == jMin) printf("%d(%d, %d) ", iMin, ci+1, cj+1); } return 0; }

翻转扑克牌

有 52 张扑克牌,使它们全部正面朝上。从第 2 张牌开始,把凡是 2 的倍数位置上的牌翻成正面朝下;接着从第 3 张牌开始,把凡是 3 的倍数位置上的牌正面朝上的翻成正面朝下,正面朝下的翻成正面朝上;接着从第 4 张牌开始,把凡是 4 的倍数位置上的牌按此规律翻转;以此类推,直到第 1 张要翻的牌是第 52 张 牌翻完为止。统计最后有几张牌正面朝上,并打印出来。

#include<stdio.h> int main() { int a[53] = {0}; // 1正面朝上, 0正面朝下 for (int i = 1; i <= 52; i++) { a[i] = 1; // 52张牌初始化为正面朝上 } // 2倍数位置上的牌,朝上->朝下 for (int i = 2; i <= 52; i+=2) { a[i] = 0; } // 3倍数位置上的牌,朝上->朝下,朝下->朝上 // 4倍数位置上的牌,朝上->朝下,朝下->朝上 // .... // 52倍数位置上的牌,朝上->朝下,朝下->朝上 for (int i = 3; i <= 52; i++) { for (int j = i; j <= 52; j++) { if (j % i == 0) { a[j] = a[j] ? 0 : 1 ; } } } /* // 更精简的写法 for (int i = 3; i <= 52; i++) { for (int j = i; j <= 52; j+=i) a[j] = a[j] ? 0 : 1 ; } */ int count = 0; for (int i = 1; i <=52; i++) { if (a[i]) { printf("%d ", i); count++; } } printf("有%d张正面朝上", count); return 0; }

编程题 - 结构体

*统计学生成绩

已知共有 30 名学生,每名学生有数学、语文、物理、化学、英语这 5 门课,班主任需要统计总分在前 10 名的同学的姓名和学号,另外特别关注这 10 名同学中有某门课程低于 80 分的同学,请编写程序实现上述功能。(若有分数相同,允许和第十名并列输出。程序添加必要的注释)

本题知识点:结构体、冒泡排序

#include<stdio.h> #define N 30 // 30个学生 #define M 5 // 5门课 typedef struct Student { char *name; // 姓名 char* id; // 学号 int score[M]; // 5门课成绩 int sum; // 总分 } Student; // 冒泡排序 void sort(Student s[]) { Student tmp; for (int i = N - 1; i > 0; i--) { for (int j = 0; j < i; j++) { if (s[j].sum < s[j+1].sum) { tmp = s[j]; s[j] = s[j + 1]; s[j + 1] = tmp; } } } } int main() { Student s[N] = { {"张三", "001",{90, 90, 80, 90, 90}}, {"李四", "002", {90, 80, 50, 90, 70}}, {"王五", "002", {70, 40, 60, 80, 80}}, {"赵六", "002", {80, 30, 80, 90, 90}}, {"燕七", "002", {50, 50, 70, 80, 50}}, {"周八", "002", {30, 60, 90, 90, 20}}, // 30个人.... }; // 计算总分 for (int i = 0 ; i < N; i++) { for (int j = 0; j < M; j++) { s[i].sum += s[i].score[j]; } } sort(s); for (int i = 0; i < N; i++) { if (s[i].sum == 0) break; // 人数不足30不显示 printf("No.%d 学号:%s 姓名:%s 总分:%d ", i+1, s[i].id, s[i].name, s[i].sum); for (int j = 0; j < M; j++) { if (s[i].score[j] < 80) { switch(j) { case 1: printf("语文低于80分! "); break; case 2: printf("数学低于80分! "); break; case 3: printf("英语低于80分! "); break; case 4: printf("物理低于80分! "); break; case 5: printf("化学低于80分! "); break; } } } printf("\n"); } return 0; }

*计算天数

输入一个日期 startdata(年、月、日) 和 天数 days(>=1),输出自该输入日期 days 天后的日期 enddate(即 enddate = startdate + days)。要求输入和输出的年份为四位整数,输入时要对输入数据的有效性进行检查,并确保得到有效的输入数据。同时还需要考虑跨月、跨年和闰年等情况,闰年用自定义函数计算,日期用自定义结构体描述。

知识点:闰年

普通闰年:公历年份是4的倍数的, 且不是100的倍数(2004、2020)

世纪闰年:公历年份是400的倍数(2000)

#include<stdio.h> typedef struct Date { int y; int m; int d; } Date; int main() { int checkyear(Date date); int checkmonth(Date date); int checkday(Date date); Date getDate(Date date, int days); Date startdate, enddate; int days; while (1) { printf("please input startdate:"); scanf("%d %d %d", &startdate.y, &startdate.m, &startdate.d); if (checkyear(startdate) && checkmonth(startdate) && checkday(startdate)) { break; } else { printf("error, please try again\n"); } } printf("please input days:"); scanf("%d", &days); enddate = getDate(startdate, days); printf("%d %d %d\n", enddate.y, enddate.m, enddate.d); return 0; } // 年份输入检查 及 判断是否闰年 int checkyear(Date date) { if (date.y < 1000 || date.y > 9999) return 0; // 错误年份 if ((date.y%4==0 && date.y%100!=0) || date.y%400==0) return 2; // 闰年 else return 1; // 非闰年 } int checkmonth(Date date) { if (date.m >= 1 && date.m <= 12) return 1; else return 0; } int checkday(Date date) { int t[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if (checkyear(date) == 2) t[2] = 29; // 闰年2月有29天 if (date.d >= 1 && date.d <= t[date.m]) return 1; else return 0; } // 高斯日记算法 Date getDate(Date date, int days) { int a[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; for (int i = 1; i <= days; i++) { // 一天一天的加 if (checkyear(date) == 2) a[2] = 29; // 闰年2月有29天 date.d = date.d % a[date.m] + 1; if (date.d == 1) date.m = date.m % 12 + 1; if (date.m == 1) date.y++; } return date; }

学生成绩管理

输入 n 个学生的学号、姓名、数学成绩、语文成绩和英语成绩,求出每位学生的三门课程的总分,然后按总分由高到低排序,并将排序结果按学号、姓名、数学成绩、语文成绩、英语成绩、总分和名次打印输出到屏幕和文件 student.dat 中。要求用结构体描述学生信息,输出打印时每位学生信息占一行且上下列对齐,总分相同时名次相同。例如,假设有四个成绩为 280、275、275、250,则对应的名次为 1、2、2、4。

#include<stdio.h> #define N 50 typedef struct Student { char id[10]; char name[10]; int chi; // 语文成绩 int math; // 数学成绩 int eng; // 英语成绩 int sum; // 总分 } Student; Student stus[N]; void sort(Student stus[], int n) { Student tmp; for (int i = n-1; i >= 0; i--) { for (int j = 0; j < i; j++) { if (stus[j].sum < stus[j+1].sum) { tmp = stus[j]; stus[j] = stus[j+1]; stus[j+1] = tmp; } } } } int main() { FILE *fp; if ((fp=fopen("student.dat","w+")) == NULL) { printf("cannot open student.dat\n"); return 0; } int n; printf("please tell me how many stus:"); scanf("%d", &n); // 输入数据 for (int i = 0;i < n; i++) { printf("please intput no.%d 【id】", i+1); scanf("%s", stus[i].id); printf("please intput no.%d 【name】", i+1); scanf("%s", stus[i].name); printf("please intput no.%d 【chinese score】", i+1); scanf("%d", &stus[i].chi); printf("please intput no.%d 【math score】", i+1); scanf("%d", &stus[i].math); printf("please intput no.%d 【english score】", i+1); scanf("%d", &stus[i].eng); } // 计算每个学生的总分 for (int i = 0; i < n; i++) { stus[i].sum = stus[i].chi + stus[i].eng + stus[i].math; } sort(stus, n); for (int i = 0; i < n; i++) { int j = 0; printf("no.%d, id:%s\tname:%s\tchinese:%d english:%d math:%d sum:%d\n", (stus[j].sum==stus[i].sum)?j+1:i+1, stus[i].id, stus[i].name, stus[i].chi, stus[i].eng, stus[i].math, stus[i].sum); fprintf(fp, "no.%d, id:%s\tname:%s\tchinese:%d english:%d math:%d\n", (stus[j].sum==stus[i].sum)?j+1:i+1, stus[i].id, stus[i].name, stus[i].chi, stus[i].eng, stus[i].math, stus[i].sum); j = i; } if (fclose(fp) != 0) printf("close file error\n"); return 0; }
最新回复(0)