istream_iterator behaviour - c++

I have two pieces of code.They work properly when it is used alone in the main().
vector<int> v;
cout << "Enter sequance of integers "<< "(press q to quit) : ";
istream_iterator<int> start_cin(cin);
istream_iterator<int> end_of_cin;
copy(start_cin,end_of_cin,back_inserter(v));
for ( vector<int>::iterator It = v.begin();It != v.end(); It++ )
cout << *It << "\t";
cout << endl;
and
vector<string> vS;
cout << "Enter three strings : ";
for ( int i = 0; i < 3; i++ )
vS.push_back(*istream_iterator<string>(cin));
ostream_iterator<string> sIt(cout,", ");
copy(vS.begin(),vS.end(),sIt);
cout << endl;
When these two part use together,i.e
#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
#include <string>
using namespace std;
int main ()
{
// first part
vector<int> v;
cout << "Enter sequance of integers "<< "(press q to quit) : ";
istream_iterator<int> start_cin(cin);
istream_iterator<int> end_of_cin;
copy(start_cin,end_of_cin,back_inserter(v));
for ( vector<int>::iterator It = v.begin();It != v.end(); It++ )
cout << *It << " \t";
cout << endl;
vector<string> vS;
cout << "Enter three strings : ";
for ( int i = 0; i < 3; i++ )
vS.push_back(*istream_iterator<string>(cin));
ostream_iterator<string> sIt(cout,", ");
copy(vS.begin(),vS.end(),sIt);
cout << endl;
return 0;
}
here first part worked but second part give output: Enter Three Strings : , , ,.
I want to know that what is the reason behind this behaviour?
Thanks.

