一. 口算练习题
## 题目描述
王老师正在教简单算术运算。细心的王老师收集了 i 道学生经常做错的口算题,并且想整理编写成一份练习。 编排这些题目是一件繁琐的事情,为此他想用计算机程序来提高工作效率。王老师希望尽量减少输入的工作量,比如 5+8 的算式最好只要输入 5 和 8,输出的结果要尽量详细以方便后期排版的使用,比如对于上述输入进行处理后输出 5+8=13以及该算式的总长度 6。王老师把这个光荣的任务交给你,请你帮他编程实现以上功能。
## 输入格式
第一行一个整数 i。
接着的 i行为需要输入的算式,每行可能有三个数据或两个数据。
若该行为三个数据则第一个数据表示运算类型,a 表示加法运算, b 表示减法运算, c 表示乘法运算,接着的两个数据表示参加运算的运算数。
若该行为两个数据,则表示本题的运算类型与上一题的运算类型相同,而这两个数据为运算数。
## 输出格式
输出 i 行。对于每个输入的算式,输出完整的运算式及结果,第二行输出该运算式的总长度。
## 样例 #1
### 样例输入 #1
4
a 64 46
275 125
c 11 99
b 46 64
### 样例输出 #1
64+46=110
9
275+125=400
11
11*99=1089
10
46-64=-18
9
代码如下
#include <iostream>
#include <string>
using namespace std;
int main()
{int n = 0;cin >> n;string op;string num1;string num2;string last;int ret = 0;while (n--){string ans;cin >> op;if (op == "a" || op == "b" || op == "c"){cin >> num1 >> num2;int n1 = stoi(num1);int n2 = stoi(num2);ans += num1;if (op == "a")ret = n1 + n2, ans += "+";else if (op == "b")ret = n1 - n2, ans += "-";elseret = n1 * n2, ans += "*";last = op;}else{num1 = op;cin >> num2;int n1 = stoi(num1);int n2 = stoi(num2);ans += num1;if (last == "a")ret = n1 + n2, ans += "+";else if (last == "b")ret = n1 - n2, ans += "-";elseret = n1 * n2, ans += "*";}ans += (num2 + "=" + to_string(ret));cout << ans << endl;cout << ans.size() << endl;}return 0;
}
代码解读(简略重点):
①利用string定义字符串(需要头文件#include<string>)。
②通过stoi把n1 n2转换为int 型,ans用来计算最终字符串总长度。
③根据题目规则,通过last来“记忆”上一次运算结果。
④to_string()用来把整型转化成字符串string类型。
代码解读(详细):
### **代码逐段解析**
#### 1. **变量定义**
int n = 0;
cin >> n; // 输入操作次数
string op, num1, num2, last; // 操作符、操作数、上一次操作符
int ret = 0; // 运算结果
- `n` 表示后续需要处理的操作次数。
- `op` 可以是操作符(`a`/`b`/`c`)或第一个操作数(数字)。
- `last` 记录上一次的操作符,用于省略操作符时的运算。
#### 2. **主循环**
while (n--) {string ans; // 当前生成的表达式字符串cin >> op; // 读取操作符或第一个操作数
- 循环执行 `n` 次,处理每条输入。
#### 3. **分支处理**
##### **情况 1:操作符为 `a`/`b`/`c`**
if (op == "a" || op == "b" || op == "c") {cin >> num1 >> num2; // 读取两个操作数int n1 = stoi(num1), n2 = stoi(num2);ans += num1; // 拼接第一个操作数到表达式// 根据操作符计算结果,并记录操作符到表达式if (op == "a") ret = n1 + n2, ans += "+";else if (op == "b") ret = n1 - n2, ans += "-";else ret = n1 * n2, ans += "*";last = op; // 更新上一次操作符
}
- 明确的操作符(`a`/`b`/`c`)触发对应的加、减、乘法。
- 更新 `last` 以便后续省略操作符时使用。##### **情况 2:操作符为数字(省略操作符)**
else {num1 = op; // 当前输入的第一个部分是数字(num1)cin >> num2; // 读取第二个操作数int n1 = stoi(num1), n2 = stoi(num2);ans += num1; // 拼接第一个操作数到表达式// 根据上一次操作符计算结果if (last == "a") ret = n1 + n2, ans += "+";else if (last == "b") ret = n1 - n2, ans += "-";else ret = n1 * n2, ans += "*"; // 默认乘法(若 last 未初始化)
}
- 输入的第一个部分为数字时,沿用 `last` 中的操作符。
- **潜在问题**:若首次输入就省略操作符,`last` 未初始化会导致默认使用乘法。
#### 4. **生成结果字符串**
ans += (num2 + "=" + to_string(ret)); // 拼接第二个操作数和结果
cout << ans << endl; // 输出表达式
cout << ans.size() << endl; // 输出表达式长度
- 最终生成完整表达式(如 `3+5=8`),并输出其长度。
### **示例输入输出**
#### **输入**
```plaintext
3
a 1 2
b 3 4
5 6
```
#### **输出**
```plaintext
1+2=3
7
3-4=-1
8
5-6=-1
8
```
#### **解释**
1. 第一次输入 `a 1 2`:执行加法,结果为 `3`,表达式长度 7。
2. 第二次输入 `b 3 4`:执行减法,结果为 `-1`,表达式长度 8。
3. 第三次输入 `5 6`:沿用上一次操作符 `b`(减法),结果为 `-1`,表达式长度 8。
通过这段代码,可以学习到字符串拼接、条件分支和输入流的基本操作。
二. 小乐乐改数字
题目描述:
小乐乐喜欢数字,尤其喜欢0和1。他现在得到了一个数,想把每位的数变成0或1。如果某一位是奇数,就把它变成1,如果是偶数,那么就把它变成0。请你回答他最后得到的数是多少。
输入描述:
输入包含一个整数n (0 ≤ n ≤ 109)
输出描述:
输出一个整数,即小乐乐修改后得到的数字。
示例1
输入:
222222
复制
输出:
0
示例2
输入:
123
输出:
101
代码(1):当做整数读取
#include <iostream>
#include <cmath>
using namespace std;
int main()
{int n;cin >> n;int ret = 0;int i = 0; // 标记⼀下此时处理到多少位 while (n){if (n % 10 % 2 == 1) // 如果这⼀位是奇数 {ret += pow(10, i); // pow(a, b) 求 a的b次⽅ }n /= 10; // 把最后⼀位⼲掉 i++; // 去判断下⼀位 }cout << ret << endl;return 0;
}
代码(2):当做字符串处理
#include <iostream>
#include <string>
using namespace std;
int main()
{string s;cin >> s;for (int i = 0; i < s.size(); i++) // 数字字符与对应的数的奇偶⼀致 {if (s[i] % 2){s[i] = '1';}else{s[i] = '0';}}cout << stoi(s) << endl; // 转换成数字输出 return 0;
}
代码解读(简略详细):
①两段代码均可以实现题目要求,第一个代码是通过输入整数来实现,是比较好像常规的一个做法,只是在某些方面注意一下权重问题。
②第二段代码把输入的看成字符串最终转化成整型,更加简单,但是思路巧妙。
代码解读(详细)(第一段):
#include <iostream>
#include <cmath>
using namespace std;
#include <iostream>
:包含标准输入输出流库,使得程序可以使用cin
进行输入操作,使用cout
进行输出操作。#include <cmath>
:包含数学库,该库提供了许多数学函数,在这段代码中使用了pow
函数。using namespace std;
:使用标准命名空间,这样在使用标准库中的类和函数时就不需要加上std::
前缀。
int main()
{int n;cin >> n;int ret = 0;int i = 0; // 标记⼀下此时处理到多少位
int n;
:声明一个整型变量n
,用于存储用户输入的整数。cin >> n;
:从标准输入读取一个整数,并将其赋值给变量n
。int ret = 0;
:声明一个整型变量ret
,并初始化为 0,用于存储最终提取奇数位数字后组成的新整数。int i = 0;
:声明一个整型变量i
,并初始化为 0,用于标记当前处理到输入整数的第几位。
while (n)
{if (n % 10 % 2 == 1) // 如果这⼀位是奇数 {ret += pow(10, i); // pow(a, b) 求 a的b次⽅ }n /= 10; // 把最后⼀位⼲掉 i++; // 去判断下⼀位
}
while (n)
:当n
不为 0 时,继续循环。这是因为在不断将n
除以 10 的过程中,最终n
会变为 0,表示已经处理完输入整数的所有位。if (n % 10 % 2 == 1)
:n % 10
用于获取n
的最后一位数字,然后再对 2 取余,如果结果为 1,则说明该数字是奇数。ret += pow(10, i);
:如果当前位是奇数,则将10
的i
次幂累加到ret
中。这里i
表示当前位的权重,例如,个位的权重是10^0
,十位的权重是10^1
,以此类推。pow(10, i)
函数用于计算10
的i
次幂。n /= 10;
:将n
除以 10,相当于去掉n
的最后一位数字。例如,若n
为 123,执行n /= 10
后,n
变为 12。i++;
:将i
的值加 1,表示处理下一位数字。
cout << ret << endl;
return 0;
}
cout << ret << endl;
:将最终得到的新整数ret
输出到标准输出,并换行。return 0;
:表示程序正常结束,返回值 0 通常表示程序执行成功。
代码解读(详细)(第二段):
#include <iostream>
#include <string>
using namespace std;
#include <iostream>
:引入标准输入输出流库,这样程序就能使用cin
进行输入操作,使用cout
进行输出操作。#include <string>
:引入字符串处理库,使得程序可以使用std::string
类型来处理字符串。using namespace std;
:使用标准命名空间,这样在使用标准库中的类和函数时就无需加上std::
前缀。
string s;
cin >> s;
string s;
:声明一个std::string
类型的变量s
,用于存储用户输入的字符串。cin >> s;
:从标准输入读取一个字符串,并将其存储到变量s
中。这里假设用户输入的字符串是由数字字符组成的。
for (int i = 0; i < s.size(); i++) // 数字字符与对应的数的奇偶⼀致
{if (s[i] % 2){s[i] = '1';}else{s[i] = '0';}
}
for (int i = 0; i < s.size(); i++)
:使用for
循环遍历字符串s
中的每个字符。s.size()
函数返回字符串s
的长度。if (s[i] % 2)
:在 C++ 中,字符类型本质上是整数类型,字符'0'
到'9'
对应着连续的 ASCII 码值。因此,s[i] % 2
实际上是判断当前字符对应的 ASCII 码值的奇偶性。由于数字字符的 ASCII 码值与其表示的数值的奇偶性是一致的,所以这里可以直接用字符的 ASCII 码值对 2 取余来判断该数字字符表示的数值是奇数还是偶数。如果余数为 1(即if
条件为真),则说明该数字字符表示的数值是奇数。s[i] = '1';
:如果当前数字字符表示的数值是奇数,则将该字符替换为'1'
。s[i] = '0';
:如果当前数字字符表示的数值是偶数,则将该字符替换为'0'
。
cout << stoi(s) << endl; // 转换成数字输出
return 0;
stoi(s)
:stoi
是 C++ 标准库中的一个函数,用于将字符串转换为整数。这里将处理后的字符串s
转换为整数。cout << stoi(s) << endl;
:将转换后的整数输出到标准输出,并换行。return 0;
:表示程序正常结束,返回值 0 通常表示程序执行成功。