Split String to Vector with Whitespaces c++ error - c++

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
vector<string> split_string(string s)
{
string buf;
stringstream ss(s);
vector<string> tokens;
while (ss >> buf)
tokens.push_back(buf);
return tokens;
}
int main()
{
cout << split_string("Alpha Beta Gamma");
}
when i try to split a string into a vector by using whitespaces i am not able to print out my solution.
i doesnt let me use std::cout but in my function the return value is given
why cant i use it like that? how do i fix this?

std::cout cannot take a vector, you need to iterate through the container and print each element separately, try using something like this:
int main()
{
string originalString = "Alpha Beta Gamma";
for (const auto& str : split_string(originalString))
cout << str << '\n';
return 0;
}

Related

Can we create std::istringstream object from a reversed std::string

I am learning C++ using recommended C++ books. In particular, i read about std::istringstream and saw the following example:
std::string s("some string");
std::istringstream ss(s);
std::string word;
while(ss >> word)
{
std::cout<<word <<" ";
}
Actual Output
some string
Desired Output
string some
My question is that how can we create the above std::istringstream object ss using the reversed string(that contains the word in the reverse order as shown in the desired output)? I looked at std::istringstream's constructors but couldn't find one that takes iterators so that i can pass str.back() and str.begin() instead of passing a std::string.
You can pass iterators to the istringstream constructor indirectly if you use a temporary string:
#include <sstream>
#include <iostream>
int main()
{
std::string s{"Hello World\n"};
std::istringstream ss({s.rbegin(),s.rend()});
std::string word;
while(ss >> word)
{
std::cout<<word <<" ";
}
}
Output:
dlroW olleH
Though thats reversing the string, not words. If you want to print words in reverse order a istringstream alone does not help much. You can use some container to store the extracted words and then print them in reverse:
#include <sstream>
#include <iostream>
#include <vector>
int main()
{
std::string s{"Hello World\n"};
std::istringstream ss(s);
std::string word;
std::vector<std::string> words;
while(ss >> word)
{
words.push_back(word);
}
for (auto it = words.rbegin(); it != words.rend(); ++it) std::cout << *it << " ";
}
Output:
World Hello
Since you added the c++20 tag:
#include <sstream>
#include <string>
#include <iostream>
#include <vector>
#include <ranges>
int main()
{
std::vector<std::string> vec;
std::string s("some string");
std::string word;
std::istringstream ss(s);
while(ss >> word)
{
vec.push_back(word);
}
for (auto v : vec | std::views::reverse)
{
std::cout << v << ' ';
}
}

Best way to iterate over a string without going over its size

I am having trouble splitting words of a string into a vector. I am trying to keep track of each word with a first and last integer. I believe my main issue has to do with how I am iterating over the string.
What would be ways to improve this function?
Input: "hello there how are you"
Actual Output: "hello", "there", "how", "are"
Expected Output: "hello", "there", "how", "are", "you"
std::vector <std::string> wordChopper(std::string& s)
{
std::vector<std::string> words;
int first = 0;
int last;
std::string word;
for(unsigned int i = 0; i < s.size(); i++)
{
if(s[i] != ' ')
{
last++;
}
else
{
word = s.substr(first,last);
words.push_back(word);
first = i+1;
last = 0;
}
}
return words;
}
I suggest:
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <iterator>
using namespace std;
vector<string> wordChopper(const string & s)
{
istringstream iss(s);
return vector<string>(istream_iterator<string>{iss}, istream_iterator<string>());
}
int main()
{
for (auto & iter : wordChopper("hello there how are you"))
{
cout << iter << endl;
}
return 0;
}
I have given the widely used method in the comment. However, if you want to write your own function, I would suggest trying out something on the lines of:
std::vector<std::string> stringTokeniser(std::string originalString, char delimiter = ' ') {
std::vector<std::string> tokensVector;
std::string word;
for (const auto character : originalString) {
if (character != delimiter) {
word.push_back(character);
}
else {
tokensVector.push_back(word);
word.clear();
}
}
tokensVector.push_back(word);
return tokensVector;
}
I am having trouble splitting words of a string into a vector
There is no need for indexing, start and first positions, etc. if the words are separated by spaces.
Usage of std::stringstream accomplishes this:
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
std::vector <std::string> wordChopper(std::string s)
{
std::vector<std::string> words;
std::stringstream strm(s);
std::string word;
while (strm >> word)
words.push_back(word);
return words;
}
int main()
{
auto v = wordChopper("hello there how are you");
for (auto s : v)
std::cout << s << "\n";
}
Output:
hello
there
how
are
you

Problem with converting vector of string to vector of doubles

