簡體   English   中英

如何在一行中讀取具有多個分隔符的文件

[英]How to read a file with multiple delimiters within a single line

我試圖讀取每行有多個分隔符的文件。 以下是數據

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;
    }
  }
}

但是代碼存在問題,因為它正在跳過第一行。 此外,如果我評論第二個while循環,只有第一行打印,下面是輸出

Ian無法弄清楚代碼出錯的地方

產量

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

為什么是兩個while

你的問題是你永遠重復第二次。 執行第一個while只是為了獲得前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;
}

問題來自你使用std::getline兩次的事實。

在開始時,您進入第一個循環。 第一次調用std::getline返回想你所期待的:第一線,直到 ,分隔符。

然后在嵌套循環中輸入第二個std::getline ,以獲取該行的其余部分。 但事實是,你永遠不會離開第二個循環,直到文件結束。 因此,您通過以下方式讀取所有文件拆分: delimiter。

當第二個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

你可以清楚地看到它直到最后才退出第二個循環。

我建議閱讀整行,不用分隔符, 然后使用量身定制的函數將字符串拆分為令牌。 它會很容易也很干凈。

方案:

#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>

如果要在多個分隔符上拆分字符串,而不必擔心分隔符的順序,可以使用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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM