【C++筆記】一些輸入函數 cin, getline(), cin.get() 等 === [TOC] cin --- 這大家都知道,這是 C++ 的標準輸入物件,屬於 istream 類別。 基本語法不外乎就是透過鍵盤輸入將資料存入某個變數。 ```cpp int a; cin >> a; ``` 那其特性如下: * 以空白(空格、Tab 縮排、換行)為分隔符號。 * 自動忽略前導空白字元(如輸入:`1 2 3 4 5`,每個數字間的空格都會忽略,並依序存入變數) * 無法讀取含有空白字元的字串,如下範例: ```cpp string name; cin >> name; // 輸入 John Doe // name 只會得到 "John" ``` 這是 cin 的缺點,要讀入完整的字串,則需要 `getline()`。 printf() / scanf() --- 雖然本文講輸入函數,但想說既然 C 有的東西,C++ 當然也繼承下去,就順便講一講 printf()。 相對於 cin / cout 來說,printf() / scanf() 的執行效率遠高於前者,因為在底層進行實作,接近硬體層面。 其基本語法如下: `printf("字串格式化符號", 值1, 值2, ...)` `scanf("字串格式化符號", &值1, &值2, ...)` 使用前先引入 `<cstdio>`,或是 `<stdio.h>`,或是也可以不用寫。 ```cpp= #include <cstdio> using namespace std; int main(){ int a; scanf("%d", &a); printf("%d", a); return 0; } ``` Output(輸入 2 輸出 2): ``` 2 2 ``` 字串結合格式化符號: ```cpp= #include <cstdio> using namespace std; int main(){ int a; printf("請輸入:"); scanf("%d", &a); printf("你所輸入的是:%d", a); return 0; } ``` Output: ``` 請輸入:2 你所輸入的是:2 ``` `&` 取出變數 a 的記憶體位址,用於告訴 scanf 要將輸入的東西存到哪裡。 以下是一些常用的格式化符號: | 類型 | 符號 | 說明 | | ----- | ---------- | ------------ | | 整數 | `%d` | 10 進位整數 | | | `%x`, `%X` | 16 進位(小寫/大寫) | | | `%o` | 8 進位 | | 字元 | `%c` | 單一字元 | | 字串 | `%s` | 字元陣列 | | 浮點數 | `%f` | 十進位浮點數 | | | `%.nf` | 保留 n 位小數 | | | `%e`, `%E` | 科學記號表示法 | | 指標 | `%p` | 地址指標輸出 | | 百分比符號 | `%%` | 輸出 `%` 本身 | 浮點數的格式化符號 `%.nf` 是比較常在考試中被拿出來講的東西: ```cpp= #include <cstdio> using namespace std; int main(){ float a = 0.12345; printf("%.2f", a); // 0.12345 只取小數點後兩位, 輸出即 0.12 return 0; } ``` Output: ``` 0.12 ``` 經典題: ```cpp= #include <cstdio> using namespace std; int main(){ float a = 0.12345; // %2.f 代表這個字串的總字元最小寬度為 2 printf("%2.f", a); // %2.f, 點後面沒東西預設就是 %2.0f return 0; } ``` Output: ``` 0 ``` 輸出的 0 多了一個空格,因為 `%2.f` 的關係,要求總字元寬度至少要為 2,阿 0 只有一個字元,所以左邊補一個空格,就醬。 getline() --- 讀取整行字串,包含空格,直到遇到換行字元(\n)。 語法: ```cpp string line; getline(cin, line); ``` 若 getline 前面有 cin 的話,如下: ```cpp string a; cin >> a; getline(cin, line); ``` 需要加上 `cin.ignore()`,去把前面 cin 留下的 `\n` 給忽略掉,避免影響到後續 `getline()` 讀取。 ```cpp string a; cin >> a; cin.ignore(); getline(cin, line); ``` cin.get() --- 讀取單一字元,含空格與 `'\n'`。 語法: ```cpp char ch; cin.get(ch); ``` 特性: * 不會忽略空白與換行,為 cin 的延伸版本。 * 也可寫成:`char ch = cin.get();` 限制輸入字元: ```cpp= char str[20]; cin.get(str, 20); // 讀取最多 19 字元,含空格 cout << str << endl; ``` 在後面多加一個整數參數,即可限制要輸入多少個字元,從輸入中讀取最多 `size-1` 個字元(含空格),直到讀到 `\n` 或到達上限為止。 另外很重要的就是他會在結尾加上 `'\0'` 字元,表示字串到此結束。 也不會讀取 `\n`,會留在輸入緩衝區,所以若要繼續用 getline() 或 cin.get() 的時候,就用 `cin.ignore()` 清除。 如果緩衝區已經滿了,會發生 failbit,可用 `cin.clear()` 清除。 另外 `cin.get()` 也可自訂結束字元(delimiter),預設為 `\n`。若遇到指定的結束字元會停止讀取,但不會把 delimiter 取走。 具體語法如下: ``` cin.get(char *buffer, int size, char delim) ``` 其實就是多加第三個參數,然後指定結束字元。 cin.getline() --- 這是用來填入字元陣列(C-style string)的方法。 語法: ```cpp= char buf[100]; cin.getline(buf, 100); ``` 特性: * 和 `getline()` 相同,可讀取整行(含空格),但需指定緩衝區的大小。 * 結尾自動加上 `\0` 表示字串結束,這是 C 語言的作法。 總結 --- ### 1. cin - 標準輸入物件,屬於 `istream` 類別。 - **特性**: - 以空白(空格、Tab 縮排、換行)為分隔符號。 - 自動忽略前導空白。 - **無法讀取含空格的字串**,例如輸入 "John Doe" 只會取得 "John"。 - 適用於基本輸入(整數、字串無空白等情形)。 --- ### 2. getline() - **用於讀取整行字串**(包含空格),直到 `\n` 為止。 - 若前面有用 `cin`,需加 `cin.ignore()` 清除殘留的 `\n`。 - 語法:`getline(cin, line);` - line 是字串型態 --- ### 3. cin.get() - 可讀取單一字元,**含空白與換行**。 - 語法有兩種: - `cin.get(ch);` - `char ch = cin.get();` - 也可限制讀取字元數:`cin.get(buffer, size);`,適用於 C-style 字串。 - 可設定自訂的結束字元(delimiter),為 cin.get() 的第三個參數。 --- ### 4. cin.getline() - 用於 **C-style 字元陣列** 的整行輸入。 - 語法:`cin.getline(buf, size);` - 功能與 `getline()` 類似,但需指定緩衝區大小。 - 自動在結尾加上 `\0` 字元。 --- ### 5. scanf() / printf()(C 語言) - 執行效率較高,底層更貼近硬體。 - 格式化控制更細緻,如 `%d`、`%f`、`%.2f` 等。 - 使用需引入 `<cstdio>`、`<stdio.h>`,也可以不用加。 - 別忘了用 scanf() 時,要存入的變數都要在前面加上 `&` 取址運算子。 --- ### 結語 - 各輸入方式適用場景不同: - `cin`:單一基本型態。 - `getline()`:讀取整行含空白的 `string`。 - `cin.get()` / `cin.getline()`:操作細緻、支援 C-style 字元陣列。 - `scanf()`:效率高、格式化明確,但較不安全(如緩衝區溢位問題)。 參考資料 --- [C++中cin、cin.get()、cin.getline()、getline()、gets()等函数的用法 - flatfoosie - 博客园](https://www.cnblogs.com/flatfoosie/archive/2010/12/22/1914055.html) [cin get() in C++ with Examples | geeksforgeeks](https://www.geeksforgeeks.org/cin-get-in-c-with-examples/) [printf 與 scanf](https://openhome.cc/Gossip/CGossip/PrintfScanf.html) [如何在 C++ 中使用 scanf() & printf()_c++scanf函数-CSDN博客](https://blog.csdn.net/bjxqmy/article/details/98251253)