Reading a row until newline in the console - c++

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.

Related

C++ How to load from the standard input to an array of chars at most 5 alphanumeric characters?

When I load less than 5 chars, it is ok. But if i load more than five chars my program crash.
How can i protect before that?
#include <iostream>
#include <cstdlib>
using namespace std;
int main() {
char tab[5];
int tab2[5];
char *wsk = tab;
int i = 0;
cin >> tab;
while (true) {
cin >> tab2[i];
if (tab2[i] == 0) break;
i++;
}
i = 0;
while (true) {
if (tab2[i] ==0) break;
wsk += tab2[i];
cout << *wsk;
i++;
}
return 0;
}
You don;t want to limit it to 5.
What you really want is to make sure the read works and never crashes.
The reason you don't want to stop reading at 5 characters is that if the user enters more than 5 characters you have stopped reading in the middle of their input and you now have to write code to find the end of this input and then continue. Writting code to fix the input stream is hard. Rather take input validate (the user may have typed crap and you can generate an error message) but you will be in the correct place to continue reading for the next input operation.
char tab[5];
cin >> tab; // Fails if you read more than 4 input characters
// (because it will add '\0' on the end)
Why not use a self expanding destination structure.
std::string tab;
std::cin >> tab; // Read one word whatever the size.
But what about the array.
No more difficult. Here you want an array that re-sizes. Guess what we have std::vector
int tab2[5];
while (true) {
cin >> tab2[i]; // Fails on the 6 number you input.
// STUFF
}
The loop can be written like this:
std::vector<int> tab2;
while (true) {
int val;
cin >> val;
tab2.push_back(val);
// STUFF
}
Instead of:
while (true)
put:
while (i < 5)
For C-style arrays, you have to set the width of the input stream to the number of characters allotted to the buffer, otherwise it will be possibly for you to write past the end of the array and get a buffer overflow. This is typically done using ios_base::width:
std::cin.width(5);
std::cin >> buffer;
You can also use the manipulator std::setw:
std::cin >> std::setw(5) >> buffer;
These will both set the maximum width of the stream to 5 characters. The width will be reset to its default after the first input operation.
Your loop condition should be
while(i < 5)
Also a for loop would fit perfectly
for(int i = 0; i < 5; i++) {
// body
}
You can use the algorithms part of the STL to bound your reads.
for example :
int main(){
char c[5];
auto newEnd = std::copy_n(std::istream_iterator<char>(std::cin), 5, std::begin(c));
// if newEnd != c + 5 then it failed to read 5 characters
}
The standard input is a stream. You don't get to decide what's in it. All you can do is read from it and see what you get -- either you get some data, or you learn that the stream has ended.
If you really only want to read five bytes, you can use std::cin.read(tab, 5); you must then call std::cin.gcount() to see how many bytes have actually been read and only consume as many bytes.
Alternatively, you can use C++'s dynamic containers and use std::getline(std::cin, line) to read into an std::string line as much data as is available up to a newline.
In either event, you first do the reading, then check whether and how much you actually read, and then check if what you read is of the form you expected (e.g. alphanumeric).

cin.get() in a loop

I was trying to read from standard input. The first line is the number of lines that I will read. The lines that I read next will be printed again. Here is the code:
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
for (unsigned int i = 0; i < n; ++i)
{
char a[10];
cin.get (a, 10);
cout << "String: " << a << endl;
}
return 0;
}
When I run it and give number of lines, the program exits. I haven't figured out what's going on, so I've decided to ask it here.
Thanks in advance.
Mixing formatted and unformatted input is fraught with problems. In your particular case, this line:
std::cin >> n;
consumes the number you typed, but leaves the '\n' in the input stream.
Subsequently, this line:
cin.get (a, 10);
consumes no data (because the input stream is still pointing at '\n'). The next invocation also consumes no data for the same reasons, and so on.
The question then becomes, "How do I consume the '\n'?" There are a couple of ways:
You can read one character and throw it away:
cin.get();
You could read one whole line, regardless of length:
std::getline(std::cin, some_string_variable);
You could ignore the rest of the current line:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
As a bit of related advice, I'd never use std::istream::get(char*, streamsize). I would always prefer: std::getline(std::istream&, std::string&).
Adding a cin.get() before cin.get(a, 10) will solve your problem because it will read the remaining endline in the input stream.
I think it is important to know this when you are using cin : http://www.cplusplus.com/forum/articles/6046/

Reusing std::cin after EOF

The code below is for storing a group of words in a std::vector and to count how many times a particular word given by the user appears in the vector by comparing it to all the words stored in the vector.
The console does not prompt me for input at the second std::cin >> in the program below.
#include <iostream>
#include <ios>
#include <iomanip>
#include <vector>
#include <algorithm>
using namespace std;
int main(int argc, const char * argv[])
{
cout<<"enter your words followed ny EOF"<<endl;
vector<string> words;
string x;
typedef vector<string>::size_type vec_size;
vec_size size;
while (cin>>x)
{
words.push_back(x);
}
size=words.size();
cin.clear();
//now compare
cout<<"enter your word:"<<endl;
string my_word;
int count=0;
cin>>my_word; //didn't get any prompt in the console for this 'cin'
for (vec_size i=0; i<size; ++i)
{
my_word==words[i]?(++count):(count=count);
}
cout<<"Your word appeared "<<count<<" times"<<endl;
return 0;
}
The final output I get is "Your word appeared 0 times".
What is the problem with the code. Any help would be great.
The program reads the word list until end of file. So, at a terminal, you can type the EOF character (Ctrl-D on Linux, Ctrl-Z Return on Windows), but what then?
I think after resetting the stream, a terminal will continue to read. But if the program is taking input from a disk file, pipe, etc., there is no hope. End-of-file is forever.
Instead, use some sort of sentinel, or prefix it by a count. That way the first loop can run until the logical end of the list. And then it can read the word intended for the summary logic.
while (cin>>x && x != '*') // The word "*" ends the list of words
{
words.push_back(x);
}
size=words.size();
//now compare
cout<<"enter your word:"<<endl;
while (cin>>x)
{
words.push_back(x);
}
Here, you're reading until failure. So, when this loop finishes, cin is in an error state. You need to clear the error state:
cin.clear();
http://www.cplusplus.com/forum/articles/6046/
Read this as an example and probable issues !!

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.

How to read space separated numbers from console?

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.