PTA - C编程NoE - 结构
6-1 计算两个复数之积
struct complex multiply(struct complex x, struct complex y)
{
struct complex res;
res.real = x.real * y.real - x.imag * y.imag;
res.imag = x.real * y.imag + x.imag * y.real;
return res;
}
6-2 按等级统计学生成绩
int set_grade(struct student *p, int n)
{
int res = 0;
for(int i = 0; i < n; i++)
{
if(p[i].score >= 85) p[i].grade = 'A';
else if(p[i].score >= 70) p[i].grade = 'B';
else if(p[i].score >= 60) p[i].grade = 'C';
else
{
p[i].grade = 'D';
++res;
}
}
return res;
}
7-1 计算职工工资
#include <stdio.h>
struct clerk
{
char name[10]; // name为长度小于10的不包含空白字符的非空字符串
double basic_wage, floating_wage, expenditure, real_wage;
};
int main()
{
int n;
scanf("%d", &n);
struct clerk ck;
for(int i = 0; i < n; i++)
{
scanf("%s%lf%lf%lf", ck.name, &ck.basic_wage, &ck.floating_wage, &ck.expenditure);
ck.real_wage = ck.basic_wage + ck.floating_wage - ck.expenditure;
printf("%s %.2lf\n", ck.name, ck.real_wage);
}
return 0;
}
7-2 时间换算
因为需要用两位输出时分秒,也就是 ‘0’ 需要输出为 ‘00’,所以用 %02d 来控制输出。
#include <stdio.h>
struct Time
{
int hour, minute, second;
};
int main()
{
int time_passed; // 过了多少时间,小于60
struct Time t;
scanf("%d:%d:%d%d", &t.hour, &t.minute, &t.second, &time_passed);
int carry1 = (t.second + time_passed) / 60; // 计算秒上的进位
t.second = (t.second + time_passed) % 60; // 计算新的时间的秒位
int carry2 = (t.minute + carry1) / 60; // 计算分上的进位
t.minute = (t.minute + carry1) % 60; // 计算新的时间的分位
t.hour = (t.hour + carry2) % 24; // 计算新的时间的时位
printf("%02d:%02d:%02d\n", t.hour, t.minute, t.second);
return 0;
}
7-3 计算平均成绩
解:
因为要求先输出他们的平均成绩,再顺序输出平均线以下的学生名单,所以不能挨个判断然后输出,也就只能用结构体数组了。
#include <stdio.h>
struct student
{
char num[6]; // 学号(由5个数字组成的字符串)
char name[10]; // 姓名(长度小于10的不包含空白字符的非空字符串)
int grade; // 成绩([0,100]区间内的整数)
};
int main()
{
int n;
double average = 0.0;
scanf("%d", &n);
struct student stu[n];
for(int i = 0; i < n; i++)
{
scanf("%s %s %d", stu[i].num, stu[i].name, &stu[i].grade);
average += stu[i].grade;
}
average /= (double)n;
printf("%.2lf\n", average);
for(int i = 0; i < n; i++)
if(stu[i].grade < average)
printf("%s %s\n", stu[i].name, stu[i].num);
return 0;
}
7-4 查找书籍
长度不超过 30 的字符串需要用 31 大小的字符数组存放。而且用 gets 读取字符串的时候,一定要读掉前边的换行符,负责会只读到这个换行符。
#include <stdio.h>
int main()
{
int n, max_idx = 0, min_idx = 0;
char book_name[10][35];
double book_price[10];
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
getchar(); // 要读掉 gets 前边的换行符
gets(book_name[i]);
scanf("%lf", &book_price[i]);
if(book_price[i] > book_price[max_idx]) max_idx = i;
else min_idx = i;
}
printf("%.2lf, %s\n", book_price[max_idx], book_name[max_idx]);
printf("%.2lf, %s\n", book_price[min_idx], book_name[min_idx]);
return 0;
}
7-5 有理数比较
其实直接用 double 记录除法结果进行比较就可以,但是我觉得可能会出现精度错误,所以把两个分母变成一样大,比较变化后的分子的方式来判断,两种方法在这道题的测试用例中都可以通过。
#include <stdio.h>
long long LCM(int a, int b) // 计算最小公倍数 Least Common Multiple
{
int start;
if(a < b) start = b;
else start = a;
for(long long i = start; ; i++)
if(i % a == 0 && i % b == 0)
return i;
}
int main()
{
int a1, b1, a2, b2;
scanf("%d/%d %d/%d", &a1, &b1, &a2, &b2);
long long lcm = LCM(b1, b2);
long long a1_new = lcm / b1 * a1, a2_new = lcm / b2 * a2;
//double a_res = a1 * 1.0 / b1, b_res = a2 * 1.0 / b2;
//if(a_res > b_res) printf("%d/%d > %d/%d\n", a1, b1, a2, b2);
//else if(a_res < b_res) printf("%d/%d < %d/%d\n", a1, b1, a2, b2);
//else printf("%d/%d = %d/%d\n", a1, b1, a2, b2);
if(a1_new > a2_new) printf("%d/%d > %d/%d\n", a1, b1, a2, b2);
else if(a1_new < a2_new) printf("%d/%d < %d/%d\n", a1, b1, a2, b2);
else printf("%d/%d = %d/%d\n", a1, b1, a2, b2);
return 0;
}
7-6 平面向量加法
需要知道的是 %.1f 会自动进行四舍五入,0.05 变成 0.1, -0.05 变成 -0.1,-0.04 变成 -0.0,所以对于 -0.0 这种情况,不是说值是 0,而是 -0.04 这种小于0,但是又大于 -0.05 的情况,把这种情况设为0,即可。
#include<stdio.h>
int main()
{
double x1, y1, x2, y2, m, n;
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
m = x1 + x2;
n = y1 + y2;
if(m > -0.05 && m < 0) m = 0;
if(n > -0.05 && n < 0) n = 0;
printf("(%.1lf, %.1lf)\n", m, n);
return 0;
}
7-7 找出总分最高的学生
#include <stdio.h>
struct student
{
char num[6]; // 学号(由5个数字组成的字符串)
char name[10]; // 姓名(长度小于10的不包含空白字符的非空字符串)
int grade1, grade2, grade3; // 成绩([0,100]区间内的整数)
};
int main()
{
int n, top_sum = 0; // 最高的总分
scanf("%d", &n);
struct student top, tmp; // top: 总分最高的学生, tmp: 每次读的student变量
for(int i = 0; i < n; i++)
{
scanf("%s %s %d %d %d", tmp.num, tmp.name, &tmp.grade1, &tmp.grade2, &tmp.grade3);
if(tmp.grade1 + tmp.grade2 + tmp.grade3 > top_sum)
{
top_sum = tmp.grade1 + tmp.grade2 + tmp.grade3;
strcpy(top.num, tmp.num);
strcpy( top.name, tmp.name);
// 三门课的成绩不需要,只记录总分即可
}
}
printf("%s %s %d\n", top.name, top.num, top_sum);
return 0;
}
7-8 找出总分最高的学生
其实就是正常的插入排序,只不过对象换成了结构体。
#include <stdio.h>
#include <string.h>
struct friends
{
char name[11]; // 长度不超过10的英文字母组成的字符串
int birthday; // yyyymmdd格式的日期, 因为肯定是1开头,所以可以用 int 存放
char tel[18]; // 不超过17位的数字及+、-组成的字符串
};
int main()
{
int n, cur = 0;
scanf("%d", &n);
struct friends f[n];
for(int i = 0; i < n; i++) // 用 birthday 进行插入排序, birthday 大年纪就小
{
struct friends tmp;
scanf("%s %d %s", tmp.name, &tmp.birthday, tmp.tel);
int j;
for(j = 0; j < cur; j++)
if(tmp.birthday < f[j].birthday)
{
for(int k = cur; k > j; k--)
{
strcpy(f[k].name, f[k - 1].name);
f[k].birthday = f[k - 1].birthday;
strcpy(f[k].tel, f[k - 1].tel);
}
strcpy(f[j].name, tmp.name);
f[j].birthday = tmp.birthday;
strcpy(f[j].tel, tmp.tel);
break;
}
if(j == cur)
{
strcpy(f[cur].name, tmp.name);
f[cur].birthday = tmp.birthday;
strcpy(f[cur].tel, tmp.tel);
}
++cur;
}
for(int i = 0; i < n; i++)
printf("%s %d %s\n", f[i].name, f[i].birthday, f[i].tel);
return 0;
}