【问题标题】:C++ read file with multiple delimtersC ++读取具有多个分隔符的文件
【发布时间】:2026-02-06 10:00:01
【问题描述】:

我有以下文本文件。

文本.txt

1, Harry Potter, 1998, UK/trains/wizards/

要求用户输入书名,然后是出版日期,并列出与该书关联的所有关键字。用户可以输入的关键字数量没有限制。此数据将在具有私有成员的类中使用,以便可以更改或删除等。

我想知道如何读取文本文件,该文件将在 1 Harry Potter 1998 和每个关键字(如 UK trains wizards)之间分割每一行。

下面的代码读取文件并根据设置的分隔符将其拆分。有没有办法修改它以与多个分隔符一起使用,或者是为数据的第一位创建一个文件并为 keyowrds 创建另一个文件的简单解决方案?

std::ifstream file("test.txt");
std::string line;
if (file)
{
    std::string token;
    std::stringstream ss;

    while (getline(file, line))
    {
        ss << line;

        while (getline(ss, token, ','))
        {   
            std::cout << token << std::endl;
        }
        ss.clear();
    }
}

【问题讨论】:

    标签: c++ delimiter file-handling


    【解决方案1】:

    不要对逗号分隔的字段使用循环。为关键字使用循环。

    std::string token1 = getline(ss, token1, ','); // 1
    std::string token2 = getline(ss, token2, ','); // "Harry Potter"
    std::string token3 = getline(ss, token3, ','); // 1998
    std::vector<string> keywords;
    std::string word;
    while (getline(ss, word, '/'))
    {
      keywords.push_back(word);
    }
    

    您需要根据逗号分隔符限制提取次数。由于您的示例中只有 3 列,因此实际上不需要循环。

    【讨论】:

      【解决方案2】:

      简单的解决方案是完全按照您在关键字标记上的逗号上进行拆分:

      std::vector parseKeywords(const std::string & keywords)
      {
          std::vector result;
          std::stringstream keywordstrm(token);
          std::string keyword;
          while (getline(keywordstrm, keyword, '/'))
          {
              result.push_back(keyword);
          }
          return result;
      }
      

      【讨论】:

        【解决方案3】:

        您可以扩展通过任意数量字段的 while 循环,并使用内部循环中的第二个分隔符进一步分解每个字段:

        while (getline(file, line)) {
            ss << line;
            while (getline(ss, token, ',')) {   
                std::stringstream ss2(token);   // parse now the field that was read    
        
                while (getline(ss2, tok2, '/'))  // and decompose it again
                   std::cout << tok2 << " + ";
                std::cout << std::endl; 
            }
            ss.clear();
        }
        

        Online demo

        您可以使用向量而不是字符串来存储多值字段。

        【讨论】:

          【解决方案4】:

          在这种情况下使用 strtok

          `std::ifstream file("test.txt");
          std::string line;
          if (file)
          {
              std::string token;
              std::stringstream ss;
          
              while (getline(file, line))
              {
          
                  char * pch;
                  pch = strtok (str.c_str()," ,.-");
                  while (pch != NULL)
                 {
                   std::cout<<pch<<std::endl;
                   pch = strtok (NULL, " ,.-");
                 }
                          ss.clear();
              }
          }`
          

          【讨论】:

          • std::string::c_str 返回const char *strtok 需要 char *,因为它修改了提供的 c 样式字符串。您需要一个 strdup 或类似的在那里将字符串复制到非常量缓冲区中。
          【解决方案5】:

          假设您知道文本文件的确切格式,Thomas Matthews solution 可能更好,但对于您不知道的更一般的情况...您可以尝试此解决方案,它适用于任何一组分隔符它就像 getline 一样工作......

          std::istream& getline2(std::istream& stream, std::string& s, const std::string& delimeters){
              s.clear(); char c;
              while(stream.read(&c, 1)){
                  if(delimeters.find(c) != std::string::npos)
                      break;
                  s += c;
              }
              return stream;
          }
          

          示例用法:

          while (getline2(ss, token, ",/\."))
          {   
              std::cout << token << std::endl;
          }
          

          此处为您的用例的完整代码on Coliru

          【讨论】: