跳转至

C1-02 变量的输入输出

变量、输入、运算与结果输出

学习目标:理解变量就是程序中用来存放数据的“盒子”;学会定义变量、给变量赋值;掌握 cin 输入和 cout 输出;能够完成“输入数据 → 计算处理 → 输出结果”的简单程序;知道如何根据题目数据范围选择合适的数据类型。

一、变量是什么

1. 为什么需要变量

第一课中,我们可以直接输出算式:

cout << "3 + 4 = " << 3 + 4 << endl;

这个程序只能计算 3 + 4。如果题目换成 5 + 8,就必须修改代码。

变量可以在程序运行时暂时保存数据,让程序先读入数据,再进行计算:

int a, b;            // 准备两个盒子,名字叫 a 和 b
cin >> a >> b;       // 从键盘读入两个整数
cout << a + b << endl;

输入 3 4,程序输出 7;输入 100 200,程序输出 300。同一份代码可以处理不同的数据,这就是变量的作用。

2. 把变量想象成一个盒子

变量是程序中用来存放数据的一块空间。可以把它想象成一个贴了名字的盒子:

┌─────────────┐
│    a = 10   │
└─────────────┘
  • 盒子:程序中用来保存数据的空间。
  • 标签:变量名,例如 a。
  • 盒子里的内容:变量的值,例如 10。
  • 盒子的类型:决定这个盒子可以装整数、小数、字符还是“是/否”。

3. 变量的值可以改变

变量之所以叫“变量”,是因为里面的值可以发生变化:

int a = 10;
cout << a << endl;      // 输出 10

a = 20;
cout << a << endl;      // 输出 20

第二次赋值后,原来的 10 被新的 20 覆盖了。

4. 定义、赋值和初始化

使用变量前,要先告诉计算机变量的类型和名字:

int score;
score = 100;
cout << score << endl;

= 是赋值运算符,意思是“把右边的内容放进左边的变量”:

int a;
a = 10;       // 把 10 放进 a
a = 20;       // 再把 20 放进 a,原来的 10 被覆盖

还可以把一个变量的值放进另一个变量:

int a = 10;
int b;
b = a;
cout << b << endl;     // 输出 10

定义变量的同时给它一个初始值,叫作初始化:

int age = 10;

初始化的完整例子:

int age = 10;
double pi = 3.14;
char ch = 'A';
bool pass = true;

关键区别: = 在这里不是数学里的“等于”,而是“赋值”。所以 a = a + 1; 是合法的,意思是“把 a 加 1 后再放回 a”。

5. 变量必须先定义,再使用

下面的写法是错误的:

score = 100;    // 错误:还没有定义 score

正确写法:

int score;
score = 100;

局部变量如果没有初始化,里面可能是内存中原来留下的随机内容:

int a;
cout << a << endl;     // 不要这样写,结果不确定

如果变量马上要通过 cin 输入,也可以先定义、后输入:

int a;
cin >> a;

二、变量名的写法

变量名就是盒子上的标签。标签写得不符合规则,程序就无法编译。

1. 变量名的四条规则

规则 说明 合法示例 非法示例
只能使用字母、数字和下划线 不能有空格,也不能使用其他符号 score、a1、student_score s core、a-b、a#
不能以数字开头 第一个字符必须是字母或下划线 a1、_x 1a、2nd
区分大小写 大写和小写是不同的字母 a 和 A 是两个不同变量 不要把 score 和 Score 混用
不能使用保留字 C++ 已经占用的词不能当普通变量名 num、sum int、return、if

2. 给变量名起名字的原则

给变量名起名字时,可以记住三个原则:

  • 见名知义:变量名尽量让人一眼看懂用途。例如,分数用 score,长度用 length,人数用 count。
  • 常用取简:很短、很常见的题目,可以使用 a、b、n、i 这类简短名字。
  • 专用取繁:程序较长、变量用途容易混淆时,变量名要写得更具体,例如 student_count、total_score。

示例:

int age;             // 年龄
int score;           // 分数
int student_count;   // 学生人数
double price;        // 价格

竞赛题中也经常使用简短的变量名:

int a, b, n;

3. 常见保留字

下面这些词有特殊作用,不能拿来当普通变量名:

int    long long    float    double
char   bool         if       else
for    while        return

main 是程序的主函数名称,也不要拿它当普通变量名。

三、用 cin 输入和 cout 输出

这一部分先统一使用 int 举例。学会流程后,再扩展到小数、字符等其他类型。

1. 程序的基本流程

写程序时经常遵循下面的顺序:

输入数据(Input) → 计算处理(Process) → 输出结果(Output)

例如,计算两个数的和:

输入 a 和 b → 计算 a + b → 输出 a + b

2. cin 是什么

cin 用来从键盘读取数据。>> 的中文正式名称是提取运算符,英文全称是 extraction operator,可以理解为“从输入流中提取数据,送进变量”。

cin >> 变量名;

数据方向可以画成:

键盘输入 → cin → 变量

3. 输入一个整数

int a;
cin >> a;

运行程序后,在键盘输入 10,然后按回车键结束本次输入,变量 a 的值就变成了 10。

注意: 自己在控制台运行时,输入完数据后要按回车。

4. 输入多个整数

int a, b;
cin >> a >> b;

程序会先把读到的第一个数据放进 a,再把读到的第二个数据放进 b。输入顺序必须和变量接收顺序一致。

输入:

3 4

结果是 a = 3、b = 4。如果输入 4 3,结果就会变成 a = 4、b = 3。

下面两种输入方式都可以:

3 4
3
4

空格和回车都可以用来分隔数据。输入完最后一个数据后,也要按回车键。

5. cout 输出变量

变量名不加引号,输出的是变量里的值:

int a = 10;
cout << a << endl;       // 输出 10

如果加上双引号,输出的就是字母 a:

cout << "a" << endl;      // 输出 a
写法 输出
cout << a; 输出变量 a 里面的值
cout << "a"; 输出字母 a

6. 输出多个变量和文字

int a = 10, b = 20;
cout << "a = " << a << ", b = " << b << endl;

输出:

a = 10, b = 20

7. 输入两个数并输出它们的和

这是最经典的顺序结构程序:

#include <iostream>
using namespace std;

int main() {
    int a, b;
    cin >> a >> b;           // Input:输入
    cout << a + b << endl;   // Process + Output:计算并输出
    return 0;
}

输入:

3 4

输出:

7

在线评测题没有要求时,不要输出“请输入两个数:”之类的提示语,否则可能造成答案格式错误。

四、数据类型

1. 为什么变量要有类型

不同的数据需要不同的“盒子”:

  • 12 是整数;
  • 3.14 是小数;
  • 'A' 是一个字符;
  • true 和 false 表示“是”或“否”。

定义变量时,要先写出它的数据类型。

2. 常用的基本数据类型

下面的范围和精度以信奥常见的 64 位 Linux + g++ 环境为参考。不同平台可能略有差异。

类型 关键字 字节数 常见范围或精度 示例
整数型 int 4 字节 -2147483648 ~ 2147483647,约 ±21 亿 12、-5
大整数型 long long 8 字节 -9223372036854775808 ~ 9223372036854775807,约 ±9.22×10¹⁸ 1000000000000
单精度小数型 float 4 字节 约 ±3.4×10^38,有效数字约 6~7 位 3.14
双精度小数型 double 8 字节 约 ±1.7×10^308,有效数字约 15~16 位 3.14
字符型 char 1 字节 通常占 1 字节;常见 ASCII 字符范围为 0~127 'A'、'+'
布尔型 bool 1 字节 只有 true 和 false true、false

初学阶段的选择口诀:

整数通常用 int,数字可能超过 21 亿时用 long long;小数一般用 double,需要明确使用单精度时用 float;一个字符用 char;只有“是/否”时用 bool。

3. 整数:int 和 long long

int age = 12;
int score = 100;

long long population;
cin >> population;
  • int 是最常用的整数类型。
  • long long 可以保存比 int 大得多的整数。

4. 小数:float 和 double

float rate;
cin >> rate;
double height = 1.52;
double price = 3.5;
  • float 是单精度小数,通常有约 6~7 位有效数字。
  • double 是双精度小数,通常有约 15~16 位有效数字。
  • 信奥入门阶段遇到小数,通常直接使用 double,因为它更精确。

