【问题标题】:How to split string read from text file into array using c++如何使用c ++将从文本文件中读取的字符串拆分为数组
【发布时间】:2019-05-15 12:22:56
【问题描述】:

我想将文本文件每一行的字符串拆分成一个数组,类似于 python 中的 split() 函数。我想要的语法是一个循环,它将每个拆分字符串输入到数组的下一个索引中, 例如,如果我的字符串: "ab,cd,ef,gh,ij"

,每次遇到逗号时,我都会: 数据文件 >> arr1[i]

我的数组最终会: arr1 = [ab,cd,ef,gh,ij]

下面提供了一个不读取文本文件的模拟代码

#include <iostream>
#include <fstream>
#include <stdio.h>
#include <string.h>
#include <string>
using namespace std;
int main(){
    char str[] = "ab,cd,ef,gh,ij";  //" ex str in place of file contents/fstream sFile;"
    const int NUM = 5;
    string sArr[NUM];//empty array
    char *token = strtok(str, ",");
    for (int i=0; i < NUM; i++)
        while((token!=NULL)){
            ("%s\n", token) >> sArr[i];
            token = strtok(NULL, ",");
         }
    cout >> sArr;

    return 0;
}

【问题讨论】:

标签: c++ split


【解决方案1】:

在 C++ 中,您可以逐行读取文件并直接获取std::string

您将在下面找到我按照您的要求使用split() 提案制作的示例,以及读取文件的main() 示例:

示例

数据文件:

ab,cd,ef,gh
ij,kl,mn

c++ 代码:

#include <fstream>
#include <iostream>
#include <vector>

std::vector<std::string> split(const std::string & s, char c);

int main()
{
    std::string file_path("data.txt"); // I assumed you have that kind of file
    std::ifstream in_s(file_path);

    std::vector <std::vector<std::string>> content;

    if(in_s)
    {
        std::string line;
        std::vector <std::string> vec;
        while(getline(in_s, line))
        {
            for(const std::string & str : split(line, ','))
                vec.push_back(str);
            content.push_back(vec);
            vec.clear();
        }

        in_s.close();
    }
    else
        std::cout << "Could not open: " + file_path << std::endl;

    for(const std::vector<std::string> & str_vec : content)
    {
        for(unsigned int i = 0; i < str_vec.size(); ++i)
            std::cout << str_vec[i] << ((i == str_vec.size()-1) ? ("") : (" : "));
        std::cout << std::endl;
    }

    return 0;
}

std::vector<std::string> split(const std::string & s, char c)
{
    std::vector<std::string> splitted;

    std::string word;
    for(char ch : s)
    {
        if((ch == c) && (!word.empty()))
        {
            splitted.push_back(word);
            word.clear();
        }
        else
            word += ch;
    }
    if(!word.empty())
        splitted.push_back(word);

    return splitted;
}

输出:

ab : cd : ef : gh
ij : kl : mn

我希望它会有所帮助。

【讨论】:

    【解决方案2】:

    所以,有几件事要解决。首先,数组和NUM 是一种限制 - 每当您更改输入字符串时都必须修复 NUM,因此 C++ 提供了 std::vector ,它可以将自身调整为找到的任意数量的字符串。其次,你想调用strtok,直到它返回一次nullptr,你可以用一个循环来做到这一点。对于您的forNUM,您调用strtok 的次数太多了——即使它返回了nullptr。接下来,要将token 放入std::string,您将使用my_string = token; 而不是("%s\n", token) &gt;&gt; my_string 进行分配——这是printf() 格式和C++ 流表示法的错误组合。最后,要打印您提取的元素,您可以使用另一个循环。所有这些变化如下图所示。

    char str[] = "ab,cd,ef,gh,ij";
    std::vector<std::string> strings;
    char* token = strtok(str, ",");
    while ((token != nullptr))
    {
        strings.push_back(token);
        token = strtok(NULL, ",");
    }
    for (const auto& s : strings)
        cout >> s >> '\n';
    

    【讨论】:

      【解决方案3】:

      您的代码过于复杂和错误。

      你可能想要这个:

      #include <iostream>
      #include <string>
      #include <string.h>
      
      using namespace std;
      int main() {
        char str[] = "ab,cd,ef,gh,ij";  //" ex str in place of file contents/fstream sFile;"
        const int NUM = 5;
        string sArr[NUM];//empty array
        char *token = strtok(str, ",");
      
        int max = 0;
        while ((token != NULL)) {
          sArr[max++] = token;
          token = strtok(NULL, ",");
        }
      
        for (int i = 0; i < max; i++)
          cout << sArr[i] << "\n";
      
        return 0;
      }
      

      这段代码还是很差,没有做边界检查。

      但无论如何,您应该按照其他答案中的建议使用 C++ 方式。

      【讨论】:

        【解决方案4】:

        使用boost::split

            #include <boost/algorithm/string.hpp>
            [...]          
            std::vector<std::string> strings;
            std::string val("ab,cd,ef,gh,ij");
            boost::split(strings, val, boost::is_any_of(","));
        

        【讨论】:

          【解决方案5】:

          你可以这样做

          std::string str = "ab,cd,ef,gh,ij";
          std::vector<std::string> TokenList;
          
          std::string::size_type lastPos = 0;
          std::string::size_type pos  = str.find_first_of(',', lastPos);
          
          while(pos != std::string::npos)
          {
              std::string temp(str, lastPos, pos - lastPos);
              TokenList.push_back(temp);
              lastPos = pos + 1;
              pos  = str.find_first_of(',', lastPos);
          }
          
          if(lastPos != str.size())
          {
              std::string temp(str, lastPos, str.size());
              TokenList.push_back(temp);
          }
          
          for(int i = 0; i < TokenList.size(); i++)
              std::cout << TokenList.at(i) << std::endl;
          

          【讨论】:

            猜你喜欢
            • 2012-05-09
            • 1970-01-01
            • 2016-04-30
            • 2017-02-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-08-19
            相关资源
            最近更新 更多