14 KiB
第二章 数据类型与顺序结构程序设计
本章内容
- 2.1 变量的数据类型
- 2.2 变量的输入与输出
- 2.3 顺序结构程序设计案例
- 2.4 提交评测与错误自查
2.1 变量的数据类型
核心知识
数据类型决定变量能够保存什么数据、占用多少存储空间,以及参与运算时采用什么规则。基础课程中常用的数据类型包括整数、浮点数、字符和布尔值。
| 分类 | 类型 | 主要用途 | 示例 |
|---|---|---|---|
| 整数 | short |
较小范围整数(-128~127) | short level = 10; |
| 整数 | int |
中范围整数,最常用(-21亿~21亿) | int age = 15; |
| 整数 | long long |
大范围整数(非常大,万兆以上) | long long total = 80000000; |
| 浮点数 | float |
单精度小数 | float rate = 0.5; |
| 浮点数 | double |
双精度小数,小数最常用 | double price = 12.5; |
| 字符 | char |
单个字符 | char grade = 'A'; |
| 布尔值 | bool |
真或假 | bool passed = true; |
选择类型时要同时考虑数据范围和计算精度。题目可能出现小数时,一般使用 double;整数范围可能很大时,需要考虑 long long。
char、转义字符与 ASCII
char 用来保存单个字符,字符值必须使用单引号:
char letter = 'A';
char digit = '7'; // 数字字符,不是整数 7
char op = '*';
char blank = ' ';
字符串使用双引号。'A' 是一个字符,"A" 是一个字符串,两者不能混用。
字符在内存中以整数编码保存。基础题通常使用 ASCII 规律处理英文字母和数字字符:
| 字符范围 | ASCII 值 |
|---|---|
'0'~'9' |
48~57 |
'A'~'Z' |
65~90 |
'a'~'z' |
97~122 |
常用转换:
char c = '8';
int number = c - '0'; // 数字字符转整数,得到 8
char upper = 'B';
char lower = upper + ('a' - 'A'); // 大写字母转小写字母,得到 'b'
int code = 65;
char letter = (char)code; // 强制转换后得到字符 'A'
char x = 'A';
int ascii = (int)x; // 强制转换后得到整数 65
转义序列以反斜杠 \ 开头:
| 写法 | 含义 |
|---|---|
\n |
换行 |
\t |
水平制表符(Tab键, 一般代表的 4 个空格) |
\\ |
一个反斜杠 |
\" |
一个双引号 |
\' |
一个单引号 |
示例:
cout << "小明说:\"what is \\n\"" << '\n';
输出:
小明说:"what is \n"
类型转换
当表达式中出现不同数据类型时,编译器可能进行自动类型转换。一般而言,整数与浮点数混合运算时,整数会转换为浮点类型:
int a = 5;
double b = 2.0;
double result = a / b; // 2.5
把 double 转为 int 会丢弃小数部分:
double value = 3.9;
int n = (int)value; // 3,不进行四舍五入
如果要转换整个表达式,应把表达式完整括起来:
char result = (char)(a + b);
典型例题
题目: 输入一个大写英文字母,输出对应的小写字母。
int main() {
char upper;
cin >> upper;
char lower = (upper - 'A') + 'a'; // 也可通过加减 32 来实现, 大写转小写需要加 32
cout << lower;
return 0;
}
说明: ASCII 中大写字母和小写字母各自连续排列,而对应大小写字母的差值则一定相同。
常见错误
- 把单个字符写成
"A"。char值应使用单引号'A'。 - 混淆整数
7与字符'7'。'7' - '0'才得到整数 7。 - 让
int保存需要保留小数的计算结果。 - 强制类型转换前没有考虑数据范围和精度损失。
- 直接假设任何字符都能通过加减 32 转换大小写。该规律只适用于对应的英文字母。
- 想输出一个反斜杠时只写一个反斜杠。字符串中应写
"\\"。
2.2 变量的输入与输出
核心知识
cin、cout 是 C++ 的流式输入输出工具,通过 <iostream> 使用。scanf、printf 是格式化输入输出函数,需要添加 <cstdio> 使用。
输入多个数据时,变量的数量、类型和顺序必须与题意一致。
输出时不仅要保证答案数值正确,还要严格匹配题目要求的空格、换行、小数位数和文字内容。
cin 与 cout
int a, b;
cin >> a >> b; // 依次读入两个整数
cout << a << " " << b; // 输出两个整数,中间一个空格
cout << a + b << '\n'; // 输出计算结果并换行
使用规则:
cin使用提取运算符>>,把输入保存到变量。cout使用插入运算符<<,把数据发送到控制台。cin >> a >> b;会跳过前导的空白字符,输入中的空格、Tab、回车通常都能分隔数据。cout << "a+b";输出文本a+b;cout << a + b;输出计算结果。endl和'\n'都能换行。
scanf 与 printf
#include <cstdio>
int age;
double height;
char grade;
scanf("%d%lf %c", &age, &height, &grade);
printf("%d %.2f %c\n", age, height, grade);
常用格式说明符:
| 数据类型 | scanf 读取 |
printf 输出 |
|---|---|---|
int |
%d |
%d |
long long |
%lld |
%lld |
float |
%f |
%f |
double |
%lf |
%f |
char |
%c |
%c |
输出小数位数:
double value = 3.1415926;
printf("%.2f\n", value); // 3.14
printf("%.3f\n", value); // 3.142
scanf 要把数据写入变量,因此变量名前通常要加取地址符 &:
int n;
scanf("%d", &n);
格式字符串中的普通字符必须与输入对应:
scanf("%d%d", &a, &b); // 可输入:10 20
scanf("%d,%d", &a, &b); // 必须输入:10,20
%c 默认不会跳过空白字符。需要跳过已有的空格或换行时,可在 %c 前留一个空格:
char op;
scanf(" %c", &op);
典型例题
题目: 输入总水量 t(毫升)和人数 n。输出每人分到的水量,保留 3 位小数;第二行输出需要的杯子数,每人 2 个杯子。
int main() {
double t;
int n;
scanf("%lf%d", &t, &n);
printf("%.3f\n", t / n);
printf("%d\n", n * 2);
return 0;
}
说明: scanf 读取 double 使用 %lf;printf 输出 double 使用 %f;%.3f 表示保留 3 位小数。
常见错误
- 把方向写反:
cin使用>>,cout使用<<。 scanf漏写&,导致无法把输入正确保存到变量。- 格式说明符与变量类型不匹配。此问题不只是“精度降低”,还可能导致读取失败或未定义行为。
- 混淆
double的格式:scanf读取用%lf,printf输出用%f。 scanf("%d,%d", ...)要求输入中真的出现逗号。- 用
%c读取字符时,意外读入了前一次输入留下的空格或换行。 - OJ 输出中多了提示语、单位、标点或空格。
2.3 顺序结构程序设计案例
核心知识
顺序结构程序按照代码书写顺序逐条执行。基础题通常可以分成“输入、处理、输出”三层:
// 1. 输入
cin >> ...;
// 2. 处理
// 计算公式、更新变量、转换单位
// 3. 输出
cout << ...;
面对程序设计题时,可以使用七步法:
- 读懂题目:明确最终要计算什么。
- 理解输入:确认数据的数量、类型、顺序和单位。
- 设计逻辑思路:先写公式或处理步骤。
- 翻译成代码:定义变量,把思路逐步写成 C++ 语句。
- 处理输出:安排顺序、空格、换行和精度。
- 编译查错:先解决语法错误。
- 样例验证:输入样例并对照输出,再补充边界数据。
常见解题方法包括:
- 把复杂计算拆成多个中间结果,用变量保存。
- 统一不同单位,再进行计算。
- 使用临时变量,防止原数据在赋值时被覆盖。
- 在关键位置临时输出中间变量,与手算结果逐步核对。
交换变量时需要第三个变量中转:
int a = 3, b = 4;
int temp = a;
a = b;
b = temp;
例题:小鱼的游泳时间
题目: 小鱼从当天 a 时 b 分游到 c 时 d 分。输入四个整数,输出游泳时长的小时数和分钟数。本题保证结束时间不早于开始时间。
#include <iostream>
using namespace std;
int main() {
int a, b, c, d;
cin >> a >> b >> c >> d;
int startMinutes = a * 60 + b;
int endMinutes = c * 60 + d;
int duration = endMinutes - startMinutes;
int hours = duration / 60;
int minutes = duration % 60;
cout << hours << " " << minutes;
return 0;
}
思路说明:
- 输入开始时间和结束时间,共 4 个整数。
- 把两个时刻统一换算为分钟。
- 用结束总分钟数减去开始总分钟数。
- 用
/ 60得到小时,用% 60得到剩余分钟。 - 输入
12 50 19 10时,应输出6 20。
如果结果错误,可以临时输出中间变量:
cout << "start=" << startMinutes << '\n';
cout << "end=" << endMinutes << '\n';
cout << "duration=" << duration << '\n';
提交 OJ 前要删除这些调试输出。
补充案例:按格式反转数字
输入形如 123.4 的固定格式数据,将其输出为 4.321。可以把输入看作 4 个字符和一个固定的小数点:
#include <cstdio>
int main() {
char a, b, c, d;
scanf("%c%c%c.%c", &a, &b, &c, &d);
printf("%c.%c%c%c\n", d, c, b, a);
return 0;
}
这里的 . 是格式字符串中的普通字符,因此输入中也必须在对应位置出现小数点。
常见错误
- 把样例数据直接写死,程序无法处理其他合法输入。
- 时间差分别计算小时差和分钟差,却没有处理借位。
- 交换变量时直接写
a = b; b = a;,使原值丢失。 - 复杂公式全部写在一行,出错后难以定位。
- 只测试样例,不测试整点、临界值、最小值等情况。
- 调试输出未删除,导致答案格式不匹配。
2.4 提交评测与错误自查
提交流程
- 在本地完成代码并成功编译。
- 输入题目样例,确认输出内容和格式一致。
- 把完整源代码提交到 OJ。
- 根据评测结果定位问题,修改后重新测试和提交。
OJ 只检查程序输出的字符序列是否符合要求。不要擅自添加输入提示、答案说明或单位。
常见评测结果
| 结果 | 含义 | 优先检查 |
|---|---|---|
| AC(Accepted) | 通过全部测试数据 | 程序已通过本题评测 |
| CE(Compile Error) | 编译错误 | 分号、括号、变量名、头文件、中文标点 |
| WA(Wrong Answer) | 答案错误 | 公式、条件、类型、边界情况、输出格式 |
| RE(Runtime Error) | 运行时错误 | 除数为 0、非法访问、错误输入函数用法 |
| TLE(Time Limit Exceeded) | 超出时间限制 | 算法效率、循环终止条件 |
错误自查顺序
出现 CE
- 查看编译器给出的第一条错误信息和行号。
- 检查该行以及前一行是否漏写分号。
- 检查
()、{}、引号是否成对。 - 检查变量是否先定义后使用,名称是否拼写一致。
- 检查是否误用了中文标点或缺少头文件。
出现 WA
- 先检查输出格式:空格、换行、小数位数、文字大小写。
- 用草稿纸手算样例和一组自选数据。
- 分步输出中间变量,找出第一个与手算不一致的位置。
- 检查整数除法、数据类型和运算优先级。
- 检查最小值、最大值、临界值和特殊情况。
出现 RE(目前较少遇见)
- 检查除数是否可能为 0。
- 检查
scanf的格式说明符和&。
本章练习
一、基础知识
-
为下列数据选择合适的类型:学生人数、商品价格、考试等级字符、条件真假、较大的整数总数。
-
说明字符
'7'与整数7的区别。 -
写出
'0'、'A'、'a'的 ASCII 值。 -
写出以下转换表达式:
- 数字字符
ch转为对应的整数数字。 - 大写英文字母
upper转为对应的小写字母。 - 整数
code强制转换为字符。
- 数字字符
-
写出下列转义序列的作用:
\n、\t、\\、\"。 -
scanf读取int、double、char时分别使用什么格式说明符? -
printf输出double并保留两位小数时,格式说明符应怎样写? -
scanf中为什么通常要在变量名前加&? -
分别说明 AC、CE、WA 的含义。
二、代码阅读与改错
-
写出程序的输出结果:
char c = '6'; int n = c - '0'; cout << n + 4; -
写出程序的输出结果:
char upper = 'C'; char lower = upper + ('a' - 'A'); cout << lower;
-
找出格式说明符的错误并改正:
int age; double height; scanf("%lf%d", &age, &height); printf("%d %.2d\n", age, height); -
找出变量交换失败的原因并改正:
int a = 3, b = 8; a = b; b = a; cout << a << " " << b;
三、程序设计
-
字符与 ASCII
输入一个字符,输出该字符以及它对应的 ASCII 值,中间用一个空格分隔。
- 样例输入:
A - 样例输出:
A 65
- 样例输入:
-
数字字符转整数
输入一个
'0'~'9'的数字字符,将它转换成整数后加 5,并输出结果。- 样例输入:
7 - 样例输出:
12
- 样例输入:
-
格式化平均值
输入三个
double数据,输出它们的平均值,结果需要严格保留 3 位小数。