How can I split a getline() into array in c++ - c++

I have an input getline:
man,meal,moon;fat,food,feel;cat,coat,cook;love,leg,lunch
And I want to split this into an array when it sees a ;, it can store all values before the ; in an array.
For example:
array[0]=man,meal,moon
array[1]=fat,food,feel
And so on...
How can I do it? I tried many times but I failed!😒
Can anyone help?
Thanks in advance.

You can use std::stringstream and std::getline.
I also suggest that you use std::vector as it's resizeable.
In the example below, we get input line and store it into a std::string, then we create a std::stringstream to hold that data. And you can use std::getline with ; as delimiter to store the string data between the semicolon into the variable word as seen below, each "word" which is pushed back into a vector:
int main()
{
string line;
string word;
getline(cin, line);
stringstream ss(line);
vector<string> vec;
while (getline(ss, word, ';')) {
vec.emplace_back(word);
}
for (auto i : vec) // Use regular for loop if you can't use c++11/14
cout << i << '\n';
Alternatively, if you can't use std::vector:
string arr[256];
int count = 0;
while (getline(ss, word, ';') && count < 256) {
arr[count++] = word;
}
Live demo
Outputs:
man,meal,moon
fat,food,feel
cat,coat,cook
love,leg,lunch

I don't want to give you some code because you must be new at C++ and you have to learn by yourself but I can give an hint: use substring to store it into a vector of string.

Related

Reading integers and strings from a text file and storing in parallel arrays

I have a text file that stores the index, student name and student ID and I am trying to read them into an array of integers index, arrays of strings studentName and studentID. I'm having problems storing the student's names because they could be more than a single word. I could separate the items in the text file by commas and use getline but that would mean the index array will have to be a string type. Is there a workaround for this without changing the original text file?
Original file:
1 James Smith E2831
2 Mohammad bin Rahman M3814
3 MJ J4790
const int SIZE = 3;
int index[SIZE];
string studentName[SIZE], studentID[SIZE];
fstream infile("students.txt");
if(infile.is_open()){
int i = 0;
while(i < 3){
infile >> index[i] >> studentName[i] >> studentID[i];
i++;
}
}
Changed file:
1,James Smith,E2831
2,Mohammad bin Rahman,M3814
3,MJ,J4790
const int SIZE = 3;
string index[SIZE];
string studentName[SIZE], studentID[SIZE];
fstream infile("students.txt");
if(infile.is_open()){
int i = 0;
while(i < 3){
getline(infile, index[i],','); //index array is string
getline(infile, studentName[i],',');
getline(infile, studentID[i],'\n');
i++;
}
}
It's an error to read one line into one student property with the given input format. You need to read one line and then split the information in this line into the 3 properties.
std::stoi can be used to convert to convert the first part of the line read to an int. Futhermore it's simpler to handle the data, if you create a custom type storing all 3 properties of a student instead of storing the information in 3 arrays.
Note that the following code requires the addition of logic to skip whitespace directly after (or perhaps even before) the ',' chars. Currently it simply includes the whitespace in the name/id. I'll leave that task to you.
struct Student
{
int m_index;
std::string m_name;
std::string m_id;
};
std::vector<Student> readStudents(std::istream& input)
{
std::vector<Student> result;
std::string line;
while (std::getline(input, line))
{
size_t endIndex = 0;
auto index = std::stoi(line, &endIndex);
if (line[endIndex] != ',')
{
throw std::runtime_error("invalid input formatting");
}
++endIndex;
auto endName = line.find(',', endIndex);
if (endName == std::string::npos)
{
throw std::runtime_error("invalid input formatting");
}
result.push_back(Student{ index, line.substr(endIndex, endName - endIndex), line.substr(endName + 1) });
}
return result;
}
int main() {
std::istringstream ss(
"1,James Smith,E2831\n"
"2, Mohammad bin Rahman, M3814\n"
"3, MJ, J4790\n");
auto students = readStudents(ss);
for (auto& student : students)
{
std::cout << "Index=" << student.m_index << "; Name=" << student.m_name << ";Id=" << student.m_id << '\n';
}
}
There are so many possible solutions that it is hard to tell, what should be used. Depends a little bit on your personal style and how good you know the language.
In nearly all solutions you would (for safety reasons) read a complete line with std::getline then put either split the line manually or use a std::istringstream for further extraction.
A csv input would be preferred, because it is more clear what belongs together.
So, what are the main possibilities? First the space separated names
You could use a std::regexand then search or match for example "(\d) ([\w ]+) (\w+)"
You cou create substrings, by searching the first space from the right side of the string, which would be the "studentID", then the getting the rest is simple
You could use a while loop and read all parts of the string and put it in a std::vector. The first element in the std::vector is then the index, the last the ID and the rest would be the name.
You could parse the string with formatted input functions. First read the index as number, then the rest as stringm the split of the last part and get the id.
And many more
For csv, you could use
the std::sregex_token_iterator looking for the comma as separator
Use also a std::vector and later pick the needed values.
Use a mixture of formatted and unformatted input
Example:
std::getline(std::getline(infile >> index >> Comma >> std::ws, name, ','), id);
It is up to you, what you would like to implement.
Write your preference in the comment, then I will add some code.

Split string with space but only get first word

I'm having problem to split the string with space as a delim. I have tried 2 of the proposed solution as in here:
Split a string in C++?
(using copy + istringstream and split method)
However, no matter what I did, the vector only get the first word (not the rest). When I use the split method, it's working with anything else (dot, comma, semi colon...) but not space.
Here is my current code, can you tell me what I get wrong? Or how I should try to approach the fix?
int main()
{
std::vector<std::string> textVector;
std::string textString;
std::cout << "Input command : ";
std::cin >> textString;
std::istringstream iss(textString);
std::copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(), std::back_inserter(textVector));
for (int i = 0 ; i < textVector.size(); i++) {
std::cout << textVector[i];
}
return 0;
}
The runnable code: http://cpp.sh/8nzq
Reason is simple, std::cin >> textString only reads until first whitespace. So textString only contains the first word.
To read entire line, you should instead use: std::getline(std::cin, textString);

