に見えるようにしたいこれは、この質問のいくつかの繰り返しに答えているので、それがされているものと少し調子が悪いに見えるかもしれません上に尋ねた。 「:」文字
問題あなたは、最大読み取りにstd::getline
を使用していることです。その後、オーバーロードされた演算子>>
をstd::string
に使用して、別の読み取りを同じ文字列name
に上書きします。今回は、行末まで読み込みます。
の呼び出しの後で、変数name
にはJohn.Smith
が含まれており、input >> name;
を実行するとすぐにその値を上書きします。これは基本的にgetline
と同じもので、区切り文字を指定することはできません。文字列name
には11:F12
が含まれ、後で表示するために配列にコピーします。
getline
がどのように動作しているのか混乱していたと思いますが、を使用して名前の値を読み取る必要はありませんでした。文字列はすでにname
です。あなたはちょうどラインの残りの部分を読んでそれを捨てる必要がありました。どのように機能するかをよりよく理解するために、std::getline
のオンラインリファレンスを読むことをお勧めします。
問題を解決するには、次のいずれかを実行します。あなたは配列にname
をコピーして値を破棄した後
- は、それが行の残りの部分をクリアし、そのように他人のgetline 'または「>>」を実行して、あなたは、あなたのループ
getline
に次の名前を読んでコール。これを実現するにはちょっと面倒な方法は、name
を追加する行の後にinput >> name;
を移動することです。
- 区切り文字なしで行全体を読み取ってから、最初に ':'を見つけて(メンバ関数を使用して)その文字まで部分文字列を取ります(
find
メンバ関数を使用)。
- 名前が&のクラスメンバーを構造体として定義し、両方の値を構造体に読み込みます。この方法で、意図的に両方の値をファイルから読み込みます。あなたがコースストリングを気にしないなら、これは過度なことかもしれません。
多かれ少なかれ私が示唆していることを行うコードです。
#include<fstream>
#include<iostream>
#include<string>
using namespace std;
void readNumbers(istream &input)
{
string array[10];
string name;
string garbage;
int i=0;
while(getline(input, name, ':'))
{
array[i]=name;
i++;
input >> garbage;
}
for(int i=0; i<10; i++) cout<< array[i] << '\n';
}
void readNumbers2(istream &input)
{
string array[10];
string ln;
int i=0;
while(getline(input, ln))
{
size_t colpos = ln.find(':');
if(colpos != string::npos)
{
array[i]=ln.substr(0, colpos);
i++;
}
}
for(int i=0; i<10; i++) cout<< array[i] << '\n';
}
struct studentinfo
{
string name;
string classref;
};
void readNumbers3(istream &input)
{
studentinfo array[10];
string name;
int i=0;
while(getline(input, array[i].name, ':'))
{
input >> array[i].classref;
i++;
}
for(int j=0; j < i; j++)
cout<< "name=" << array[j].name << '\n';
}
int main()
{
std::ifstream f("students.txt");
readNumbers(f);
}
もちろん、このDOEは、そのようなファイルまたは配列をオーバーランで空行としてエッジケースを扱うないが、それはstd::getline
の使用方法を示します。また、std::vector
またはstd::array
を参照して、文字列を保持し、イテレータまたは範囲ベースのループを使用して値を出力することをお勧めします。
文字列からコロンを削除するには、次の方法を使用します。 find
を使用して、コロン文字インデックスと、その位置の文字を削除するためのstring::erase
の1つのイテレータオーバーロードを検索します。
void charerase()
{
std::string s("15:F15");
std::cout << s << '\n';
size_t cpos = s.find(':');
if(cpos != std::string::npos)
{
s.erase(s.begin() + cpos);
}
std::cout << s << '\n';
}
この場合、ヘッダ<iterator>
を含める必要があります。
本当に使用パターンに依存しますか?極端な例として、ほとんどクエリを実行せず、更新のみを行う場合は、最後に追加するベクトルを使用することがあります。 –
本当に、何を保存したいかによって異なります。永続性や内部ストレージについて質問していますか?あなたのプロジェクトは大きいですか?クエリより頻繁に更新しますか?自然なキーがありますか? –
@Lauren既存の質問を編集して、質問する内容を完全に変更するのではなく、新しい質問をする必要があります。あなたは私の答えを文脈から完全に外しました。あなたはより多くの質問をしてより良い評価を得るので、それもあなたの関心事です。 –