2016-04-13 19 views
-2

誰かの名前、場所、所在地などを含むファイルがありますstd :: getline関数を正しく使用するには

ex。 JOHN.SMITH:11:F12

は現在、出力は私がコースの参考のためにコロンを取り除くでしょうどのようにこの

George.Clooney 

Jennifer.Lawrence 

Kevin.Bacon 


15:S13 

15:F15 

15:F15 

のですか?私はそれがこの

15S13

私のコード

struct studentinfo 
{ 
    string name; 
    string classref; 
}; 

void readNumbers(istream &input, char *argv[], int argc) 
{ 

    string program = argv[0]; 
    string text = argv[1]; 
    studentinfo array[10]; 
    string name; 
    int i=0; 

    if(text=="students.txt"){ 
     while(!getline(input, array[i].name, ':').eof()){ 
      input >> array[i].classref; 
      i++; 
    } 

    for(int j=0; j < i; j++){ 
     cout<< array[j].name << endl; 
    } 

    for(int i=0; i < 10; i++){ 
     cout << array[i].classref << endl; 
    }  
} 
+0

本当に使用パターンに依存しますか?極端な例として、ほとんどクエリを実行せず、更新のみを行う場合は、最後に追加するベクトルを使用することがあります。 –

+0

本当に、何を保存したいかによって異なります。永続性や内部ストレージについて質問していますか?あなたのプロジェクトは大きいですか?クエリより頻繁に更新しますか?自然なキーがありますか? –

+0

@Lauren既存の質問を編集して、質問する内容を完全に変更するのではなく、新しい質問をする必要があります。あなたは私の答えを文脈から完全に外しました。あなたはより多くの質問をしてより良い評価を得るので、それもあなたの関心事です。 –

答えて

2

に見えるようにしたいこれは、この質問のいくつかの繰り返しに答えているので、それがされているものと少し調子が悪いに見えるかもしれません上に尋ねた。 「:」文字


問題あなたは、最大読み取りにstd::getlineを使用していることです。その後、オーバーロードされた演算子>>std::stringに使用して、別の読み取りを同じ文字列nameに上書きします。今回は、行末まで読み込みます。

の呼び出しの後で、変数nameにはJohn.Smithが含まれており、input >> name;を実行するとすぐにその値を上書きします。これは基本的にgetlineと同じもので、区切り文字を指定することはできません。文字列nameには11:F12が含まれ、後で表示するために配列にコピーします。

getlineがどのように動作しているのか混乱していたと思いますが、を使用して名前の値を読み取る必要はありませんでした。文字列はすでにnameです。あなたはちょうどラインの残りの部分を読んでそれを捨てる必要がありました。どのように機能するかをよりよく理解するために、std::getlineのオンラインリファレンスを読むことをお勧めします。

問題を解決するには、次のいずれかを実行します。あなたは配列にnameをコピーして値を破棄した後

  1. は、それが行の残りの部分をクリアし、そのように他人のgetline 'または「>>」を実行して、あなたは、あなたのループgetlineに次の名前を読んでコール。これを実現するにはちょっと面倒な方法は、nameを追加する行の後にinput >> name;を移動することです。
  2. 区切り文字なしで行全体を読み取ってから、最初に ':'を見つけて(メンバ関数を使用して)その文字まで部分文字列を取ります(findメンバ関数を使用)。
  3. 名前が&のクラスメンバーを構造体として定義し、両方の値を構造体に読み込みます。この方法で、意図的に両方の値をファイルから読み込みます。あなたがコースストリングを気にしないなら、これは過度なことかもしれません。

多かれ少なかれ私が示唆していることを行うコードです。

#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>を含める必要があります。

+0

ありがとうございました! – Lauren

関連する問題