这里的“精度”是通常能可靠保留的有效数字位数,不是小数点后固定有多少位。float 和 double 都可能存在很小的表示误差。

5. 字符:char

char 只能保存一个字符,必须使用英文单引号:

char ch = 'A';
char op = '+';
char ch = 'A';       // 一个字符
cout << "A";         // 一个字符串

记忆: 一个字符用单引号,多个字符组成的文字用双引号。

6. 布尔值:bool

bool 只有两个值:

  • true:真,是;
  • false:假,不是。
bool pass = true;
bool finished = false;

使用 cout 输出时,true 通常显示为 1,false 通常显示为 0。

7. sizeof:查看占用多少字节

C++ 可以使用 sizeof 查看类型或表达式占用多少字节:

cout << sizeof(int) << endl;        // 类型名

int a = 10;
cout << sizeof(a) << endl;          // 变量名

cout << sizeof(12) << endl;         // 数字,12 默认是 int
cout << sizeof(12LL) << endl;       // long long 类型的数字
cout << sizeof(3.14f) << endl;      // float 类型的小数
cout << sizeof(3.14) << endl;       // double 类型的小数

sizeof 查看的是“占用多少字节”,不是数值大小。1 字节等于 8 位,1 位表示一个二进制的 0 或 1。

数据类型 常见大小
int 4 字节
long long 8 字节
float 4 字节
double 8 字节
char 1 字节
bool 1 字节

五、算术运算符

1. 五个基本算术运算符

运算符 含义 示例 结果 适用类型
+ 加法 3 + 4 7 整数、小数
- 减法 10 - 3 7 整数、小数
* 乘法 6 * 7 42 整数、小数
/ 除法 15 / 4 见下文 整数、小数
% 取余 15 % 4 3 只适用于整数

2. 整数除法

两个整数相除,结果仍然是整数,小数部分会直接丢掉,不会四舍五入:

cout << 15 / 4 << endl;      // 输出 3,不是 3.75
cout << 7 / 2 << endl;       // 输出 3,不是 3.5
cout << 1 / 2 << endl;       // 输出 0

如果想得到小数,只要让其中一个数变成小数:

cout << 15.0 / 4 << endl;    // 输出 3.75
cout << 7 / 2.0 << endl;     // 输出 3.5
cout << 1.0 / 2 << endl;     // 输出 0.5

3. 取余运算 %

% 求的是除法的余数:

cout << 15 % 4 << endl;      // 15 除以 4,余 3
cout << 7 % 2 << endl;       // 7 除以 2,余 1
cout << 10 % 5 << endl;      // 10 除以 5,余 0

重要: % 只能用于整数。3.14 % 2 会编译错误。

(1)取一个数的个位和十位

int n;
cin >> n;

cout << n % 10 << endl;       // 个位
cout << n / 10 % 10 << endl;  // 十位

(2)把秒数转换成时、分、秒

int total;
cin >> total;

int hour = total / 3600;
int rest = total % 3600;
int minute = rest / 60;
int second = rest % 60;

cout << hour << " " << minute << " " << second << endl;

这里使用了整数除法和取余:

小时 = 总秒数 / 3600
剩余秒数 = 总秒数 % 3600
分钟 = 剩余秒数 / 60
秒 = 剩余秒数 % 60

4. 运算顺序

C++ 的运算顺序和数学中很像,只不过多了一个取余%:

  • 先算乘法 *、除法 / 和取余 %;
  • 再算加法 + 和减法 -;
  • 同级运算,自左向右;
  • 有小括号,先算小括号。
cout << 2 + 3 * 4 << endl;       // 输出 14
cout << (2 + 3) * 4 << endl;     // 输出 20
cout << 10 - 2 * 3 << endl;      // 输出 4

拿不准时,主动加括号:

int result = (a + b) * c;

5. 长方形的周长和面积

输入长方形的长和宽,输出周长和面积:

int length, width;
cin >> length >> width;

int perimeter = 2 * (length + width);
int area = length * width;

cout << perimeter << " " << area << endl;

6. 平均分

输入三门课的整数成绩,输出平均分:

