Converting a string of numbers into an int vector c++ - c++

Is there a simple way to convert a string of numbers separated by spaces into a vector of ints or something that I can easily convert into a vector?
I am creating an input operator (>>) to make a binary tree using values input from command line. And this is the main that goes with it
int main(int argc, char **argv)
{
stringstream stream;
stream << " 10" << " 11" << " 10" << " 2" << endl;
tree = new binary_tree();
stream >> *tree;
if (tree->inorder() != string("7 10 11")) //inorder() prints the tree in order
cout << "Test passed" << endl;
delete tree;
return 0;
}
The problem I am having is that while I can create and print the values that I need, I can't convert them and put them into a vector - for which I have a working defined method that creates a tree from the values.
std::istream& operator>>(std::istream &in, binary_tree &value)
{
vector<int> input_tree;
string readline;
getline(in, readline);
cout << "(" << readline << ")" << endl; //prints correctly - (10 11 10 2)
//where I need to insert insert values into vector
for(int i = 0; i < input_tree.size(); i++)
{
insert(input_tree[i], value); //inserts the values from a vector into a binary tree
}
return in;
}
I have tried looping through the string and using stoi() on each character but it always errored whenever the spaces were causing errors.
Thanks for any help and sorry if I've missed any important information out.

A little easier to understand solution, I think (though less concise):
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
int main() {
string s= "4 5 6";
stringstream ss(s);
vector<int> v;
int hlp;
while(ss >> hlp)
{
v.push_back(hlp);
}
for(auto i: v)
cout << i << '\n';
return 0;
}
You can use a stringstream just as you could use cin.
http://ideone.com/Y6UfuW

You can do this:
vector<int> vec((istream_iterator<int>(in)), istream_iterator<int>());
This will read integers from in and insert them into vec all in one line. It's a pretty canonical use of istream_iterator which is part of the standard library. Then you don't need to read each line and parse it yourself.
If you want to read more about how this works, see here: How does std::copy work with stream iterators
As for why there appear to be an extra pair of parentheses around the first argument, that's because of the "most vexing parse": https://en.wikipedia.org/wiki/Most_vexing_parse - just a silly quirk of C++ syntax.

Related

why is this code not giving the desired output?

#include <sstream>
#include <vector>
#include <iostream>
using namespace std;
vector<int> parseInts(string str) {
istringstream ss(str);
vector<int> integ;
int val;
while(ss){
if(ss>>val){
integ.push_back(val);
}
}
return integ;
}
vector<int> parseInts2(string str)
{
vector<int> vec;
stringstream ss(str);
char ch;
int temp;
while(ss)
{
ss>>temp>>ch; >> operator
vec.push_back(temp);
}
return vec;
}
int main() {
string str;
cin >> str;
vector<int> integers = parseInts(str);
for(int i = 0; i < integers.size(); i++) {
cout << integers[i] << "\n";
}
return 0;
}
i want to create a stream,to a string,read integers to the stream from the string and insert it in a vector and display its elements while the output is displaying nothing.what is wrong with the code?
EDIT
basically the question ask inputs in the form of integers that are separated by commas and asks us to print the integers after parsing it. i find no significant difference between the 2 functions but parseInt2 still works(while calling the function in main,of course instead of parseInt). Why?
I fear that your question will be closed by people on SO.
But let me give you the answer.
Basically everything set already in the comments. Why not in an answer? I do not know.
Before you can read something from an std::istringstream, you need to put something in it. You need to initialize it. That is usually done by using its constructor:
istringstream ss(str);
In main, you have the problem, that you read only one value from std::cin with cin >> str;. You want to use std::getline instead, which reads a complete line. And not only "something" up to the next space. So
getline(cin, str);
will help you further.
In modern C++, with keeping the std::istringstream approach, you would probably write
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <sstream>
int main() {
// Read a line and check, if that worked
if (std::string str; std::getline(std::cin, str)) {
// Create and initialize a std::istringstream
std::istringstream iss(str);
// Define a variable integers, use its range constructor with iterators
std::vector integers(std::istream_iterator<int>(iss), {});
// Range based for loop
for (const int& i : integers) {
std::cout << i << "\n";
}
}
return 0;
}
That will save the subfunction.
EDIT:
OK, you want to read csv and you must use ">>".
If you want to read data separated by comma from a stream, then you need to extract:
an integer value from the stream
then a comma
then a integer
then a comma
then a integer
. . .
The extractor operator, or the functionality behind it, will always extract characters from a stream and convert it to a requested type (e.g. an integer), until it reaches a space or the conversion can not be continued any longer (for example, a "," is a separator).
That is the reason, why your 2nd function works.
It is important that you alwys check the status of the extraction operation. In the below example you will see that, at the end of the string, we try to read a comma, where there is none. The extraction fails, but we do not care. We ignore it by intent. To understand the functionality better, please see.
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
int main() {
// Source or test data. We put it directly into the stream;
std::istringstream ss{ "1,2,3, 4 , 5,6" };
std::vector<int> integers{};
char comma{};
int integer{};
while (ss) {
// Read integer and check, if it could be read
if (ss >> integer) {
integers.push_back(integer);
std::cout << "Read Integer " << integer << "\n";
}
else
std::cerr << "Error: Could not read integer\n";
// Now read the comma
if (ss && (ss >> comma))
std::cout << "Read Comma: " << comma << "\n";
else
std::cerr << "Error: Could not read comma\n";
}
// SHow all values
for (const int i : integers) std::cout << i << "\n";
return 0;
}
If you have questions, I am happy to answer.

