C++でstd::getline()を使う方法は?
この記事では、C++の関数std::getline()の使用方法について見ていきます。これは、入力ストリームから文字を読み取りたい場合に非常に便利な関数です。
この使い方を正しく理解するために、具体的な例を使って探求しましょう。
C++におけるstd::getline()の基本的な構文。
この関数は入力ストリームから文字を読み取り、文字列に追加します。
ヘッダファイルをインポートする必要があります。なぜなら、getline()はこのファイルの一部だからです。
テンプレート引数を持つが、出力は文字列に書き込まれるため、私たちは文字列入力に焦点を当てます。
istream& getline(istream& input_stream, string& output, char delim);
これが言っていることは、getline()が入力ストリームを受け取り、それを出力に書き込むということです。区切り文字は任意にdelimを指定することができます。
ほとんどの場合、これは同じ入力ストリームへの参照を返しますが、実際にはこのハンドルは必要ありません。
入力ストリームからstd::getline()を使用して読み込む。
基本の構文を知ったことだから、std::cin(標準入力ストリーム)から文字列を入力しましょう。
#include <iostream>
#include <string>
int main() {
// Define a name (String)
std::string name;
std::cout << "Enter the name: ";
// Get the input from std::cin and store into name
std::getline(std::cin, name);
std::cout << "Hello " << name << "!\n";
return 0;
}
出力
Enter the name: JournalDev
Hello JournalDev!
確かに、std::cinからの入力を問題なく取得することができました!
では、別の例を見てみましょう。次の内容を含むファイルinput.txtがあるとします。
$ cat input.txt
Hello from JournalDev
Second Line of file
Last line
では、今ファイルを行ごとに読み込み、それらを文字列のベクターに格納しましょう!
入力ストリームがEOFに到達するまで、std::getline(file)を使って読み込みを続けることが、基本的なロジックとなります。
この形式を使えば、簡単にこれを書くことができます。
std::ifstream infile("input.txt");
// Temporary buffer
std::string temp;
// Get the input from the input file until EOF
while (std::getline(infile, temp)) {
// Add to the list of output strings
outputs.push_back(temp);
}
以下に完全なコードが示されています。
#include <iostream>
#include <string>
#include <vector> // For std::vector
#include <fstream> // For std::ifstream and std::ofstream
int main() {
// Store the contents into a vector of strings
std::vector<std::string> outputs;
std::cout << "Reading from input.txt....\n";
// Create the file object (input)
std::ifstream infile("input.txt");
// Temporary buffer
std::string temp;
// Get the input from the input file until EOF
while (std::getline(infile, temp)) {
// Add to the list of output strings
outputs.push_back(temp);
}
// Use a range-based for loop to iterate through the output vector
for (const auto& i : outputs)
std::cout << i << std::endl;
return 0;
}
出力する。
Reading from input.txt....
Hello from JournalDev
Second Line of file
Last line
C++でstd::getline()を使って入力をデリミタで分割する
デリミタ文字に基づいて、getline関数で入力を分割するために、delim引数を使うこともできます。
デフォルトでは、区切り文字は改行(\n)です。getline()を他の文字に基づいて入力を分割するように変更することもできます。
上記の例で区切り文字をスペース’ ‘に設定して、何が起こるか見てみましょう!
#include <iostream>
#include <string>
#include <vector> // For std::vector
#include <fstream> // For std::ifstream and std::ofstream
int main() {
// Store the contents into a vector of strings
std::vector<std::string> outputs;
std::cout << "Reading from input.txt....\n";
// Create the file object (input)
std::ifstream infile("input.txt");
// Temporary buffer
std::string temp;
// Get the input from the input file until EOF
while (std::getline(infile, temp, ' ')) {
// Add to the list of output strings
outputs.push_back(temp);
}
// Use a range-based for loop to iterate through the output vector
for (const auto& i : outputs)
std::cout << i << std::endl;
return 0;
}
出力(しゅつりょく)
Reading from input.txt....
Hello
from
JournalDev
Second
Line
of
file
Last
line
実際に、スペースで区切られた文字列を持っていますね!
std::getline() を使用する際の潜在的な問題点
std::getline()は非常に便利な関数ですが、std::cinなどの入力ストリームと一緒に使用する際には問題が発生する可能性があります。
- std::getline() does not ignore any leading white-space / newline characters.
これにより、getline()の直前にstd::cin >> var;を呼び出すと、入力変数を読み取った後でも入力ストリームに改行がまだ残っています。
ですので、cinの直後にgetline()を呼び出すと、入力ストリームの最初の文字が改行文字になるため、改行文字が返されます。
これを避けるためには、単純にダミーのstd::getline()を追加して、この改行文字を消費するだけです!
下記のプログラムは、getline()の直前にcinを使用する際の問題を示しています。
#include <iostream>
#include <string>
int main() {
// Define a name (String)
std::string name;
int id;
std::cout << "Enter the id: ";
std::cin >> id;
std::cout << "Enter the Name: ";
// Notice std::cin was the last input call!
std::getline(std::cin, name);
std::cout << "Id: " << id << std::endl;
std::cout << "Name: " << name << "\n";
return 0;
}
出力
Enter the id: 10
Enter the Name: Id: 10
Name:
名前を入力できなかったことに気づいてください!入力ストリームに改行があったため、それを取り込み、区切り文字として認識したため、読み取りが停止しました。
実際のstd::getline()の前に、ダミーのstd::getline()呼び出しを追加しましょう。
#include <iostream>
#include <string>
int main() {
// Define a name (String)
std::string name;
int id;
std::cout << "Enter the id: ";
std::cin >> id;
std::cout << "Enter the Name: ";
// Add a dummy getline() call
std::getline(std::cin, name);
// Notice std::cin was the last input call!
std::getline(std::cin, name);
std::cout << "Id: " << id << std::endl;
std::cout << "Name: " << name << "\n";
return 0;
}
出力
Enter the id: 10
Enter the Name: JournalDev
Id: 10
Name: JournalDev
ついに私たちはバグを修正しました!これで、std::getline()を盲目的に使用する前に少し考えることを期待します。
残念ながら、C++で入力を行うための洗練された方法はありませんので、手元にあるもので頑張らなければなりません!
結論
結論はひとつだけ必要です。
この記事では、C++でstd::getline()を使用する方法について学びました。また、この関数のパワーや注意点を示すいくつかの例も紹介しました。
参考文献
- cppreference.com page std::getline()
- StackOverflow Question on using std::getline()