error in looping - c++

consider this code snippet
void make(int n)
{
std::string user_input;
std::istringstream iss(user_input);
char letter;
int index;
while(n>0)
{ cout<<n<<endl;
std::getline(std::cin, user_input);
while (iss >> letter >> index)
cout<<letter<<' '<<index;
n--;
}
}
int main()
{ int n;
cin>>n;
make(n);
return 0;
}
here loop is not running correctly
if i put n=5 then output is
5
//getline doesn't work
4
then getline works... why this

The reason why it's doing this, is because when you're calling getline(), it's taking what's in cin and putting it in the variable. However, when you initially called cin to take in the inital input, the newline character remained in the buffer after going into your make() function.
So when you enter the loop, the first getline() takes '\n' from cin, and the buffer was cleared. That's why it seems to "skip" the first iteration as it would seem.
So in order to get it to function correctly, you should clear your input buffer when you call your function using cin.ignore(), like so:
void make(int n)
{
cin.ignore(1000,'\n'); //ignores 1000 characters or until sees \n
std::string user_input;
std::istringstream iss(user_input);
char letter;
int index;
while(n>0)
{ cout<<n<<endl;
std::getline(std::cin, user_input);
while (iss >> letter >> index)
cout<<letter<<' '<<index;
n--;
}
}
int main()
{ int n;
cin>>n;
make(n);
return 0;
}
I haven't used c++ much recently, so at the moment, i'm not sure if there's a better way to handle this, but this should give you a good direction.

Related

reading space separated data and pushing it into proper contaner

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

For Loop should run one time but it is not running

When I enter "1", for loop should run one time. but it just prints "0". I don't know why.
I think the problem is with "getline(cin, input)" but i dont know the problem.
Here is the code:
int main()
{
string input;
int t, output, occured_length, lenght, match;
char occured[26];
cin>>t;
for(int i=0; i<t; i++) //I am talking about this loop
{
occured_length = 0;
getline(cin, input); //This might be causing the problem
lenght = input.size();
for(int j=0; j<lenght; j++)
{
if(occured_length == 25)
{
cout<<"\n"<<occured_length+1;
break;
}
match = 0;
for(int k=0; k<occured_length; k++)
{
if(input[j] == occured[k])
{
match= 1;
break;
}
}
if(match == 0)
{
occured_length++;
occured[occured_length] = input[i];
}
}
cout<<"\n"<<occured_length;
}
return 0;
}
input is empty & length is 0
istream& getline (istream& is, string& str);
Gets line from input stream into string. It extracts characters from is and stores them into str until the the newline character, '\n' is found.
\n remains in the input stream, you need to another dummy input reading, otherwise you will get input = "" on next getline
cin>>t;
char c;
cin >> c;
The problem is that after the input with using operator >>
cin>>t;
the input buffer will contain new line character. And next statement with getline
getline(cin, input);
reads an empty string.
You have to remove the new line character from the input buffer usig method ignore. For example
#include <limits>
//...
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
The call of ignore should be before getline and after operator >>.

String length getting reduced by using getline?