I am trying to write a program that reads some numerical values from a .csv file, stores them in a std::vector<std::string>, and then converts these values into doubles and stores them in a std::vector<double>.
I am trying to do the conversion using stringstreams, which has worked fine for me in the past.
I have managed to import the numerical values and store them in the std::vector<std::string>, however I am getting a weird problem when trying to do the conversions to double. Only the very first value is stored in the std::vector<double> with a lot of significant figures missing, and the other entries are just ignored and not stored in the std::vector<double> at all.
Here is my code so far:
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
double extract_double(std::string str)
{
std::stringstream ss;
double grade;
//Pass all the course details to string stream
ss << str;
//Extract the double type part of the string stream which is the course grade
ss >> grade;
str = "";
ss.ignore();
return grade;
}
int main()
{
std::ifstream my_input_file;
std::string file_name;
my_input_file.open("scale_free_gamma_2_fitnesses.csv");
int number_of_data_in_file;
std::vector<std::string> fitnesses_string;
std::vector<double> fitnesses;
std::string string_temp;
while (my_input_file.good()) {
//Extract strings from file
std::getline(my_input_file, string_temp, ',');
fitnesses_string.push_back(string_temp);
}
for (auto fitnesses_it = fitnesses_string.begin();
fitnesses_it < fitnesses_string.end(); ++fitnesses_it){
fitnesses.push_back(extract_double(*fitnesses_it));
}
for (auto fitnesses_itt = fitnesses.begin();
fitnesses_itt < fitnesses.end(); ++fitnesses_itt){
std::cout << *fitnesses_itt << std::endl;
}
return 0;
}
You should be reading individual lines from the file first, and then splitting up each line on commas.
And there are easier ways to handle the rest of your code, too.
Try something more like this instead:
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
int main()
{
std::ifstream my_input_file("scale_free_gamma_2_fitnesses.csv");
std::vector<std::string> fitnesses_string;
std::vector<double> fitnesses;
std::string line, string_temp;
while (std::getline(my_input_file, line)) {
//Extract strings from line
std:::istringstream iss(line);
while (std::getline(iss, string_temp, ','))
fitnesses_string.push_back(string_temp);
}
for (const auto &s : fitnesses_string){
fitnesses.push_back(std:stod(s));
}
for (auto value : fitnesses){
std::cout << value << std::endl;
}
return 0;
}
In which case, even simpler would be to just get rid of the std::vector<std::string> altogether:
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
int main()
{
std::ifstream my_input_file("scale_free_gamma_2_fitnesses.csv");
std::vector<double> fitnesses;
std::string line, string_temp;
while (std::getline(my_input_file, line)) {
//Extract strings from line
std:::istringstream iss(line);
while (std::getline(iss, string_temp, ','))
fitnesses.push_back(std:stod(string_temp));
}
for (auto value : fitnesses){
std::cout << value << std::endl;
}
return 0;
}
A few things. First, there's a far better way to loop over your vectors.
for (const std::string &str: fitnesses_string) {
}
These are referred to as range-based for-loops, and I think you can see how much cleaner this syntax is. In modern C++, you rarely need to use iterators anymore. (I won't say never, but rarely.)
Next, your inner loop makes no sense at all. Instead, just do it quite simply:
for (const std::string &str: fitnesses_string) {
fitnesses.push_back(extract_double(str));
}
Now, let's talk about how to convert a string to double.
fitnesses.push_back(std::stod(str));
So you don't need your method. There's already a method waiting for you. It's defined in #include <string>.

How do I read a file into a 2D list by splitting at the comma

I'm working on a program where the user will input in the format x,0,0 and it will be saved to a file then read into an array where I can compare the values however I'm stuck when trying to read into a 2D array can someone please help? Think the error is in the struct part
This is what I have so far:
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
#include <sstream>
using namespace std;
struct listArray
{
string name[];
int price1[];
int price2[];
};
int main()
{
listArray la;
string line;
cout << "Enter your list: ";
ofstream fout;
fout.open("list.txt");
while (fout) {
getline(cin, line);
if (line == "-1")
break;
fout << line << endl;
}
fout.close();
int count = 0;
ifstream listFile;
listFile.open("list.txt");
if(listFile.is_open()){
while (listFile) {
getline(listFile, la.name[count], ",");
count++;
listFile.close();
}
}
You can use delimiter to grab the substring, and use this substring to fill your struct, an exemple of split:
#include<iostream>
std::vector<std::string> split(const string& input, const string& regex)
{
// passing -1 as the submatch index parameter performs splitting
std::regex re(regex);
std::sregex_token_iterator first{input.begin(), input.end(), re, -1},last;
return {first, last};
}
if you are using C++11 or higher, you can use std::vector for arrays, and you also can use boost library, they have nice support for delimiter and other stuffs.

How to split string using istringstream with other delimiter than whitespace?

The following trick using istringstream to split a string with white spaces.
int main() {
string sentence("Cpp is fun");
istringstream in(sentence);
vector<string> vec = vector<string>(istream_iterator<string>(in), istream_iterator<string>());
return 0;
}
Is there a similar trick to split a string with any delimiter? For instance, | in "Cpp|is|fun".
Generally speaking the istringstream approach is slow/inefficient and requires at least as much memory as the string itself (what happens when you have a very large string?). The C++ String Toolkit Library (StrTk) has the following solution to your problem:
#include <string>
#include <vector>
#include <deque>
#include "strtk.hpp"
int main()
{
std::string sentence1( "Cpp is fun" );
std::vector<std::string> vec;
strtk::parse(sentence1," ",vec);
std::string sentence2( "Cpp,is|fun" );
std::deque<std::string> deq;
strtk::parse(sentence2,"|,",deq);
return 0;
}
More examples can be found Here
#include <iostream>
#include <string>
#include <sstream>
int main()
{
std::istringstream iss { "Cpp|is|fun" };
std::string s;
while ( std::getline( iss, s, '|' ) )
std::cout << s << std::endl;
return 0;
}
Demo
The following code uses a regex to find the "|" and split the surrounding elements into an array. It then prints each of those elements, using cout, in a for loop.
This method allows for splitting with regex as an alternative.
#include <iostream>
#include <string>
#include <regex>
#include <algorithm>
#include <iterator>
using namespace std;
vector<string> splitter(string in_pattern, string& content){
vector<string> split_content;
regex pattern(in_pattern);
copy( sregex_token_iterator(content.begin(), content.end(), pattern, -1),
sregex_token_iterator(),back_inserter(split_content));
return split_content;
}
int main()
{
string sentence = "This|is|the|sentence";
//vector<string> words = splitter(R"(\s+)", sentence); // seperate by space
vector<string> words = splitter(R"(\|)", sentence);
for (string word: words){cout << word << endl;}
}