reading space separated data and pushing it into proper contaner - c++

I am facing a problem how to read space separated data from input stream.
Lets say we need to input J 123 7 3 M. First is letter and last is letter. The rest is int.
vector<int> ints;
vector<char> chars;
stringstream ss;
...
cin >> c
chars.push_back(c);
ss << c;
cin >> i;
while(ss << i) {
ints.push_back(i);
}
...
But this code does not resolve the problem. I tried lots of combinations and still nothing.
I was thinking that I could read everything as char and then convert it to int.
I know that there are similar questions to that but in my case I would like to solve that without string and not dynami arrays (may be dynamic array but without set length).
EDIT
I managed to read such stram by:
char first, last;
int i;
std::cin >> first;
std::cout << first;
while(std::cin >> i) {
std::cout << i;
}
std::cin >> last;
std::cout << last;
But there is one problem:
writing "F 1 23 2 2 W" displays F12322#. Don't know why there is "#" at the end.
Any thoughts?
EDIT2:
std::cin.clear();
after while loop solves the problem.

In order to organize and add your data you could create a small struct which with an operator>> for example (ideone):
struct line{
char f1,f5; // give them meaningful names
int f2,f3,f4;
friend std::istream &operator>>(std::istream &is, line &l) {
is >> l.f1;
is >> l.f2;
is >> l.f3;
is >> l.f4;
is >> l.f5;
return is;
}
};
int main() {
string input = "J 123 7 3 M\nK 123 7 3 E\nH 16 89 3 M";
stringstream ss(input);
vector<line> v;
line current;
while(ss >> current){
v.push_back(current);
}
for (auto &val: v){
cout<< val.f1 << endl;
}
return 0;
}
Each time you read something you can do whatever you'd like with the current line. If each lien does not have a specific meaning you could just do a
while(ss>>f1>>f2>>f3>>f4>>f5){
// do stuff with fields
}
Where ss is a stringstream but it could all so be cin.

If you know the number of elements and its type then you can use the following code for
#include<vector>
#include<iostream>
using namespace std;
int main()
{
int i;
char c;
vector<int> ints;
vector<char> chars;
cin>>c;
chars.push_back(c);
for(int j=0;j<3;j++){
cin>>i;
ints.push_back(i);
}
cin>>c;
chars.push_back(c);
}

Related

istringsteam with line breaks

Okay I read that if we have a string s =" 1 2 3"
we can do :
istringstream iss(s);
int a;
int b;
int c;
iss >> a >> b >> c;
Lets say we have a text file with the following :
test1
100 ms
test2
200 ms
test3
300 ms
ifstream in ("test.txt")
string s;
while (getline(in, s))
{
// I want to store the integers only to a b and c, How ?
}
1) You can rely on succesful convertions to int:
int value;
std::string buffer;
while(std::getline(iss, buffer,' '))
{
if(std::istringstream(buffer) >> value)
{
std::cout << value << std::endl;
}
}
2) or just skip over unnecessary data:
int value;
std::string buffer;
while(iss >> buffer)
{
iss >> value >> buffer;
std::cout << value << std::endl;
}
If you know the pattern of the details in the text file, you could parse through all the details, but only store the int values. For example:
ifstream in ("test.txt")
string s;
while (getline(in, s))
{
getline(in,s); //read the line after 'test'.
string temp;
istringstream strm(s);
s >> temp;
int a = stoi(temp) // assuming you are using C++11. Else, atoi(temp.c_str())
s >> temp;
getline(in,s); // for the line with blank space
}
This above code is still somewhat of a inelegant hack. What you could do besides this is use random file operations in C++. They allow you to move your pointer for reading data from a file. Refer to this link for more information: http://www.learncpp.com/cpp-tutorial/137-random-file-io/
PS: I haven't run this code on my system, but I guess it should work. The second method works for sure as I have used it before.

Data not being correctly read from input file

please see below c++ function. The point of it is to store variables in an input file ("is") to global arrays. I go through with the debugger with a watch on the "temp" variable (the first if statement seems to work fine), and after reading the first line of the input file, the variable temp no longer updates.
The file is in a specific format so it should be reading an int, although I did eventually put a char at the end of the KEYFRAME if statement to see if it was reading the endline character (it wasn't).
What are some possible reasons for this? Thank you so much!
void readFile(istream& is){
string next;
int j = 0;
int i = 0;
while (is){
for (int i = 0; i < F; i++){
is >> next;
if (next == "OBJECT")
{
int num;
is >> num;
string name;
is >> name;
objects[j].objNum = num;
objects[j].filename = name;
j++;
}
else if (next == "KEYFRAME"){
int k;
int temp;
is >> k;
int time;
is >> time;
objects[k].myData[time].setObjNumber(k);
objects[k].myData[time].setTime(time);
is >> temp;
objects[k].myData[time].setPosition('x', temp) ;
is >> temp;
objects[k].myData[time].setPosition('y', temp);
is >> temp;
objects[k].myData[time].setPosition('z', temp);
is >> temp;
objects[k].myData[time].setRotation('x', temp);
is >> temp;
objects[k].myData[time].setRotation('y', temp);
is >> temp;
objects[k].myData[time].setRotation('z', temp);
is >> temp;
objects[k].myData[time].setScaling('x', temp);
is >> temp;
objects[k].myData[time].setScaling('y', temp);
is >> temp;
objects[k].myData[time].setScaling('z', temp);
char get;
is >> get;
}
else {
cout << "Error reading input file";
return;
}
}
}
}
The most common reasons why std::istream's operator>> does not update the variable can be demonstrated using the following simple example:
#include <sstream>
#include <iostream>
int main() {
std::string sample_input="1 2 3 A 4 5";
std::istringstream i(sample_input);
int a=0, b=0, c=0, d=0;
std::string e;
int f=0;
i >> a >> b >> c >> d >> e >> f;
std::cout << a << std::endl;
std::cout << b << std::endl;
std::cout << c << std::endl;
std::cout << d << std::endl;
std::cout << e << std::endl;
std::cout << f << std::endl;
}
The resulting output from this program is:
1
2
3
0
0
This example forces a conversion error on the fourth parameter. Once operator>> encounters a formatting conversion error, an error bit is set on the stream, which prevents further conversions.
When using operator>>, it's necessary to check for conversion errors after every input format conversion, and reset the stream's state, if necessary.
So, your answer is that you have an input conversion error someplace. I generally avoid using operator>>. It's fine for simple situations where the input is known, and there is no possibility of bad input. But as soon as you get into a situation where you might need to potentially handle bad input, using operator>> becomes painful, and its much better to take some other approach for parsing stream-based input.

How to read in user entered comma separated integers?

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

Reading in unknown length of numbers

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.. :)