How to read from keyboard a variable number of integers in C++?

I need to read a variable number of integers from keyboard so that I can use each of them.
First I thought I could use something like
int myinteger;
for (int i=0; i<MAX_NUMBER_OF_INTEGERS; i++){
cin >> myinteger;
//What I want to do with that Integer
}
But then I realized that if MAX_NUMBERS_OF_INTEGERS = 10 I have to write 10 integers. But what I want is that I can pass "1 2 3" "1 2 3 4" (for example) and not necessary write 10 integers.
The question seems to have changed a little bit since it was asked and a good answer was given. This just serves to answer the new questions.
#include <iostream>
#include <sstream>
#include <vector>
const int MAX_NUMBERS_OF_INTEGERS = 10;
int main() {
std::string line;
std::cout << "Enter at most " << MAX_NUMBERS_OF_INTEGERS << " ints, separated by spaces: ";
std::getline(std::cin, line);
// create a string stream of the line you entered
std::stringstream ss(line);
// create a container for storing the ints
std::vector<int> myInts;
// a temporary to extract ints from the string stream
int myInteger;
// extract at most MAX_NUMBERS_OF_INTEGERS ints from the string stream
// and store them in the container
while(myInts.size()<MAX_NUMBERS_OF_INTEGERS && ss>>myInteger) myInts.push_back(myInteger);
std::cout << "Extracted " << myInts.size() << " integer(s)\n";
// loop through the container and print all extracted ints.
for(int i : myInts) {
std::cout << i << "\n";
}
// ... or access a certain int by index
if(myInts.size() > 2)
std::cout << "The third int was: " << myInts[2] << "\n";
}
std::vector<int> read_ints;
int _temp;
for(;;)
{
cin >>_temp;
if(!cin.good()) {
break;
}
else {
read_ints.push_back(_temp);
}
}
I haven't tested this solution but it should read an arbitrary number of ints from cin until you enter something else than an integer. You could also skip the saving in the vector part if you don't need to save the results. This is just releveant if you want to save an arbitray number of integers.
EDIT: After clarification your solution could look like this:
int MAX_CHARS = 10;
int my_int;
cin >> setw(MAX_CHARS) >> my_int;
setw limits the number of input characters but you have to include iomanip header
If you want to access every digit, convert int to vector of ints with this function:
vector <int> integerToArray(int x)
{
vector <int> resultArray;
while (true)
{
resultArray.insert(resultArray.begin(), x%10);
x /= 10;
if(x == 0)
return resultArray;
}
}
then you can access each digit with the index e.g. first digit
vectory<int> resultArray = integerToArray(my_int);
int digit = resultArray[0];
Source
One way to read all numbers from a single line limiting them to a maximum number of integers is using std::getline() to get the line into a string then use istringstream in a loop.
#include <iostream>
#include <sstream>
using namespace std;
int main() {
std::string line;
std::getline (std::cin,line);
std::istringstream iss(line);
int myInt;
for(int i=0;(iss >> myInt) && (i < MAX_NUMBER_OF_INTEGERS);++i ) {
std::cout << myInt << ' ';
}
return 0;
}
Note: I did not define MAX_NUMBER_OF_INTEGERS in the code. I could have defined it with const int MAX_NUMBERS_OF_INTEGERS = 10; before usage or possibly that could be a preprocessor define or even a command line parameter. I leave this up to the user.

How to reverse the string

