How to read space separated numbers from console? - c++

I'm trying to do a simple task of reading space separated numbers from console into a vector<int>, but I'm not getting how to do this properly.
This is what I have done till now:
int n = 0;
vector<int> steps;
while(cin>>n)
{
steps.push_back(n);
}
However, this requires the user to press an invalid character (such as a) to break the while loop. I don't want it.
As soon as user enters numbers like 0 2 3 4 5 and presses Enter I want the loop to be broken. I tried using istream_iterator and cin.getline also, but I couldn't get it working.
I don't know how many elements user will enter, hence I'm using vector.
Please suggest the correct way to do this.

Use a getline combined with an istringstream to extract the numbers.
std::string input;
getline(cin, input);
std::istringstream iss(input);
int temp;
while(iss >> temp)
{
yourvector.push_back(temp);
}

To elaborate on jonsca's answer, here is one possibility, assuming that the user faithfully enters valid integers:
string input;
getline(cin, input);
istringstream parser(input);
vector<int> numbers;
numbers.insert(numbers.begin(),
istream_iterator<int>(parser), istream_iterator<int>());
This will correctly read and parse a valid line of integers from cin. Note that this is using the free function getline, which works with std::strings, and not istream::getline, which works with C-style strings.

This code should help you out, it reads a line to a string and then iterates over it getting out all numbers.
#include <iostream>
#include <sstream>
#include <string>
int main() {
std::string line;
std::getline(std::cin, line);
std::istringstream in(line, std::istringstream::in);
int n;
vector<int> v;
while (in >> n) {
v.push_back(n);
}
return 0;
}

Also, might be helpful to know that you can stimulate an EOF - Press 'ctrl-z' (windows only, unix-like systems use ctrl-d) in the command line, after you have finished with your inputs. Should help you when you're testing little programs like this - without having to type in an invalid character.

Prompt user after each number or take number count in advance and loop accordingly.
Not a great idea but i saw this in many applications.

Related

How to take multiple line string input in C++?

I am learning C++. I want to take multiple line string as input but I can't. I am using getline() for it but it is taking only one line input. When I press enter for writing next line it stoped taking input and print the first line.
I want to give input like the example below
Hello, I am Satyajit Roy.
I want to make a program.
I love to travel.
But it takes only the first line input.
My code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
getline(cin, s);
cout << s << endl;
return 0;
}
Please help me to know how can I do that.
Thank you.
Either you write a loop to read individual lines and concatenate them to a single string, thats what this answer suggests. If you are fine with designating a specific character to signal the end of the input, you can use the getline overload that takes a delimiter as parameter:
#include <iostream>
#include <string>
int main() {
std::string s;
std::getline(std::cin,s,'x');
std::cout << s;
}
The user would have to type an x to end input, so this input
Hello, I am Satyajit Roy.
I want to make a program.
I love to travel.
x
would result in this output:
Hello, I am Satyajit Roy.
I want to make a program.
I love to travel.
Of course this won't work when the string to be entered contains x, which renders the approach rather useless.
However, instead of using a "real" character as delimiter you can use the EOF character (EOF = end of file) like this:
std::getline(std::cin, s, static_cast<char>(EOF));
Then input is terminated by whatever your terminal interprets as EOF, eg Ctrl-d in linux.
Thanks to #darcamo for enlightening me on the EOF part.
You can only read one line at a time with std::getline if you don’t provide your own delimiter. If you want to accumulate multiple lines, one at a time, you need a place to put the result. Define a second string. Read a line at a time into s with std::getline, and then append s to the result string. Like this:
std::string result;
std::string s;
while (std::getline(std::cin, s))
result += s;
You can take several lines using the code below if you know how many lines you will input.
int line=3, t;
string s, bigString;
for(int i=0 ; i<line ; i++)
{
getline(cin,s); // This is to input the sentence
bigString += s + "\n";
}
cout << bigString;
If you don't know how many lines you will input (Input from file until end of file) then you can check this.
string s;
vector<string> all;
while(getline(cin,s))
{
all.push_back(s);// This is to input the sentence
}
for(auto i:all)
{
cout << i << endl;
}

Space delimited dynamic input by user of unknown length

