1

I want to split the strings on each line of my text file into an array, similar to the split() function in python. my desired syntax is a loop that enters every split-string into the next index of an array, so for example if my string: "ab,cd,ef,gh,ij"

, every time I encounter a comma then I would: datafile >> arr1[i]

and my array would end up: arr1 = [ab,cd,ef,gh,ij]

a mock code without reading a text file is provided below

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

5 Answers 5

3

In C++ you can read a file line by line and directly get a std::string.

You will found below an example I made with a split() proposal as you requested, and a main() example of reading a file:

Example

data file:

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

c++ code:

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

output:

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

I hope it will help.

Sign up to request clarification or add additional context in comments.

Comments

1

So, a few things to fix. Firstly, arrays and NUM are kind of limiting - you have to fix up NUM whenever you change the input string, so C++ provides std::vector which can resize itself to however many strings it finds. Secondly, you want to call strtok until it returns nullptr once, and you can do that with one loop. With both your for and NUM you call strtok too many times - even after it has returned nullptr. Next, to put the token into a std::string, you would assign using my_string = token; rather than ("%s\n", token) >> my_string - which is a broken mix of printf() formatting and C++ streaming notation. Lastly, to print the elements you've extracted, you can use another loop. All these changes are illustrated below.

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

Comments

1

You could do something like this

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;

Comments

0

Your code is overly complicated and wrong.

You probably want this:

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

This code is still poor and no bound checking is done.

But anyway, you should rather do it the C++ way as suggested in the other answers.

Comments

-1

Use 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(","));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.