I'm a beginner at coding and was given a project by a friend to reverse the order of a string inputted by the user, however when I run this code the program just repeatedly prints the string inputted many times over and I'm not sure whats wrong.
For instance, I input "hi", it just prints "hi" many times. I have tried using cin, getline and scanf (as recommended by a friend), but to no avail...
#include <iostream>
using namespace std;
int main()
{
char arr[5];
getline(cin, arr);
for(int x=4; x>=0; x--){
cout << arr << endl;
}
return 0;
}
Since the question is tagged C++, you should use C++ constructs such as std::string and std::reverse. This will result in more readable and understandable code.
#include <string>
#include <iostream>
#include <algorithm>
int main()
{
std::string input;
std::getline(std::cin, input);
std::reverse(input.begin(), input.end());
std::cout << input << std::endl;
return 0;
}
This line is wrong:
cout << arr << endl;
You have to use the index operator [] like this:
cout << arr[x];
Note that there is no endl, as that would print every character in a new line.
Using arr[x] gives you the element of the array (or character of the string if you will) at index x. Please note that element indexes in C++ start at 0. So the first element is arr[0], second arr[1], and so on.
Also, why use a C-style char array of only size 5? You can use the C++ std::string just as effectively and it will work for larger strings:
string x;
getline(cin, x);
for (int i = x.size() - 1; i >= 0; i--)
{
cout << x[i];
}
cout << endl;
Hope this helps.
When you write, cout << arr << endl; you are printing the entire string in each iteration of the loop. Instead, you wish to print the character at the index x, so you should write it as cout << arr[x]; If you use endl inside the loop, you will get a new line after each character.
Moreover, in C++, there is an easier way to deal with strings, using the string library. Then, you need not specify the number of characters in your string beforehand, and helps if the user needs to enter more than 4 characters.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string arr;
getline(cin, arr);
for(int x=arr.size()-1; x>=0; x--){
cout << arr[x];
}
cout << endl;
return 0;
}
What's happening is you're sending the entire contents of arr to cout 5 times. What you want instead is to print each character in reverse; to do this, you need to send only one character of arr at a time inside your for loop:
cout << arr[x] // This sends the character at index x to cout
cout << arr // This sends the entire array to cout
Also, you should have cout << endl after the for loop; otherwise, you'll print a newline character after each letter.
Alternate solution using iterators:
#include <iostream>
#include <iterator>
#include <algorithm>
#include <string>
int main()
{
std::string input;
getline(std::cin, input);
for (std::string::reverse_iterator rit=input.rbegin(); rit!=input.rend(); ++rit)
std::cout << *rit;
return 0;
}

Putting text file content into a 2D array

I'm trying to read in a text file that is 200 x 1000 of numbers into an array. Each number is separated by a tab. I thought using a 2D array would be good for this situation since it would allow me to distinguish between the individual rows. Being able to distinguish between the individual rows is important in this situation which is why I wanted to do it in this manner. Right now I have the following:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ifstream file("text.txt");
if(file.is_open())
{
string myArray[1000];
for(int i = 0; i < 1000; ++i)
{
file >> myArray[i];
cout << myArray[i] << endl;
}
}
}
Which currently scans the first row of numbers into the array and then prints it out. I wanted to have a 2D array that scans each individual row into the array but keeps them separate. This means the content of row 1 is separate from the content of row 2. I figured a 2D array would do this. I am a bit stuck on this part. I attempted to make a 2D array through the use of a nested for loop but when I tried to copy the values over into the array things started to go wrong. The order was incorrect and the rows were not separated. I am coding this in C++. If someone could help me understand how to import a text document like the one I described and send all that information to a 2D array I would greatly appreciate it. Thanks.
You can use a stringstream to extract the numbers from each row. Also, you don't need to have an array of strings. You can just use one string.
int main()
{
ifstream file("text.txt");
if(file.is_open())
{
for(int i = 0; i < 1000; ++i)
{
string row;
if ( std::getline(file, row) )
{
std::istringstream istr(row);
int number;
while ( istr >> number )
{
// Add the number to a container.
// Or print it to stdout.
cout << number << "\t";
}
cout << endl;
}
}
}
}
If your dimensions change, you use the following code. Note that you can use std::copy to copy from a std::stringstream into a std::vector:
#include <iostream>
#include <iterator>
#include <sstream>
#include <vector>
int main()
{
std::string input =
"11 12\n"
"21 22\n"
"31 32\n"
"41 42\n"
;
std::stringstream file(input);
std::string temp;
while (std::getline(file, temp)) {
std::stringstream line(temp);
std::vector<std::string> v;
std::copy(
std::istream_iterator<std::string>(line),
std::istream_iterator<std::string>(),
std::back_inserter(v));
for (auto x: v)
std::cout << x << " ";
std::cout << "\n";
}
}

Reading a list of numbers and sorting C++

