11|單字反轉
相關主題: C++ 基礎速查
只限 C++|CPU 時間上限 1 秒
讀入好幾行文字,把每一行裡的單字順序反過來再輸出。單字本身的內容不變,只是順序顛倒。
「單字」是指連在一起、中間沒有空格的一串字元,例如 hello、C++、!、x=1; 都各算一個單字。單字之間可能隔著一個或好幾個空格,一行的開頭和結尾也可能有空格;輸出時一律只用一個空格分隔單字,開頭和結尾不要有空格。
這一題要練習 C++ 處理字串的基本工具:用 std::getline 一次讀一整行、用 std::istringstream 把一行拆成單字、用 std::vector<std::string> 把單字存起來。用 C 做同一件事要自己開固定大小的字元陣列、用 fgets 讀、再用 strtok 或手動掃描切單字,還得擔心陣列夠不夠大;用 C++ 會簡單很多。
- 好幾行文字,一直讀到輸入結束 (EOF)。至少 1 行,最多 1000 行。
- 每行最多 1000 個字元(不含換行),只會出現可印出的 ASCII 字元(英文、數字、符號、空格),不會有 Tab。
- 可能有空行,或整行都是空格的行。
- 最後一行後面不一定有換行。
輸入有幾行,輸出就有幾行,順序和輸入相同。每一行輸出該行的單字反過來的結果,單字之間用一個空格分隔。
如果某一行是空行或整行都是空格(沒有任何單字),就輸出一個空行。
輸入:
hello world the quick brown foxone
I love C++ !輸出:
world hellofox brown quick theone
! C++ love I空格在上面看不出來,用 · 代表空格再看一次輸入:
hello·world··the·quick···brown·fox··one
···I·love·C++·!- 第 2 行開頭、結尾各有 2 個空格,
quick和brown之間有 3 個空格;輸出時都變成一個空格分隔。 - 第 4 行是空行,第 5 行只有 3 個空格,兩行都輸出空行。
C++和!都只是一般的單字。
C++:
std::getline(std::cin, line)讀一整行到std::string(不含換行)。放在while (...)的條件裡,讀到 EOF 就會停std::istringstream in(line);把一個字串當成輸入來源,之後就能用in >> word一個一個讀單字;>>會自動跳過任意數量的空白std::vector<std::string>:可以一直push_back的字串陣列,不用事先知道有幾個- 範圍 for 迴圈:
for (const std::string& w : words),依序走過每個元素;const &表示只讀、不複製 std::reverse(v.begin(), v.end())(在<algorithm>)可以把整個 vector 倒過來;也可以用索引從最後一個往前走
對照 C:
- C 要先開
char line[1002];這種固定大小的陣列,用fgets讀,讀進來的字串最後會留著'\n' - 切單字要用
strtok(line, " ")(會修改原字串)或自己一個字元一個字元掃描 - 存單字要再開一個二維陣列或指標陣列,還要自己記住有幾個
提示 1:怎麼一直讀到輸入結束?
std::string line;while (std::getline(std::cin, line)) { // 處理 line}在終端機手動測試時,打完所有行之後按 Ctrl+Z 再按 Enter 代表輸入結束。比較方便的做法是直接拿測試檔當輸入(在 E:\C++ 的終端機輸入):
run exercises\2-cpp\11-reverse-words\main.cpp --input exercises\2-cpp\11-reverse-words\tests\01.in提示 2:怎麼把一行拆成單字?
#include <sstream> 之後:
std::istringstream in(line);std::string word;while (in >> word) { // 每次拿到一個單字,連續空格會被自動跳過}空行或全是空格的行,這個迴圈一次都不會執行。
提示 3:怎麼反過來印、而且單字之間只有一個空格?
先把單字都 push_back 進 std::vector<std::string> words,再從最後一個印到第一個(或先 std::reverse)。
處理分隔空格的常見寫法:用一個 bool first = true;,除了第一個單字以外,每個單字前面先印一個空格。不管這一行有沒有單字,最後都要印 '\n',空行才不會不見。