2016-09-05 8 views
3

1行に複数の区切り文字を持つファイルを読み込もうとしています。以下 はデータ1行に複数の区切り文字を含むファイルを読む方法

2,22:11 
3,33:11 
4,44:11 
5,55:11 
6,66:11 
7,77:11 
8,88:11 
9,99:11 
10,00:11 
11,011:11 
12,022:11 
13,033:11 
14,044:11 
15,055:11 
16,066:11 
17,077:11 
18,088:11 
19,099:11 

、コードはここ

を下回っているが、私はラインとコロンを取得するために、区切り文字としてカンマで最初の行を読みしようとしています。

#include <fstream> 
#include <iostream> 
#include <string> 

int main() { 
    std::string line; 
    std::string token; 
    std::ifstream infile; 

    infile.open("./data.txt"); 
    while (std::getline(infile, line,',')) { 
    std::cout << line << std::endl; 
    while(getline(infile, token, ':')) 
    { 
     std::cout << " : " << token; 
    } 
    } 
} 

ただし、最初の行をスキップしているため、コードに問題があります。私はループ間に、第2のコメント場合 はまた、最初の行のみが印刷され、以下の正確コードが間違っている

出力

2 
: 22 : 11 
3,33 : 11 
4,44 : 11 
5,55 : 11 
6,66 : 11 
7,77 : 11 
8,88 : 11 
9,99 : 11 
10,00 : 11 
11,011 : 11 
12,022 : 11 
13,033 : 11 
14,044 : 11 
15,055 : 11 
16,066 : 11 
17,077 : 11 
18,088 : 11 
19,099 : 11 
を把握することができませんでし出力

イアンで取得されます

+0

を使用することができ、私は私の説明を更新しました:次のようにコンパイル

ソリューションで。私はそれが良いフィット感だと思う。解決に深く没する時間をかけてください。できるだけねじって頭を包みます。 –

+0

デバッガはあなたの親友です –

答えて

2

なぜ2つwhile

あなたの問題は、永遠に2番目を繰り返すことです。最初のwhileは、最初に2を取得するためにのみ実行され、2番目のwhileは、ファイルの最後まで実行されます。

すべてを単一のwhileで行うことができます。

#include <fstream> 
#include <iostream> 

using namespace std; 

int main() { 
std::string line; 
std::string token; 
std::string num; 
ifstream infile; 
infile.open("a.txt"); 
    while ( getline(infile, line,',') 
     && getline(infile, token, ':') 
     && getline(infile, num)) 
    cout << line << ',' << token << ':' << num << endl; 
} 
+0

最初のwhileが処理された後でtokenという名前の変数に部分文字列があるとしますか?例:22:11、カンマまで文字列を削除しますか?説明してください。 – user2256825

+0

':'で区切られたものは可変長リストです。それは二倍の時間を説明するでしょう。本当の問題は改行です。 –

2

問題のようなものは、あなたが二回std::getlineを使用しているという事実から来ています。

最初に最初のループを入力します。 std::getlineへの最初の呼び出しは、最初の行が,の区切り文字まで期待しています。

次に、ネストされたループ内に2番目のstd::getlineを入力して、残りの行を取得します。しかし、問題は、ファイルの最後まで2番目のループを離れることは決してありません。だから、すべてのファイル:区切りで分割して読んでいます。

ファイルの最後まで2番目のstd:getlineが終了すると、ネストされたループが残ります。

すでにすべてのファイルを読み込んでいるため、読み込みには何も残っておらず、最初のループは直接終了します。ここで

あなたは文脈を理解するのに役立ついくつかのデバッグです:

#include <fstream> 
#include <iostream> 
#include <string> 

int main() { 
    std::string line; 
    std::string token; 
    std::ifstream infile; 

    infile.open("./data.txt"); 
    while (std::getline(infile, line, ',')) { 
    std::cout << "First loop : " << line << std::endl; 
    while(getline(infile, token, ':')) 
    { 
     std::cout << "Inner loop : " << token << std::endl; 
    } 
    } 
} 

印刷される最初の行です:

First loop : 2 
Inner loop : 22 
Inner loop : 11 
3,33 
Inner loop : 11 
4,44 

あなたは明確にそれをするまで、2番目のループを終了していない見ることができます終わり。

デリミタを気にせずに行全体を読むことをお勧めします。次には、tailor made関数を使用して文字列をトークンに分割しました。それは簡単で非常にきれいです。

ソリューション:

#include <fstream> 
#include <list> 
#include <iostream> 
#include <string> 

struct line_content { 
    std::string line_number; 
    std::string token; 
    std::string value; 
}; 

struct line_content tokenize_line(const std::string& line) 
{ 
    line_content l; 

    auto comma_pos = line.find(','); 
    l.line_number = line.substr(0, comma_pos); 

    auto point_pos = line.find(':'); 
    l.token = line.substr(comma_pos + 1, point_pos - comma_pos); 

    l.value = line.substr(point_pos + 1); 

    return l; 
} 

void print_tokens(const std::list<line_content>& tokens) 
{ 
    for (const auto& line: tokens) { 
    std::cout << "Line number : " << line.line_number << std::endl; 
    std::cout << "Token : " << line.token << std::endl; 
    std::cout << "Value : " << line.value << std::endl; 
    } 
} 

int main() { 
    std::string line; 
    std::ifstream infile; 

    std::list<line_content> tokens; 

    infile.open("./data.txt"); 
    while (std::getline(infile, line)) { 
    tokens.push_back(tokenize_line(line)); 
    } 

    print_tokens(tokens); 

    return 0; 
} 

私はあなたが何を何をすることができるはずだと思います。 g++ -Wall -Wextra --std=c++1y <your c++ file>

+0

こんにちは、ありがとうコードは、これを実行しようとしたと私は文字列を維持し、それで動作するアイデアが好きでしたが、ntそこにライブラリが提供する単純なメカニズムです。 – LearningCpp

+0

ライブラリが提供する簡単なメカニズムはありませんか?_正確には何ですか?文字列分割?または、構造物のために? –

+0

このコードは、すべての行に区切り文字(1,2:3)が区切られている場合に有効です。行内に区切り文字がない場合(1,2など)、行全体を再び値として考慮しています。 ファイル内のエントリには、区切り文字がすべて含まれる場合とそうでない場合があります。助言がありますか ? – LearningCpp

0

あなたが複数の区切り文字で文字列を分割したい場合は、区切り文字の順番を気にすることなく、あなたがstd::string::find_first_of()

#include <fstream> 
#include <iostream> 
#include <streambuf> 
#include <string> 

int 
main() 
{ 
     std::ifstream f("./data.txt"); 
     std::string fstring = std::string(std::istreambuf_iterator<char>(f), 
              std::istreambuf_iterator<char>()); 
     std::size_t next, pos = 0; 
     while((next = fstring.find_first_of(",:\n", pos)) != std::string::npos) 
     { 
       std::cout.write(&fstring[pos], ++next - pos); 
       pos = next; 
     } 

     std::cout << &fstring[pos] << '\n'; 

     return 0; 
} 
関連する問題