I'm trying to read a list of numbers from a file and sort them by reading them into an array and then sorting the contents of the array. But I'm getting
error:incompatible types in assignment of 'std::basic_ostream<char, std::char_traits<char> >' to 'int [1]'
I'm fairly new to programming and this is my first time working with C++
Can anyone tell me how to write the list of numbers to an array so that I can sort them?
Here is what I have:
#include <fstream>
#include <iostream>
#include <iomanip>
#define ANYSIZE_ARRAY 1
using std::cout;
using std::endl;
int main()
{
const char* filename = "test.txt";
std::ifstream inputFile(filename);
int numbers[ANYSIZE_ARRAY];
int i, key;
// Make sure the file exists
if(!inputFile)
{
cout << endl << "The File is corrupt or does not exist. " << filename;
return 1;
}
long n = 0;
while(!inputFile.eof())
{
inputFile >> n;
numbers = cout << std::setw(10) << n;
}
for(int j=1;j<5;j++)
{
i=j-1;
key=numbers[j];
while(i>=0 && numbers[i]>key)
{
numbers[i+1]=numbers[i];
i--;
}
numbers[i+1]=key;
}
//Display sorted array
cout<<endl<<"Sorted Array\t";
for(i=0;i<5;i++)
cout<<numbers[i]<<"\t";
cout<<endl;
}
The line causing the error is:
numbers = cout << std::setw(10) << n;
I'm not quite sure what you're trying to do here, it looks like you just want to print it in which case the numbers = isn't needed.
The structure of your loop to read all the data is problematic also. The line: while (!inputFile.eof()) isn't idiomatic C++ and won't do what you hope. See here for a discussion on that issue (and here).
For reference you can do this quite simply with less work by using std::sort
#include <iterator>
#include <algorithm>
#include <vector>
#include <fstream>
#include <iostream>
int main() {
std::ifstream in("test.txt");
// Skip checking it
std::vector<int> numbers;
// Read all the ints from in:
std::copy(std::istream_iterator<int>(in), std::istream_iterator<int>(),
std::back_inserter(numbers));
// Sort the vector:
std::sort(numbers.begin(), numbers.end());
// Print the vector with tab separators:
std::copy(numbers.begin(), numbers.end(),
std::ostream_iterator<int>(std::cout, "\t"));
std::cout << std::endl;
}
This program also uses a std::vector instead of an array to abstract the "how big should my array be?" problem (which your example looked to have a possible problem problem with).
Here is what you need to do to get your program to work:
Change ANYSIZE_ARRAY to 5
Where you read the numbers, replace the while with this:
long n = 0;
i=0;
while(!inputFile.eof())
{
inputFile >> n;
cout << std::setw(10) << n;
numbers[i]=n;
i++;
}
This way, you will create an array which can hold 5 numbers, and you will read the numbers into that array. I used 5 because I saw that you were using the same number in the sorting algorithm, so I assumed that you only have to read 5 numbers. This is a bad thing, because your program will only work with 5 numbers.
If you need it to work with a variable amount of numbers, you can use a std::vector<long> to store the numbers. You can create a vector, and then use push_back() to add numbers to it. The vector will resize automatically and will hold as many numbers as you put in it. Then you can replace the 5s in your code with the vector's size() method.
You were getting your original error because this line doesn't make sense:
numbers = cout << std::setw(10) << n;
C++ views that line as if you are trying to print out the number to the stdout stream (which is in our case the console, the screen), and then assigning that stream to the "numbers" array. You cannot assign an output stream to an integer array (hence the error cannot convert from ostream to int[1]).
First, you should not assign an outstream variable to an int.
Second, n is long type and numbers is an integer array. There is type-unsafety.
Third, you should pre-allocate array size.
Forth, you can directly use sort() in STL function to do the sorting.
Try the following code:
#include <fstream>
#include <iostream>
#include <iomanip>
#include <algorithm>
using namespace std;
#define ANYSIZE_ARRAY 5
int main()
{
const char* filename = "test.txt";
std::ifstream inputFile(filename);
int numbers[ANYSIZE_ARRAY];
int i, key;
// Make sure the file exists
if(!inputFile)
{
cout << endl << "The File is corrupt or does not exist. " << filename;
return 1;
}
int n = 0;
i = 0;
while(!inputFile.eof())
{
inputFile >> n;
cout << std::setw(10) << n;
numbers[i++] = n;
}
sort(numbers, numbers + ANYSIZE_ARRAY);
//Display sorted array
cout<<endl<<"Sorted Array\t";
for(i=0; i<ANYSIZE_ARRAY; i++)
cout<<numbers[i]<<"\t";
cout<<endl;
}