How can I get and then store a space delimited input in C++ from a user into an array?
Most important part is that length is unknown and input should be by user during runtime
#include<iostream>
using namespace std;
int main() {
int n=0;
string names[3];
int i = 0;
while ( getline( cin, names[i]))
{
cout<<"i = "<<i<<"\n";
cout<<names[i]<<"\n";
i++;
cout<<"i = "<<i<<"\n";
}
for(i=0;i<3;i++)
{
cout<<names[i];
}
return 0;
}
The first problem I can spot in your code is, that you provide a fixed sized array of string names[3]; to store an unknown number of inputs from the user. That certainly won't work.
To fix this use a container that can use an "arbitrary" number of std::strings;
std::vector<std::string> names;
Having this you can just use something like
std::vector<std::string> names;
std::string name;
while(cin >> name) {
names.push_back(name);
}
The problem still left is how you could end this loop.
There are several options:
Let the user use one of CTRL-D or CTRL-Z (<- subtle link)
Ask them to enter a special value like quit, exit, -1 to end inputting
Track it down to a second level to process ENTER. Use std::getline() parse all the words using a std::istringstream or break, when getline() reads an empty result.
Let's analyze these:
Is a bad choice, because it's operating system dependent and asks the user to do relatively complicated actions.
Restricts the possible inputs, and there's a method needed to escape inputs of quit, exit or alike.
Empty input like retrieved from a simple additional hit of the ENTER key is probably the most intuitive you can offer to the user.
As a solution following my proposal in 3.:
std::string line;
std::vector<std::string> names;
while ( getline( cin, line)) {
if(line.empty()) {
// end input condition
break;
}
std::istringstream iss(line);
std::string name;
while(iss >> name) {
names.push_back(name);
}
}

Reading a row until newline in the console

I need to make a program that reads n numbers in a row. For example, the user first puts in a list of 2 numbers like this:
P n
I managed to read those with scanf but now I need to read the n following numbers, these numbers are given in a row as follows.
1 6 3 99 ... n times
These numbers must be read all at once (or give the impression of).
I already tried using
while(getline(cin,str)){
// do something with str
}
As explained in this thread but I need the actions inside the while loop to stop when I hit the intro key. With my current implementation they don't stop, it just keeps waiting for more lines to read.
In summary:
First, user must be able to input two numbers (P and n)(done!) then hit enter and start typing a list of n numbers (not done!).
Here is my code.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main(void){
int P,n;
scanf("%d %d",&P,&n);
string val;
int score[P];
int i;
for(i=0;i<P;i++){
score[i]=0;
}
while(getline(cin,val)){
printf("Val=%s\n",val.c_str());
stringstream stream(val);
int local;
while(stream >> local){
score[local]=score[local]+1;
printf("%d-%d\n",local,score[local]);
}
}
for(i=0;i<P;i++){
printf("%d-%d\n",i,score[i]);
}
return 0;
}
Use scanf() inside the n times loop instead of getline().
for(int i = 0; i < n; i ++){
scanf("%d",&variable);
}
Not sure I understood your question, but this code will read 2 numbers, then a line and then finish.
using namespace std;
int main(){
int P,n;
cin >> P;
cin >> n;
int *score = new int[P];
for(int i=0;i<P;i++){
score[i]=0;
}
int num;
string val;
cin.ignore();
getline(cin, val);
istringstream stream(val);
while (stream >> num) {
printf("Val = %d\n", num);
score[num]=score[num]+1; // potential segmentation fault here in your code
printf("%d-%d\n",num,score[num]);
}
delete [] score;
return 0;
}
The fault would occur because you are assuming that the number on the line is smaller than P, which is the size of the array. However, the following input would cause error:
1 2
5
This question is almost a classic. The classic question has this code:
cin >> n;
getline(cin, s);
and then the author is puzzled why s is empty. Your variation does the same, although it also uses C stdio function to make matters more confusing. The problem is that the first call is a field-based input, which will read a single value n and leave any other input in the buffer! If the user entered 42 and hit enter, the remaining input is the newline. The second getline() call then reads an empty string and discards the newline.
For interaction with the user, only use getline() and then try to parse each line. Using stringstreams or sscanf(), since you seem familiar with it, are both valid options. However, if you only want to read the input an not really interact, David Weston's suggestion is also a good one and probably the easiest one, too. However, since you're using C++, I'd suggest using cin >> variable instead.