I am using getline and ignore but something is not working properly,
Below is the sample code which am not able to understand how it is working.
int main()
{
string str;
int t,length;
cin>>t; // t is the number of test cases
while(t--!=0)
{
cin.ignore();
getline(cin,str);
length=str.size();
cout<<"length="<<length;
}
}
Sample output:
2
hey hi
length 6
hey hi
length 5
Why is the length decreasing? Is this because of getline and ignore function? Any help would be appreciated.
The reason it is giving a different length is becaus your ignore() function ignores only one character. The first time round it ignores the return key you pressed after entering the number. But std::getline() deletes the return character for you. So the second time round ignore() deletes the first letter of your string making it "eh hi".
int main()
{
string str;
int t, length;
cin >> t; // does not remove the RETURN character
while(t-- != 0)
{
// first removed RETURN character after removes first letter
cin.ignore();
getline(cin, str);
length = str.size();
cout << "length = " << length;
}
}
Try using this instead:
int main()
{
string str;
int t, length;
cin >> t; // does not remove the RETURN character
while(t-- != 0)
{
// cin.ignore(); // dont do this here please
// cin >> ws skips all whitespace characters
// including the return character
getline(cin >> ws, str);
length = str.size();
cout << " length = " << length;
}
}
Alternatively (maybe better) you can move the ignore() function out of the loop to where t is really needed:
#include <limits>
int main()
{
string str;
int t, length;
cin >> t; // does not remove the RETURN character
// ignore as many characters as necessary including the return
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
while(t-- != 0)
{
// cin.ignore(); // not here
getline(cin, str);
length = str.size();
cout << " length = " << length;
}
}
The cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); looks complicated but it is the only way to guarantee that any spurious characters (like spaces) are removed. You can probably get away with just cin.ignore() for the exercise if you want.
Read up on std::istream::ignore()
cin.ignore() defaults to ignoring one character.
If you output your string each time, you'll see that in later cases the string is equal to "ey hi". The h is being dropped.
The value of the string held by cin drops its first character before being passed to getline.
Since you're using getline, you can simply remove the cin.ignore() from your loop and your program should work as intended.
However, you should also change your cin>>t; line. In this case, the ignore() is dropping the line return after the input value 2. A stringstream here allows for a getline(...) function, or alternatively you can use cin.ignore(str.max_size(), '\n');.
In the case of the stringstream, your code would become:
#include <sstream> // stringstream
#include <string> // std::string
#include <iostream> // cin
int main()
{
string str;
int t,length;
getline(cin, str);
std::stringstream stream;
stream << str;
if (!(stream >> t)) {
// Couldn't process to int
}
// cin>>t; // t is the number of test cases
// No longer need this line.
while(t--!=0)
{
// cin.ignore(); Drop this too
getline(cin,str);
length=str.size();
cout<<"length="<<length;
}
}
If you are not interested in whitespace,
then use getline(cin >> ws, str)

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

Transformation to lower case in C++

#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include <string>
#include <algorithm>
using namespace std;
string A,B;
int main()
{
int t,l,i;
scanf("%d",&t);
while(t--)
{
std::string str;
std::getline(cin, str);
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
cout<<str;
/*for(i=0;i<s.length();i++)
{
s[i]=toupper(s[i]);
}*/
}
return 0;
}
i wrote this code to convert to lower case but when run on ideone with input
1
hola please!!!
it shows output no can u tell or correct it morever this will help me learn the use of std:lowercase function taking getline cin as input rather than considering it as array
The problem is definitely with the way you are reading in. scanf("%d",&t); doesn't consume the return character, so it is still there on the getline, which will get an empty sting. Change it to scanf("%d\r",&t).
If you simplify the code, the problem can be reduced to:
int main() {
int t;
scanf("%d",&t);
std::string str;
std::getline(cin, str);
std::cout<<str;
}
This is because scanf reads from the input until it reaches a character that doesn't match, and it leaves that character in the input buffer. You input is "1\nhola please!\n\0", so scanf reads the 1, and leaves the rest: "\nhola please!\n\0". Then, you tell it to read until the next \n is found, which is immediately, so it returns an empty string.
The solution is: after using std::cin >> or scanf or whatever, if the next thing you want to do is read the rest of the line, you want to ignore that leading newline character. The C++ way to do this is std::cin.ignore(0xFFFFFFFF,'\n');, which will ignore the rest of the line. Alternatively, use scanf("%d\n" &t); to get the scanf to read in the newline character.
Related, you never check the validity of any of your input:
int main() {
int num_lines=0; //variables on different lines and initialized
std::cin >> num_lines
if (!std::cin)
return 1;
std::string str;
for(int j=0; j<num_lines && std::getline(sd::cin, str); ++j) {
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
std::cout << str;
}
return 0;
}
Or simply use < boost/algorithm/string.hpp > header and function boost::to_lower().
int t = 0;
scanf("%d",&t);
std::cin.ignore();
while(t--) {
std::string str;
std::getline(cin, str);
boost::to_lower(str);
std::cout << str << std::endl;
}