一. 口算練習題
## 題目描述
王老師正在教簡單算術運算。細心的王老師收集了 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 通常表示程序執行成功。