Reading sentences as string inputs from users

I have been trying to implement a simple code which takes a sentence as an input from the user, stores it in a string and displays it back.
Here are the issues:
1. When T = 1, the program exits immediately.
2. When T>1, the loop runs for only T-1 times.
I think the usage of cin to store the value of T is an issue here. Is the value of T entered being stored as a string due to some buffer capacity of cin?
#include <iostream>
#include <string>
int main()
{
int T;
std::cin >> T;
while (T--)
{
std::string song;
getline(std::cin, song);
std::cout << song << std::endl;
}
return 0;
}
How do you terminate the input that becomes T? With a newline. What happens with that newline after you read into T? It's still left in the input buffer. What will happen when you next call std::getline, what is the first character it will read? The newline, and what happens next? The loop iterates and then T is zero (for the first case where T was originally 1) and the loop and then the program exits.
The solution to this problem is to ignore characters up to and including the newline.
Add a getchar after cin as the \n after the input of T stays in buffer.
std::cin >> T;
getchar();
This is a strange way to do it. So you ask the user to tell the program, before any other input, how many lines will follow? Why not simply:
std::string s;
while (getline(std::cin, s)) {
std::cout << s << std::endl;
}
(This will simply echo every line (press enter to end the line) until end-of-file (Ctrl-d).
Either way, the problem with your code is the while (T--): so why don't you try to see what your T is, and what your getline gives you on each iteration? (I will let you figure it out on your own). Why not use the idiomatic:
for (int i = 0; i < T; ++i)
?
P.S. If you want to read sentences, and not lines, you might want to consider reading up to a delimiter (for example .). getline will do that for you, too:
getline(std::cin, s, '.');

for loop skipping getline

Hello everyone I am doing a programming assignment on structured data and I believe I understand how structs work.
I am trying to read in a list of student names, ID numbers (A-Numbers), and their balances.
When I compile my code though, it will read everything in the first time around, but the second time around the loop and every time after, it prompts for the username but skips the getline and goes straight to A-Number and A-number entry.
Any help would be appreciated. Just trying to figure out how to make the getline work every time the loop goes around.
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
int main(){
const int maxStudents = 30;
struct Students{
string studentName;
int aNumber;
double outstandingBalance;};
Students students[maxStudents];
for(int count = 0; count < maxStudents-1; count++)
{
cout<<"Student Name:";
cin.ignore();
getline(cin,students[count].studentName);
cout<<"\nA-Number:";
cin>>students[count].aNumber;
if(students[count].aNumber == -999)
break;
cout<<"\nOutstanding Balance:";
cin>>students[count].outstandingBalance;
}
cout<<setw(20)<<"A-Number"<<"Name"<<"Balance";
for(int count2 = 29; count2 >= maxStudents-1; count2--)
cout<<setw(20)<<students[count2].aNumber<<students[count2].studentName<<students[count2].outstandingBalance;
system("pause");
return 0;
}
Look up C++ FAQ on iostreams.
Item 15.6 specifically deals with your problem ("Why is my program ignoring my input request after the first iteration?"), but you may find the whole page useful.
HTH,
Put
cin.ignore();
at the end of the loop.
The reason what you're doing doesn't work is that the '>>' operators the
first time through don't extract the trailing '\n', the next getline
sees it, and returns immediately with an empty line.
The simple answer is: don't mix getline and >>. If the input is
line oriented, use getline. If you need to parse data in the line
using >>, use the string read by getline to initialize a
std::istringstream, and use >> on it.
The problem is with mixing cin and getline. Formatted input (with the >> operator) and unformatted input (getline is an example) don't play well together. You should definitely read more about it. Click here for more explanation.
Here is the solution to your problem.
cin.ignore(1024, '\n'); is the key.
for(int count = 0; count < maxStudents-1; count++)
{
...
cout<<"\nOutstanding Balance:";
cin>>students[count].outstandingBalance;
cin.ignore(1024, '\n');
}
If you have a problem with the skipping with getline()
Use it like this std::getline(cin>>ws,a);
Using ws will skip the white space.