Parsing and adding string to vector

I have the following string "0 1 2 3 4 "(There is a space at the end of the string). Which i would like to split and add to a vector of string. When i use a loop and a stringstream, the program loops itself into a infinity loop with the last number 4. It does not want to stop.
How can I split the following and add to a vector of strings at the same time.
Please advcie.
stringstream ss(currentLine);
for(int i=0;i<strlen(currentLine.c_str());i++){
ss>>strCode;
strLevel.push_back(strCode);
}
std::ifstream infile(filename.c_str());
std::string line;
if (infile.is_open())
{
std::cout << "Well done! File opened successfully." << std::endl;
while (std::getline(infile, line))
{
std::istringstream iss(line);
std::vector<std::string> tokens { std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>() };
for (auto const &token : tokens)
if (!token.compare("your_value"))
// Do something....
}
}
First of all, we read a line just by using std::istringstream iss(line), then we split words according to the whitespaces and store them inside the tokens vector.
Update: thanks to Nawaz for improvement suggestions (see comments).
stringstream ss(currentLine);
while ( ss >> strCode )
strLevel.push_back(strCode);
That should be enough.

How to input text into array of strings?

string fruits[200];
How can I input a string into the array ?
Example:
My mom has apples;
So , fruits array will contain:
fruits[0] = "My";
fruits[1] = "mom";
..........etc.
How can I do that?
If you're reading from the standard input:
int i = 0;
for (string word; cin >> word; i++)
names[i] = word;
If you're reading from a string, use istringstream instead.
If you would like to use the standard C++ library to its fullest, use input iterators and a vector<string> instead of an array:
vector<string> words;
back_insert_iterator< vector<string> > back_iter (words);
istream_iterator<string> eos;
istream_iterator<string> iit (cin);
copy (iit, eos, back_iter);
Using vector<string> fixes the problem of having to guess how many words would be entered, and living with the consequences of making a wrong guess.
The most compact solution:
vector<string> words;
copy(istream_iterator<string>(cin),
istream_iterator<string>(),
back_inserter(words));
This is #dasblinkenlight's solution, written using temporary variables.

C++, How to get multiple input divided by whitespace?

I have a program that need to get multiple cstrings. I current get one at a time and then ask if you want to input another word. I cannot find any simple way to get just one input with words divided be whitespace. i.e. "one two three" and save the the input in an array of cstrings.
typedef char cstring[20]; cstring myWords[50];
At the moment I am trying to use getline and save the input to a cstring and then I am trying to use the string.h library to manipulate it. Is that the right approach? How else could this be done?
If you really have to use c-style strings, you could use istream::getline, strtok and strcpy functions:
typedef char cstring[20]; // are you sure that 20 chars will be enough?
cstring myWords[50];
char line[2048]; // what's the max length of line?
std::cin.getline(line, 2048);
int i = 0;
char* nextWord = strtok(line, " \t\r\n");
while (nextWord != NULL)
{
strcpy(myWords[i++], nextWord);
nextWord = strtok(NULL, " \t\r\n");
}
But much better would be to use std::string, std::getline, std::istringstream and >> operator instead:
using namespace std;
vector<string> myWords;
string line;
if (getline(cin, line))
{
istringstream is(line);
string word;
while (is >> word)
myWords.push_back(word);
}
std::vector<std::string> strings;
for (int i = 0; i < MAX_STRINGS && !cin.eof(); i++) {
std::string str;
std::cin >> str;
if (str.size())
strings.push_back(str);
}