第1部分 语言篇
第1章 程序设计入门
1.1 算术表达式
程序1-1 计算并输出1+2的值
#include<stdio.h>
int main()
{
printf("%d\n", 1 + 2);
return 0;
}
程序1-2 计算并输出8/5的值,保留小数点后1位
#include <stdio.h>
int main()
{
printf("%.1f\n", 8.0 / 5.0);
return 0;
}
程序1-3 复杂表达式的计算
计算 1 + 2 3 5 − 0.1 1+\frac{2\sqrt{3}}{5-0.1} 1+5−0.123的值:
#include<stdio.h>
#include<math.h>
int main()
{
printf("%.8f\n", 1 + 2 * sqrt(3) / (5 - 0.1));
return 0;
}
1.2 变量及及其输入
程序1-4 a+b问题
#include<stdio.h>
int main()
{
int a, b;
scanf("%d%d", &a, &b);
printf("%d\n", a + b);
return 0;
}
例题1-1 圆柱体的表面积
输入底面半径r和高h,输入圆柱体的表面积,保留3位小数。
样例输入:
3.5 9
样例输出:
Area = 274.889
#include<stdio.h>
#include<math.h>
int main()
{
const double pi = acos(-1.0);
double r, h, s1, s2, s;
scanf("%lf%lf", &r, &h);
s1 = pi * r * r;
s2 = 2 * pi * r * h;
s = s1 * 2 + s2;
printf("Area = %.3lf\n", s);
return 0;
}
math.h中定义的常量M_PI不是ANSI C标准,使用gcc-ansi编译会出错,所以使用acos(-1.0) 求取
π
\pi
π的值。double acos(double x)
返回以弧度表示x的余弦值(弧度区间为[0,
π
\pi
π]),x为介于[-1,1]的浮点值。
1.3 顺序结构程序设计
例题1-2 三位数反转
输入一个三位数,分离出它的百位、十位和个位,反转后输出。
样例输入:
127
样例输出:
721
#include<stdio.h>
int main()
{
int n;
scanf("%d", &n); // 若输入520
printf("%d%d%d\n", n % 10, n / 10 % 10, n / 100); // 输出025
printf("%d\n", (n % 10) * 100 + (n / 10 % 10) * 10 + n / 100); // 输出25
printf("%03d\n", (n % 10) * 100 + (n / 10 % 10) * 10 + n / 100); // 输出025
}
例题1-3 交换变量
输入两个整数a和b,交换二者的值,然后输出:
样例输入:
824 16
样例输出:
16 824
#include<stdio.h>
// 借助临时变量
void swap1(int& a, int& b)
{
int t = a;
a = b;
b = t;
}
// 不借助临时变量
void swap2(int& a, int& b)
{
a = a + b;
b = a - b;
a = a - b;
}
int main()
{
int a, b, t;
scanf("%d%d", &a, &b);
swap1(a, b);
printf("%d %d\n", a, b); // 1
swap1(a, b);
swap2(a, b);
printf("%d %d\n", a, b); // 2
swap2(a, b);
printf("%d %d\n", b, a); // 3
}
算法竞赛是比谁能更好地解决问题,而不是比谁写的程序看上去更高级,应该保持简单(Keep It Simple and Stupid, KISS),所以本题最适合的程序是法3。
1.4 分支结构程序设计
例题1-4 鸡兔同笼
已知鸡和兔的总数量为n,总腿数为m。输入n和m,依次输出鸡和兔的数目。如果无解,则输出No answer。
样例输入:
14 32
样例输出:
12 2
样例输入:
10 16
样例输出:
No answer
#include<stdio.h>
int main()
{
int a, b, n, m;
scanf("%d%d", &n, &m);
a = (n * 4 - m) / 2;
b = n - a;
if(m % 2 == 1 || a < 0 || b < 0)
printf("No answer\n");
else
printf("%d %d\n", a , b);
return 0;
}
C语言逻辑表达式的短路(short-circuit)策略,当a为真时表达式a||b
不再计算b的值直接返回真,当a为假时表达式a&&b
不再计算b的值直接返回假。
例题1-5 三整数排序
输入3个整数,从下到大排序后输出。
样例输入:
20 7 33
样例输出:
7 20 33
#include<stdio.h>
int main()
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
if(a <= b && b <= c) printf("%d %d %d\n", a, b, c);
else if(a <= c && c <= b) printf("%d %d %d\n", a, c, b);
else if(b <= a && a <= c) printf("%d %d %d\n", b, a, c);
else if(b <= c && c <= a) printf("%d %d %d\n", b, c, a);
else if(c <= a && a <= b) printf("%d %d %d\n", c, a, b);
else if(c <= b && b <= a) printf("%d %d %d\n", c, b, a);
int t;
if(a > b) { t = a; a = b; b = t; } // 执行完毕后a<=b
if(a > c) { t = a; a = c; c = t; } // 执行完毕后a<=c,且a<=仍然成立
if(b > c) { t = b; b = c; c = t; } // 执行完毕后a<=b<=c
printf("%d %d %d\n", a, b, c);
return 0;
}
1.5 注解与习题
习题1-1 平均数(average)
输入3个整数,输出他们的平均值,保留3位小数。
#include<stdio.h>
int main()
{
int a, b, c;
double d;
scanf("%d%d%d", &a, &b, &c);
d = (double)(a + b + c);
printf("%.3lf\n", d / 3.0);
return 0;
}
习题1-2 温度(temperature)
输入华氏温度f, 输出对应的摄氏温度c,保留3位小数。提示: c = 5 ( f − 32 ) / 9 c = 5(f - 32) / 9 c=5(f−32)/9 。
#include<stdio.h>
int main()
{
int f;
double c;
scanf("%d", &f);
c = 5 * (f - 32) / 9.0;
printf("%.3lf\n", c);
return 0;
}
习题1-3 连续和(sum)
输入正整数n, 输出1+2+···+n的值。提示:目标是解决问题,而不是练习编程。
#include<stdio.h>
int main()
{
int n;
scanf("%d", &n);
if(n % 2 == 0)
printf("%d\n", n / 2 * (n + 1));
else
printf("%d\n", (n + 1) / 2 * n);
return 0;
}
习题1-4 正弦和余弦(sin和cos)
输入正整数n(n<360),输出n的正弦、余弦函数值。提示:使用科学函数。
#include<stdio.h>
#include<math.h>
int main()
{
int n;
double angle;
const double pi = acos(-1.0);
scanf("%d", &n);
angle = n / 180.0 * pi;
printf("%lf %lf\n", sin(angle), cos(angle));
return 0;
}
习题1-5 打折(discount)
一件衣服95元,若消费满300元,可打八五折。输入购买衣服件数,输出需要支付的金额(单位:元),保留两位小数。
#include<stdio.h>
int main()
{
int n;
double prize;
scanf("%d", &n);
prize = 95.0 * n;
if(prize >= 300)
printf("%.2lf\n", prize * 0.85);
else
printf("%.2lf\n", prize);
return 0;
}
习题1-6 三角形(triangle)
输入三角形3条边的长度值(均为正整数),判断是否能为直角三角形的3个变长。如果可以,则输出yes,如果不能则输出no。如果根本无法构成三角形,则输出not a triangle。
#include<stdio.h>
int main()
{
int a, b, c, t;
scanf("%d%d%d", &a, &b, &c);
if(a > b) { t = a; a = b; b = t; }
if(a > c) { t = a; a = c; c = t; }
if(b > c) { t = b; b = c; c = b; }
if(a + b <= c)
printf("not a triangle\n");
else if(a * a + b * b == c * c)
printf("yes\n");
else
printf("no\n");
return 0;
}
习题1-7 年份(year)
输入年份,判断是否为闰年。如果是,则输出yes,否则输出no。
提示:简单地判断除以4的余数是不够的。
#include<stdio.h>
int main()
{
int n;
scanf("%d", &n);
if(n % 400 == 0 || (n % 100 != 0 && n % 4 == 0))
printf("yes\n");
else
printf("no\n");
}
第2章 循环结构程序设计
2.1 for循环
程序2-1 输出1,2,3…,n的值
#include<stdio.h> // 1
int main() // 2
{ // 3
int n; // 4
scanf("%d", &n); // 5
for(int i = 1; i <= n; i++) // 6
printf("%d\n", i); // 7
return 0; // 8
} // 9
for循环的格式为:for(初始化; 条件; 调整) 循环体;
初始化–>条件–>循环体–>调整–>条件–>循环体–>…->调整–>条件不满足 -->退出循环
输入3的执行过程:
⓵ 当前行5:scanf请求键盘输入,输入2,此时变量n=2;
⓶ 当前行6:第一次执行循环语句,执行初始化语句int i = 1
,条件i <= 1
满足,继续执行
⓷ 当前行7:执行printf,由于i=1,屏幕输出1并换行。循环体结束跳回第6行。
⓸ 当前行6:先执行调整语句i++
,此时i=2,n=2,条件i<=n满足,继续执行.
⓹ 当前行7:执行printf,由于i=2,屏幕输出2并换行。循环体结束跳回第6行。
⓺ 当前行6:先执行调整语句i++
,此时i=3,n=2,条件i<=n不满足,跳出循环体。
⓻ 当前行8:程序结束。
例题2-1 aabb
输出所有形如aabb的4位完全平方数(即前两位数字相等,后两位数字也相等)。
#include <stdio.h>
#include <math.h>
int main()
{
for (int a = 1; a < 10; a++)
for (int b = 0; b < 10; b++)
{
int n = a * 1100 + b * 11;
int m = floor(sqrt(n) + 0.5);
if (m * m == n)
printf("%d\n", n);
}
return 0;
}
if(sqrt(n)==floor(sqrt(n)))
判断sqrt(n)是否为整数不保险,因为浮点数的运算(和函数)可能存在误差,假设经过大量计算后由于误差影响整数1变成了0.9999999999,floor的结果会是0而不是1,为了减少误差影响一般改为四舍五入,即floor(x+0.5)
,但是小数部分为0.5的数也会受到浮点数误差的影响。
例如printf("%lf\n", floor(1.9999999999999999));
的结果为2.000000。
另一个思路是枚举平方根,避免开平方操作:
#include <stdio.h>
#include <math.h>
int main()
{
for (int x = 0;; x++)
{
int n = x * x;
if (n < 1000)
continue;
if (n > 9999)
break;
int hi = n / 100;
int lo = n % 100;
if (hi / 10 == hi % 10 && lo / 10 == lo % 10)
printf("%d\n", n);
}
}
死循环for(;;)
,循环体不加break就不会结束。
2.2 while循环和do-while循环
例题3n+1问题
猜想:对于任意大于1的自然数n,若n为奇数,则将n变为3n+1,否则变为n的一半。经过若干次这样的变换,一定会使n变为1。例如,3–>10->5–>16–>8–>4–>2–>1。
输入n,输出变换的次数,
n
≤
1
0
9
n\leq10^9
n≤109。
样例输入:
3
样例输出:
7
// 3n+1问题(有bug)
#include <stdio.h>
int main()
{
int n, count = 0;
scanf("%d", &n);
while (n != 1)
{
if (n % 2 == 0)
n = n / 2;
else
n = 3 * n + 1;
count++;
}
printf("%d\n", count);
}
输入测试示例987654321,当判断条件为n!=1时进入死循环,当判断条件为n>1时输出1,原因是int值是-2147483648~2147483647,而3*n+1超出了int值范围
#include <stdio.h>
#include <math.h>
int main()
{
// [-2147483648~2147483647]
printf("[%d~%d]\n", 0x80000000, 0x7fffffff);
printf("[%d~%d]\n", 0b10000000000000000000000000000000, 0b01111111111111111111111111111111);
printf("[%d~%d]\n", (int)(-(long)pow(2, 31)), (int)((long)pow(2, 31) - 1));
}