How to use cin with a variable number of inputs?

I was in a programming competition yesterday and we had to read in input of the form
n
a1 a2 ... an
m
b1 b2 ... bm
...
where the first line says how many inputs there are, and the next line contains that many inputs (and all inputs are integers).
I know if each line has the same number of inputs (say 3), we can write something like
while (true) {
cin >> a1 >> a2 >> a3;
if (end of file)
break;
}
But how do you do it when each line can have a different number of inputs?
Here's a simple take using just standard libraries:
#include <vector> // for vector
#include <iostream> // for cout/cin, streamsize
#include <sstream> // for istringstream
#include <algorithm> // for copy, copy_n
#include <iterator> // for istream_iterator<>, ostream_iterator<>
#include <limits> // for numeric_limits
int main()
{
std::vector<std::vector<double>> contents;
int number;
while (std::cin >> number)
{
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // skip eol
std::string line;
std::getline(std::cin, line);
if (std::cin)
{
contents.emplace_back(number);
std::istringstream iss(line);
std::copy_n(std::istream_iterator<double>(iss), number, contents.back().begin());
}
else
{
return 255;
}
}
if (!std::cin.eof())
std::cout << "Warning: end of file not reached\n";
for (auto& row : contents)
{
std::copy(row.begin(), row.end(), std::ostream_iterator<double>(std::cout," "));
std::cout << "\n";
}
}
See it live on Coliru: input
5
1 2 3 4 5
7
6 7 8 9 10 11 12
Output:
1 2 3 4 5
6 7 8 9 10 11 12
you can do it this way
#include<vector>
...
...
std::vector<sometype> a;
sometype b;
std::cin >> b;
while(std::cin)
{
a.push_back(b);
std::cin >> b;
}
you can input any number of items and when you are finished send in the EOF signal.
Your Algorithm will look something like this:
1. read the 'number' of inputs, say n1
2. set up a loop to read the n1 inputs
3. check if the user has more inputs to give
if YES repeat the steps 1,2 and 3 till all inputs are taken and stored.
else move on...
You can use a for or while loop and store the inputs into an array.
Hope this helps!
Because people were complaining how I called my first answer "a simple take", here's a proper version using Boost Spirit:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
int main()
{
typedef std::vector<std::vector<double>> data_t;
typedef boost::spirit::istream_iterator It;
std::cin.unsetf(std::ios::skipws);
It first(std::cin), last;
bool ok;
data_t contents;
{
using namespace boost::spirit::qi;
static rule<It, data_t(), blank_type, locals<int>> file;
static rule<It, std::vector<double>(int number), blank_type> row;
_a_type number; // friendly alias
file %= -(omit [int_[number=_1]] > eol > row(number)) % eol;
row = repeat(_r1) [ double_ ];
ok = phrase_parse(first, last, file, blank, contents);
}
if (ok) for (auto& row : contents)
{
std::copy(row.begin(), row.end(), std::ostream_iterator<double>(std::cout," "));
std::cout << "\n";
}
if (first!=last)
std::cout << "Warning: end of file not reached, remaining unparsed: '" << std::string(first, last) << "'\n";
}
It's obviously far superior
it uses far fewer include lines :)
it takes ~10x as long to compile (with no optimizations), another 16% longer with optimizations
it requires about 5 years of study in meta-programming to grok it (joking, the spirit docs/tutorials are quite ok)
on the serious account: it is much more flexible
can be extended to parse other structural elements, more complicated
can implement semantics on the fly
will parse NaN and +/-infinity correctly
etc.
See it Live on Coliru as well
Given the format you are specifying, here is what I would do.
for (int n; std::cin >> n; )
{
if (n == 0) // Test for end of input
break;
for (int i = 0; i != n; ++i)
{
int x;
std::cin >> x;
if (!std::cin)
break;
// Valid input x. Now do something with x like
// v.push_back(x) where v is some vector of ints
}
}
// Did we succeed?
if (!std::cin)
{
// Something went bad.
std::cerr << "Error reading input" << std::endl;
return EXIT_FAILURE;
}
Simple, use a for loop and array.
int a[MAX]; // programming problems usually specify a max size
for(i=0;i<n;i++)
cin>>a[i];
A simple solution using arrays and dynamic memory allocation for taking variable number of inputs of a predefined type.
#include<iostream>
using namespace std;
int main(){
int n;
cout<<"Enter the number of elements"<<endl;
cin>>n;
int *c=new int[n];
for(int k=0;k<n;k++)
cin>>c[k];
delete c;
}