int a, b, c;
cin >> a >> b >> c;

double average = (double)(a + b + c) / 3;
cout << average << endl;

这里要注意:如果写成 (a + b + c) / 3,三个数都是整数,结果会进行整数除法。先把总和转换成 double,才能保留小数。

7. 常用的简写运算

写法 等价写法 含义
a += 5; a = a + 5; a 加 5
a -= 2; a = a - 2; a 减 2
a *= 3; a = a * 3; a 乘以 3
a /= 3; a = a / 3; a 除以 3
a %= 3; a = a % 3; a 对 3 取余
a++; a = a + 1; a 加 1
a--; a = a - 1; a 减 1

六、数据类型转换

当不同类型的数据一起运算,或者把一个值放进另一种类型的变量时,C++ 需要把数据从一种类型变成另一种类型,这叫类型转换。

类型转换主要分成两种:

类型 中文名称 谁来完成 是否需要写代码
隐式类型转换 自动类型转换 编译器自动完成 通常不需要额外写
显式类型转换 强制类型转换 程序员主动指定 需要写转换语法

1. 隐式类型转换

(1)混合运算时的自动提升

当整数和小数一起运算时,C++ 通常会把整数自动转换成小数:

cout << 7 / 2 << endl;       // 3:两个 int 做整数除法
cout << 7 / 2.0 << endl;     // 3.5:2.0 是 double,7 自动转成 double
cout << 3 + 0.14 << endl;    // 3.14:3 自动转成 double

入门阶段可以先记住这个帮助理解的顺序:

bool / char → int → long long → float → double

实际转换还会受到数据范围和编译器规则影响,但做基础题时重点掌握 int 和 double 的混合运算即可。

(2)赋值时的自动转换

赋值时,右边的值会转换成左边变量的类型:

double x = 5;       // int 5 自动转成 double 5.0
int a = 3.14;       // double 3.14 转成 int,结果为 3
float f = 3.14;     // double 3.14 转成 float,精度可能降低

如果从范围大、精度高的类型放入范围小、精度低的类型,就可能丢失信息:

int a = 3.99;       // a 是 3,不是 4

小数部分会被直接截掉,不会自动四舍五入。

(3)char 和 bool 参与运算

char ch = 'A';          // 常见编码中 'A' 对应 65
cout << ch + 1 << endl; // 输出 66

bool ok = true;         // true 按 1 参与计算
cout << ok + 10 << endl; // 输出 11

2. 显式类型转换

显式类型转换也叫强制类型转换,意思是程序员主动告诉 C++:“请把这个值按照某种类型来处理”。

本课先掌握两种常见写法:

double x = 3.14;

int a = (int)x;      // C 风格写法
int b = int(x);      // 函数风格写法

cout << a << " " << b << endl;   // 3 3
写法 语法 示例 特点
C 风格 (目标类型)表达式 (int)x 简短,信奥题中很常见
函数风格 目标类型(表达式) int(x) 写法直观

3. 整数除法转换成小数除法

如果想让两个整数相除得到小数,必须在除法发生前先转换:

int a = 7, b = 2;

cout << (double)a / b << endl;    // 3.5
cout << double(a) / b << endl;    // 3.5

注意转换的位置:

cout << (double)(a / b) << endl;  // 3.0:先算 7/2,再转小数
cout << (double)a / b << endl;    // 3.5:先转小数,再做除法

关键区别: (double)(a / b) 是“先除后转”,(double)a / b 是“先转后除”。要保留小数,必须先转再除。

4. 把小数转换成整数

cout << (int)3.14 << endl;       // 3
cout << (int)3.99 << endl;       // 3
cout << int(-3.7) << endl;       // -3

转换为整数时通常是向零截断,也就是直接丢掉小数部分,不是四舍五入,也不是总向下取整。

5. 字面量和类型后缀

代码中直接写出的数字、字符和字符串叫作字面量。字面量可以通过后缀明确指定类型:

写法 类型或含义 说明
12 int 整数常量默认优先按 int 处理
12LL long long LL 明确表示 long long
3.14 double 普通小数默认按 double 处理
3.14f float f 或 F 明确表示 float
'A' char 单引号中的一个字符
"hello" 字符串 双引号中的一段文字
true、false bool 真和假