After the copy() has completed cin will be in an unreadable state (!cin.good()), due to the failed read of the "integer" q. This means the subsequent for loop will fail to read anything.
Add:
cin.clear();
cin.ignore(); // To skip the unread "q"
before the for loop.
EDIT:
As commented by James Kanze, check to ensure "q" was the cause of the termination of the copy():
...
cin.clear();
string int_read_terminator;
cin >> int_read_terminator;
if ("q" != int_read_terminator)
{
cerr << "Integer copy() failure: " << int_read_terminator << "\n";
}
else
{
...

You've just encountered one of the problems with input_iterator: it
requires the entire file to be of one type. There are several ways of
working around this; the most general is to insert a filtering streambuf
between the actual source and the stream. Thus, for example, the first
part of your stream should terminate when you enter a single line with
just a 'q', something like:
class UntilQStreambuf : public std::streambuf
{
std::streambuf* mySource;
char myBuffer;
bool myIsAtStartOfLine;
protected:
int underflow()
{
int results = mySource->sbumpc();
if ( results == 'q'
&& myIsAtStartOfLine
&& mySource->sgetc() == '\n' ) {
mySource->sbumpc(); // remove terminator line.
results = traits_type::eof();
}
if ( results != traits_type::eof() ) {
myBuffer = results;
setg( &myBuffer, &myBuffer, &myBuffer + 1 );
}
return results;
}
public:
UntilQStreambuf( std::istream& source )
: mySource( source->rdbuf() )
, myIsAtStartOfLine( true )
{
}
};
(I think boost::iostream has some support which would make this
significantly simpler to write.) You then set up a separate stream for
reading the numbers, using the streambuf from std::cin (or
whereever):
std::vector<int>
getNumbers( std::istream& source )
{
UntilQStreambuf localSB( source );
std::istream src( &localSB );
std::vector<int> results( (std::istream_iterator<int>( src )),
(std::istream_iterator<int>()) );
if ( !src.eof() ) {
// Some other error occurred...
}
return results;
}
By using a separate stream, the end condition won't be set in the
original stream, and you can continue with it later (perhaps using more
of the same technique).

Related

While loop that ends when using EOF in inner while loop

I am writing code that takes values from a user and stores it into a vector. The goal is that user can enter a said amount of values and they would be stored into a vector. The User will then be given the option to enter in another amount if he or she wishes and those values would also be stored in the same vector. However in order to terminate the inner while loop that allows the user to enter in the values, the user has to use EOF but that also ends my outer while loop. I do not know what a simple solution to this would be.
#include <iostream>
#include <vector>
#include<string.h>
using namespace std;
int main()
{
int a;
int holder, answer = 1;
vector<int> v;
vector<int> s;
while (answer == 1) {
cout << " Enter in a vector \n";
while (cin >> a) {
v.push_back(a);
}
s.insert(s.begin(), v.begin(), v.end());
for (int i{ 0 }; i < s.size(); i++) {
cout << s.at(i);
}
cout << " do you want to continue adding a vector? Type 1 for yes and 0 for no." << "\n";
cin >> holder;
if (holder == answer)
continue;
else
answer = 0;
}
return 0;
}
If the user closes his/her side of std::cin you won't be able to do cin >> holder; afterwards, so you need another way of letting the user stop entering numbers into the vector. Here's an alternative:
#include <iostream>
#include <vector>
#include <string> // not string.h
int main() {
int a;
int holder, answer = 1;
std::vector<int> v;
std::vector<int> s;
while(true) {
std::cout << "Enter in a vector of integers. Enter a non-numeric value to stop.\n";
while(std::cin >> a) {
v.push_back(a);
}
s.insert(s.begin(), v.begin(), v.end());
for(int s_i : s) {
std::cout << s_i << "\n";
}
if(std::cin.eof() == false) {
std::cin.clear(); // clear error state
std::string dummy;
std::getline(std::cin, dummy); // read and discard the non-numeric line
std::cout << "do you want to continue adding a vector? Type "
<< answer << " for yes and something else for no.\n";
std::cin >> holder;
if(holder != answer) break;
} else
break;
}
}
You could also take a closer look at std::getline and std::stringstream to make an even nicer user interface.
You might be better of using getline than cin. getline looks for \n instead of EOF as far as I remember,
But I have not used C++ in some time so I might be wrong about that.
http://www.cplusplus.com/reference/string/string/getline/

find a certain word in sentence in c++

I want to write a program that finds a word that the user entered I think my solution is right but when I Run it, the program shows nothing in the console
anybody can fix it?
int main()
{
char sen[200],del[200],maybedel[200];
cout<<"enter sentence :"<<endl;
cin.getline(sen,200);
cout<<"which word do you want to delete ?";
cin.getline(del,200);
int len = strlen(sen);
for(int i=0;i<=len;i++)
{
if(sen[i]==' ')
{
for(int j=i;j<=len;j++)
if(sen[j]==' ' || sen[j]=='\0')
for(int k=i+1,t=0;k<j;k++,t++)
maybedel[t]=sen[k];
if(maybedel==del)
cout<<maybedel;
}
}
return 0;
}
The line if(sen[i]==' '), line 12 of your code , prevents code from entering the block unless the sentence begins with (' ')!
I changed the code a bit and now it works fine.
char sen[200], del[200], maybedel[200];
cout << "enter sentence :" << endl;
cin.getline(sen, 200);
cout << "which word do you want to delete ?" << endl;
cin.getline(del, 200);
int len = strlen(sen);
int t = 0;
for(int i = 0; i <= len; i++) {
if(sen[i] == ' ' || sen[i] == '\0') {
maybedel[t] = '\0';
t = 0;
if(strcmp(del,maybedel)==0) {
cout << maybedel << endl;
}
}
else
{
maybedel[t] = sen[i];
t++;
}
}
The major reason for no output is
if (maybedel == del) // <<< this will *never* be true
cout << maybedel; // will never run
Since comparing "strings" in arrays needs help from std::strcmp(maybedel,del) == 0 would be better.
UPDATE:
Another attack method is to avoid raw loops and utilize the STL to your favor. Here's a more robust solution:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <vector>
using namespace std;
int main() {
cout << "enter sentence :\n";
string sen;
if (!getline(cin, sen)) throw std::runtime_error("Unable to read sentence");
cout << "which word do you want to delete ? ";
string del;
if (!(cin >> del)) throw std::runtime_error("Unable to read delete word");
istringstream stream_sen(sen);
vector<string> arrayofkeptwords;
remove_copy_if(istream_iterator<string>(stream_sen), istream_iterator<string>(),
back_inserter(arrayofkeptwords),
[&del](auto const &maybedel) { return maybedel == del; });
copy(begin(arrayofkeptwords), end(arrayofkeptwords),
ostream_iterator<string>(cout, " "));
cout << '\n';
}

How to stop a while loop in c++

"Write a program that consists of a while-loop that (each time around the loop) reads in two ints and then prints them.
Exit the program when a terminating '|' is entered."
my attempt
#include <iostream>
#include <cstdlib>
using namespace std;
int main(){
int firstnumber;
int secondnumber;
int stopnumber;
while(stopnumber!='|'){
cout <<"Please enter an integer, followed by another integer: \n";
cin >> firstnumber >> secondnumber;
cout <<"\n" << firstnumber <<" "<< secondnumber<< " \n";
}
return 0;
}
the program takes 2 number and prints them, but when i enter '|' , it goes in infinite loop. How to stop the program when i enter '|'
Thanks
This is how your loop should look like:
Read a character (std::cin::get).
If successful and your character is the stop symbol, break the loop.
If your character is not a digit (::isdigit), continue looping.
If your character is a digit, put it back(std::cin::putback).
Read two integers.
If successful, display them, if not, clear the stream (std::cin::clear).
You will have to patiently try to understand what get, putback & isdigit are doing.
[EDIT]
Run it
#include <iostream>
#include <cctype>
int main()
{
char c;
while ( std::cin.get( c ) && c != '|' )
{
if ( !std::isdigit( c ) )
continue;
std::cin.putback( c );
int i, j;
if ( std::cin >> i >> j )
std::cout << i << ' ' << j << std::endl;
else
std::cin.clear();
}
return 0;
}
Your loop is testing stopnumber which is never set. If you set stopnumber to either firstnumber or secondnumber then perhaps you can get your logic to work but there is a step missing as it is.
Ok, I think I have found my answer
I tried putting my cin in the while loop as such
int firstnumber;
int secondnumber;
while (cin >> firstnumber >> secondnumber)
And it worked! Thanks everyone for your help
This depends on whether you need to exit directly after you receive the '|' character or whether you mind running through the rest of the loop first before exiting it......
Personally I'd want to exit straight after receiving the '|' so would follow the basic idea of....
int a,b;
while(){
read your values a,b in
if (a='|' || b='|'){exit()};
print your values
}
std::stoi(std::string) - returns int from std::string
#include <iostream>
#include <string>
bool isNumber(std::string &str) {
for (auto i : str) {
if (i < '0' || i > '9') return false;
return true;
}
int main () {
int a, b;
std::string s;
while (true) {
std::cin >> s;
if (s == "|" || !isNumber(s)) break;
a = std::stoi(s);
std::cin >> s;
if (s == "|" || !isNumber(s)) break;
b = std::stoi(s);
std::cout << a << " " << b << std::endl;
}
return 0;
}

How to check if the input is a valid integer without any other chars?

#include <iostream>
#include <limits>
using namespace std;
int main()
{
int x;
cout << "5 + 4 = ";
while(!(cin >> x)){
cout << "Error, please try again." << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
if (x == (5 + 4)){
cout << "Correct!" << endl;
}
else{
cout << "Wrong!" << endl;
}
return 0;
}
How can I check if the user inputs a valid integer? In this program I wrote above, if the user inputs 9, it should be correct, however, if the user inputs 9a for example, it should return an error, but it doesn't for some reason. How can I correct it?
How I did it using cin.peek()
#include <iostream>
#include <limits>
#include <stdio.h>
using namespace std;
int main()
{
int x;
bool ok;
cout << "5 + 4 = ";
cin >> x;
while(!ok){
cin >> x;
if(!cin.fail() && (cin.peek() == EOF || cin.peek() == '\n')){
ok = true;
}
else{
cout << "Error, please try again." << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
if (x == (5 + 4)){
cout << "Correct!" << endl;
}
else{
cout << "Wrong!" << endl;
}
return 0;
}
You could read a string, extract an integer from it and then make sure there's nothing left:
std::string line;
std::cin >> line;
std::istringstream s(line);
int x;
if (!(s >> x)) {
// Error, not a number
}
char c;
if (s >> c) {
// Error, there was something past the number
}
bool isIntegerNumber(const std::string& string){
std::string::const_iterator it = string.begin();
int minSize = 0;
if(string.size()>0 && (string[0] == '-' || string[0] == '+')){
it++;
minSize++;
}
while (it != string.end() && std::isdigit(*it)) ++it;
return string.size()>minSize && it == string.end();
}
You have a line oriented input, so you should probably be using
getline. Something like:
bool
getIntFromLine( std::istream& source, int& results )
{
std::string line;
std::getline( source, line );
std::istringstream parse( source ? line : "" );
return parse >> results >> std::ws && parse.get() == EOF;
}
should do the trick.
Using this, your loop would be:
while ( !getIntFromLine( std::istream, x ) ) {
std::cout << "Error, please try again." << std::endl;
}
Note that this technique also means that you don't have to worry
about clearing the error or resynchronizing the input.
For the reason this happens, take a look at this link:
Extracts and parses characters sequentially from the stream to
interpret them as the representation of a value of the proper type,
which is stored as the value of val. Internally, the function accesses
the input sequence by first constructing a sentry object (with
noskipws set to false). Then (if good), it calls num_get::get (using
the stream's selected locale) to perform both the extraction and the
parsing operations, adjusting the stream's internal state flags
accordingly. Finally, it destroys the sentry object before returning.
Then observe the behavior if you attempt something like this:
int x = 0;
cin >> x;
std::cout << x << std::endl;
std::cout << cin.good() << std::endl;
g++-4.8 -std=c++11 -O3 -Wall -pedantic -pthread main.cpp && echo "900a100" | ./a.out
// Output:
// 900
// 1
If you input "a100" instead, it outputs:
0
0
try this:
std::string input;
std::cin >> input;
if ( std::all_of(input.begin(), input.end(), std::isdigit) )
{
//input is integer
}
Refer this :
C++ Fix for checking if input is an integer
One I have seen that works for some situations is:
Read the input as string. cin >> str
Decode to number: atoi, or sscanf, or stringstream, etc.
print the number into a string (using sprintf or stringstream)
check if its equal to read string. (using strings ==, not char*)
Quick and simple to do. Uses the Cin>>str word breaking rules, accept negative numbers, rejects overflowing numbers. But it does reject "+10", which in somesituations you are happy wiht, and in some you are not.
If you can use C++11 (and your compiler has full regex support), you can also use the <regex> library:
#include <iostream>
#include <limits>
#include <regex>
#include <string>
#include <utility>
int main()
{
std::string line;
std::pair<int, bool> value = std::make_pair(0, false);
std::cout << "5 + 4 = ";
while (!value.second)
{
while (!std::getline(std::cin, line))
{
std::cout << "Error, please try again." << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
if (!std::regex_match(line, std::regex("(\\+|-)?[[:digit:]]+")))
{
std::cout << "Error, please try again." << std::endl;
}
else
{
value = std::make_pair(std::stol(line), true);
}
}
if (value.first == (5 + 4))
{
std::cout << "Correct!" << std::endl;
}
else
{
std::cout << "Incorrect!" << std::endl;
}
return 0;
}

Input not cleared

As the question says, for some reason my program is not flushing the input or using my variables in ways that I cannot identify at the moment. This is for a homework project that I've gone beyond what I had to do for it, now I just want the program to actually work :P
Details to make the finding easier:
The program executes flawlessly on the first run through. All throws work, only the proper values( n > 0 ) are accepted and turned into binary.
As soon as I enter my terminate input, the program goes into a loop and only asks for the terminate again like so:
When I run this program on Netbeans on my Linux Laptop, the program crashes after I input the terminate value. On Visual C++ on Windows it goes into the loop like just described.
In the code I have tried to clear every stream and initialze every variable new as the program restarts, but to no avail. I just can't see my mistake.
I believe the error to lie in either the main function:
int main( void )
{
vector<int> store;
int terminate = 1;
do
{
int num = 0;
string input = "";
if( cin.fail() )
{
cin.clear();
cin.ignore( numeric_limits<streamsize>::max(), '\n' );
}
cout << "Please enter a natural number." << endl;
readLine( input, num );
cout << "\nThank you. Number is being processed..." << endl;
workNum( num, store );
line;
cout << "Go again? 0 to terminate." << endl;
cin >> terminate // No checking yet, just want it to work!
cin.clear();
}while( terminate );
cin.get();
return 0;
}
or in the function that reads the number:
void readLine( string &input, int &num )
{
int buf = 1;
stringstream ss;
vec_sz size;
if( ss.fail() )
{
ss.clear();
ss.ignore( numeric_limits<streamsize>::max(), '\n' );
}
if( getline( cin, input ) )
{
size = input.size();
for( int loop = 0; loop < size; ++loop )
if( isalpha( input[loop] ) )
throw domain_error( "Invalid Input." );
ss << input;
ss >> buf;
if( buf <= 0 )
throw domain_error( "Invalid Input." );
num = buf;
ss.clear();
}
}
When you call cin >> terminate, it will read the value of terminate, but leave the newline following it in the input stream. Late when you call getline(cin, input), it will read up to the newline, which means it will get an empty string.
You can discard all characters up to the newline by adding this after cin >> terminate:
cin.ignore(99, '\n');
Or avoid mixing operator >> and getline.
Don't mix those >> and getline operators as interjay mentioned.
Also, if you want to clear your code, I assume it can be rewritten the folllowing way:
int main() {
while (true) {
std::cout << "Please enter a natural number" << std::endl;
int num;
std::cin >> num;
// Exception handling here can be done easily
// like this
// if (!(std::cin >> num) || num < 0)
// throw std::domain_error("TROLOLOLO");
std::cout << "Thank you. Number is being processed..." << std::endl;
//workNum(num, store) here
std::cout << "Go again? 0 to terminate." << std::endl;
int terminate;
std::cin >> terminate;
if (terminate == 0) break;
}
}