#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.
Related
There is an exercise which dynamically asks for user input and stores in a vector, but I don't know how to end a string input. The book says it is Ctrl+Z but it doesn't work. I am using visual studio 2019 and I know it should work because when I change the variables for integers it does.
int main(void) {
std::vector<std::string> words;
for (std::string palabras; std::cin >> palabras;)
words.push_back(palabras);
std::string ban = "broccoli";
for (std::string x : words)
if (x == ban) std::cout << "Bleep!" << '\n';
else std::cout << x << '\n';
}
Keep things simple: don't use the return value of std::cin as the for loop condition, unless you're sure what to expect. Here is a simple program that does what you want without using a loop. It would be a good exercise to make that work inside a loop.
#include <iostream>
#include <string>
int main(int argc, char **argv)
{
std::string lovely_str;
std::cout << "Enter a string: ";
std::cin >> lovely_str;
std::cout << "got: " << lovely_str << "\n";
return 0;
}
If you insist on using your original program you can use ctrl+d
to signal the end of read strings
Take some help of std::istringstream & make life easier (notice comments):
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
int main(void) {
// To store the entire line of input
std::string input;
// To store the split words
std::vector<std::string> words;
// Temporary variable to iterate through
std::string temp;
// Constant string to be used
const std::string ban = "broccoli";
std::cout << "Enter some words: ";
std::getline(std::cin, input);
// Here we go
std::istringstream iss(input);
// Separating each words space, e.g. apple <sp> banana => vector apple|banana
while (iss >> temp)
words.push_back(temp);
// Using reference as for-each
for (auto& i : words)
if (i == ban) i = "bleep!";
// Printing the modified vector
for (auto& i : words) std::cout << i << ' ';
std::cout << std::endl;
return 0;
}
So guys, Actually What I wanna do here is that when I input 3,12,36 the output will be:
3
12
36
But here I have difficulty on how to make it output all the answer. What I have been doing is that when you input 3,12,36 it will output 3 12 only and if you type 3,12,36,48 it will output 3 12 36.
So it will always miss the last integer because my while loop is not correct I guess. but if I change it into
while(output >> life|| output >> ch)
It doesn't work either. I've done a lot of research but it still makes me confused and I'm still stuck on this part.
vector<int> parseInts(string str) {//23,4,56
vector<int>lifeishard;
stringstream output;
string lifeisgood = str;
output.str(lifeisgood);
int life;
char ch;
while(output >> life >> ch){
lifeishard.push_back(life);
//lifeishard.push_back(life2);
//lifeishard.push_back(life3);
}
return lifeishard;
}
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;
}
On your last number, the while loop fails because there's no character at the end. Just the end of the string. So it doesn't execute the push_back inside the loop.
Change it so that the while loop just gets the number. Then do the push_back in the loop. Then in the loop, after the push, get the comma character. Don't bother checking for failure getting the comma because when it goes around the while loop again it will fail and exit.
I changed to using getline in your main. I changed your loop index to size_t because it is never a good idea to mix signed and unsigned integers, and whenever you use a size() function, it's a size_t. When posting your program it really should include everything. My fixed up version of your program:
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
using namespace std;
vector<int> parseInts(string str) {//23,4,56
vector<int>lifeishard;
stringstream output;
string lifeisgood = str;
output.str(lifeisgood);
int life;
char ch;
while(output >> life){
lifeishard.push_back(life);
output >> ch;
}
return lifeishard;
}
int main() {
string str;
getline(cin, str);
vector<int> integers = parseInts(str);
for(size_t i = 0; i < integers.size(); i++) {
cout << integers[i] << "\n";
}
// Here is how we do for loops over containers in modern C++
for(auto x: integers) {
cout << x << '\n';
}
return 0;
}
A combination of stringstream, getline with delimiter and stoi would be enough for the conversion:
From the C++ reference for getline with delimiter:
Extracts characters from is and stores them into str until the delimitation character delim is found.
With this in mind, the code example below assumes the input is well-formed:
Example
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
vector<int> parseInts(const string& str, const char delim = ',')
{
vector<int> parsed;
stringstream ss(str);
string s;
while (getline(ss, s, delim)) // <- stores input in s upon hitting delimiter
parsed.push_back(stoi(s)); // <-- convert string to int and add it to parsed
return parsed;
}
int main()
{
string str = "3,12,36"; // <-- change to cin if you'd like
vector<int> ints = parseInts(str);
for (auto& i : ints)
cout << i << "\n";
}
Output
3
12
36
See more: getline, stoi
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.
I'm writing a program that prompts the user for:
Size of array
Values to be put into the array
First part is fine, I create a dynamically allocated array (required) and make it the size the user wants.
I'm stuck on the next part. The user is expected to enter in a series of ints separated by commas such as: 1,2,3,4,5
How do I take in those ints and put them into my dynamically allocated array? I read that by default cin takes in integers separated by whitespace, can I change this to commas?
Please explain in the simplest manner possible, I am a beginner to programming (sorry!)
EDIT: TY so much for all the answers. Problem is we haven't covered vectors...is there a method only using the dynamically allocated array I have?
so far my function looks like this. I made a default array in main. I plan to pass it to this function, make the new array, fill it, and update the pointer to point to the new array.
int *fill (int *&array, int *limit) {
cout << "What is the desired array size?: ";
while ( !(cin >> *limit) || *limit < 0 ) {
cout << " Invalid entry. Please enter a positive integer: ";
cin.clear();
cin.ignore (1000, 10);
}
int *newarr;
newarr = new int[*limit]
//I'm stuck here
}
All of the existing answers are excellent, but all are specific to your particular task. Ergo, I wrote a general touch of code that allows input of comma separated values in a standard way:
template<class T, char sep=','>
struct comma_sep { //type used for temporary input
T t; //where data is temporarily read to
operator const T&() const {return t;} //acts like an int in most cases
};
template<class T, char sep>
std::istream& operator>>(std::istream& in, comma_sep<T,sep>& t)
{
if (!(in >> t.t)) //if we failed to read the int
return in; //return failure state
if (in.peek()==sep) //if next character is a comma
in.ignore(); //extract it from the stream and we're done
else //if the next character is anything else
in.clear(); //clear the EOF state, read was successful
return in; //return
}
Sample usage http://coliru.stacked-crooked.com/a/a345232cd5381bd2:
typedef std::istream_iterator<comma_sep<int>> istrit; //iterators from the stream
std::vector<int> vec{istrit(in), istrit()}; //construct the vector from two iterators
Since you're a beginner, this code might be too much for you now, but I figured I'd post this for completeness.
A priori, you should want to check that the comma is there, and
declare an error if it's not. For this reason, I'd handle the
first number separately:
std::vector<int> dest;
int value;
std::cin >> value;
if ( std::cin ) {
dest.push_back( value );
char separator;
while ( std::cin >> separator >> value && separator == ',' ) {
dest.push_back( value );
}
}
if ( !std::cin.eof() ) {
std::cerr << "format error in input" << std::endl;
}
Note that you don't have to ask for the size first. The array
(std::vector) will automatically extend itself as much as
needed, provided the memory is available.
Finally: in a real life example, you'd probably want to read
line by line, in order to output a line number in case of
a format error, and to recover from such an error and continue.
This is a bit more complicated, especially if you want to be
able to accept the separator before or after the newline
character.
You can use getline() method as below:
#include <vector>
#include <string>
#include <sstream>
int main()
{
std::string input_str;
std::vector<int> vect;
std::getline( std::cin, input_str );
std::stringstream ss(str);
int i;
while (ss >> i)
{
vect.push_back(i);
if (ss.peek() == ',')
ss.ignore();
}
}
The code is taken and processed from this answer.
Victor's answer works but does more than is necessary. You can just directly call ignore() on cin to skip the commas in the input stream.
What this code does is read in an integer for the size of the input array, reserve space in a vector of ints for that number of elements, then loop up to the number of elements specified alternately reading an integer from standard input and skipping separating commas (the call to cin.ignore()). Once it has read the requested number of elements, it prints them out and exits.
#include <iostream>
#include <iterator>
#include <limits>
#include <vector>
using namespace std;
int main() {
vector<int> vals;
int i;
cin >> i;
vals.reserve(i);
for (size_t j = 0; j != vals.capacity(); ++j) {
cin >> i;
vals.push_back(i);
cin.ignore(numeric_limits<streamsize>::max(), ',');
}
copy(begin(vals), end(vals), ostream_iterator<int>(cout, ", "));
cout << endl;
}
#include <iostream>
using namespace std;
int main() {
int x,i=0;
char y; //to store commas
int arr[50];
while(!cin.eof()){
cin>>x>>y;
arr[i]=x;
i++;
}
for(int j=0;j<i;j++)
cout<<arr[j]; //array contains only the integer part
return 0;
}
The code can be simplified a bit with new std::stoi function in C+11. It takes care of spaces in the input when converting and throws an exception only when a particular token has started with non-numeric character. This code will thus accept input
" 12de, 32, 34 45, 45 , 23xp,"
easily but reject
" de12, 32, 34 45, 45 , 23xp,"
One problem is still there as you can see that in first case it will display " 12, 32, 34, 45, 23, " at the end where it has truncated "34 45" to 34. A special case may be added to handle this as error or ignore white space in the middle of token.
wchar_t in;
std::wstring seq;
std::vector<int> input;
std::wcout << L"Enter values : ";
while (std::wcin >> std::noskipws >> in)
{
if (L'\n' == in || (L',' == in))
{
if (!seq.empty()){
try{
input.push_back(std::stoi(seq));
}catch (std::exception e){
std::wcout << L"Bad input" << std::endl;
}
seq.clear();
}
if (L'\n' == in) break;
else continue;
}
seq.push_back(in);
}
std::wcout << L"Values entered : ";
std::copy(begin(input), end(input), std::ostream_iterator<int, wchar_t>(std::wcout, L", "));
std::cout << std::endl;
#include<bits/stdc++.h>
using namespace std;
int a[1000];
int main(){
string s;
cin>>s;
int i=0;
istringstream d(s);
string b;
while(getline(d,b,',')){
a[i]= stoi(b);
i++;
}
for(int j=0;j<i;j++){
cout<<a[j]<<" ";
}
}
This code works nicely for C++ 11 onwards, its simple and i have used stringstreams and the getline and stoi functions
You can use scanf instead of cin and put comma beside data type symbol
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a[10],sum=0;
cout<<"enter five numbers";
for(int i=0;i<3;i++){
scanf("%d,",&a[i]);
sum=sum+a[i];
}
cout<<sum;
}
First, take the input as a string, then parse the string and store it in a vector, you will get your integers.
vector<int> v;
string str;
cin >> str;
stringstream ss(str);
for(int i;ss>>i;){
v.push_back(i);
if(ss.peek() == ','){
ss.ignore();
}
}
for(auto &i:v){
cout << i << " ";
}
I have an input file that contains some data in coordinate mode
For example (2,3,5) translates to column 2, row 3, and level 5. I'm curious on a method of reading in the numbers after using getline(cin,string) to obtain the data. I don't know how many digits are in the data points so i can't assume the 1st character will be of length 1. Is there any libraries that can help solve the problem faster?
my gameplan so far that's not finished
void findNum(string *s){
int i;
int beginning =0;
bool foundBegin=0;
int end=0;
bool foundEnd=0
while(*s){
if(isNum(s)){//function that returns true if its a digit
if(!foundBegin){
foundBegin=1;
beginning=i;
}
}
if(foundBegin==1){
end=i;
foundBegin=0;
}
i++;
}
}
Try this:
#include <iostream>
#include <cstdlib>
#include <sstream>
#include <vector>
#include <string>
int main() {
std::vector <std::string> params;
std::string str;
std::cout << "Enter the parameter string: " << std::endl;
std::getline(cin, str);//use getline instead of cin here because you want to capture all the input which may or may not be whitespace delimited.
std::istringstream iss(str);
std::string temp;
while (std::getline(iss, temp, ',')) {
params.push_back(temp);
}
for (std::vector<std::string>::const_iterator it=params.begin(); it != params.end(); ++it) {
std::cout << *it << std::endl;
}
return 0;
}
The only caveat is that the arguments will have to be non whitespace delimited.
Example input string:
1,2,3
Output:
1
2
3
Once these arguments have been parsed, you can then convert them from strings to (example) integer via the following:
template <typename T>
T convertToType(const std::string &stringType) {
std::stringstream iss(stringType);
T rtn;
return iss >> rtn ? rtn : 0;
}
which can be used as follows:
int result = convertToType<int>("1");//which will assign result to a value of 1.
UPDATE:
This now works correctly on whitespace delimited input (except for newlines) like the following:
1 , 2, 3 , 4
Which yields:
1
2
3
4
jrd1's answer is pretty good, but if you'd prefer there happen to be functions for converting characters to integers (and back) already in the C standard library (cstdlib). You'd be looking for atoi.
http://en.cppreference.com/w/cpp/string/byte/atoi
#include <sstream>
void findNums(const string &str, int &i, int &j, int &k)
{
std::stringstream ss(str);
char c;
ss >> c >> i >> c >> j >> c >> k;
}
Simply use extractor operator for reading any type of value in respective variable type.
#incude<ifstream> // for reading from file
#include<iostream>
using namespace std;
int main()
{
int number;
ifstream fin ("YouFileName", std::ifstream::in);
fin >> number; // put next INT no matter how much digit it have in number
while(!fin.eof())
{
cout << number << endl;
fin >> number; // put next INT no matter how much digit it have in number and it will ignore all non-numeric characters between two numbers as well.
}
fin.close();
return 0;
}
Have a look over here for more details.
Note: Be careful while using it for character arrays and strings.. :)