例如:

int a = 12;
long long b = 12LL;
float c = 3.14f;
double d = 3.14;

当数字可能超过 int 范围时,给整数常量加 LL,可以明确告诉编译器从一开始就按 long long 处理:

long long a = 2000000000LL;
long long b = 2000000000LL;
long long sum = a + b;

七、数据范围与类型选择

写题时,定义变量的类型不是随便选的,要先看题目给出的数据范围,再看计算过程中可能出现的最大值。

1. 不只看输入,还要看中间结果

如果题目保证 a、b 都不超过 21 亿,单个数可以放进 int;但是 a + b 可能超过 int 的最大值,所以求和程序应使用 long long:

long long a, b;
cin >> a >> b;
cout << a + b << endl;

如果只把最终结果强制转换成 long long,但前面的计算已经使用 int 溢出,通常已经来不及补救:

int a = 2000000000, b = 2000000000;
long long ans = (long long)(a + b);  // a+b 先按 int 计算,可能已经溢出

更安全的写法是让计算从一开始就使用 long long:

long long a = 2000000000LL;
long long b = 2000000000LL;
long long ans = a + b;

2. 选择类型的简单原则

题目数据 常用选择
一般范围内的整数,且计算结果也不大 int
输入或中间结果可能超过 21 亿 long long
小数(一般情况,信奥首选,精度约 15~16 位) double
小数(明确要求单精度,或精度要求极低,精度约 6~7 位) float (信奥中极少使用)
一个字符 char
只有真/假、是/否 bool

做题原则: 先看输入范围,再看计算结果可能多大,最后选择能够装下所有中间结果和最终结果的类型。

八、常见错误与注意事项

1. 有编译器提示(error / warning)

编号 错误 关键错误提示(g++ -std=c++11) 后果 改正
E1 变量未定义就使用 error: 'x' was not declared in this scope 编译错误,找不到变量 先定义变量,再使用
E2 变量未赋值就读取 警告(非编译错误):warning: 'x' is used uninitialized in this function [-Wuninitialized] 结果不确定,可能输出随机值 定义时初始化,或先用 cin 输入
E3 变量名以数字开头 error: expected unqualified-id before numeric constant 编译错误 改成字母或下划线开头
E4 变量名使用保留字 error: expected unqualified-id before 'int'(以 int int; 为例) 编译错误 换一个普通名字
E5 同一个名字重复定义 error: redefinition of 'int a' 编译错误 一个作用范围内不要重复定义
E6 大小写写错 error: 'Score' was not declared in this scope score 和 Score 被当成不同变量 统一变量名大小写
E7 字符使用双引号,如 "A" error: invalid conversion from 'const char*' to 'char' [-fpermissive] 这是字符串,不是一个字符 单个字符使用 'A'
E8 cin 使用 << error: no match for 'operator<<' (operand types are 'std::istream' and 'int') 输入方向错误 cin 使用 >>
E9 cout 使用 >> error: no match for 'operator>>' (operand types are 'std::ostream' and 'int') 输出方向错误 cout 使用 <<
E10 对小数使用 % error: invalid operands of types 'double' and 'double' to binary 'operator%' 编译错误 求余只用于整数

2. 无编译器提示(非编译错误)

编号 错误 后果 改正
E11 输入完不按回车 程序可能继续等待输入 最后一个数据输入后按回车
E12 输入顺序和变量顺序不一致 变量得到错误的数据 按 cin 后面的变量顺序输入
E13 7 / 2 以为是 3.5 实际输出 3 使用 7.0 / 2 或 (double)7 / 2
E14 int a = 3.99 以为得到 4 实际得到 3 赋值转换会直接截断
E15 先除法、后转换 小数已经丢失 先转换,再做除法
E16 只看输入范围,不看计算结果范围 a + b 等中间结果可能溢出 让变量和中间结果使用足够大的类型
E17 把 12、12LL、3.14、3.14f 当成完全一样 可能使用错误的类型和精度 记住常用字面量后缀
E18 在线评测中输出多余提示语 可能格式错误 只输出题目要求的内容