Why is getline taking one extra line? - c++

why the for loop execute m-1 times instead of m.
I have used getline() to enter string instead of cin>>.
Here is my code.
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <cstdio>
using namespace std;
int main() {
int n;
int m;
int a;
cin >> n >> m;
int arr[10000];
for(int i = 0; i < n; i++) {
cin >> arr[i];
}
char s[200];
ostream_iterator<int> screen(cout," ");
for(int i = 0; i < m; i++) {
cin.getline(s,20);
int p = s[2]-48;
cout << p << endl;
}
}

Because this:
cin>>n>>m;
Has not read the end of line character from the first line.
Thus the first time through the loop.
cin.getline(s,20);
Will read an empty line.
PS. Prefer to use the string reading version of getline(). That way you guarantee that you can always read a full line.

After last cin>>arr[i], there is a newline remaining in the stream. So the new line will be assigned to s at the first iteration in the for loop without your input, so it looks like the for loop only iterates m-1 times. See this link for the explanation and solution.

Related

Can we use vector in c++ to take user input of unknown size only till we hit enter?

I was trying to take user input in a vector in c++, as vector is a dynamic data structure i wanted it to take input as long as user wants and when the user hit enter key it should stop taking the input (just as a string) only difference i want to do it in an integer vector, but i am unable to do so let me know if it is possible or not to take user input in a vector like the way i described.
I have searched the web for various ways but still my code isn't running the way i want, I have tried breaking the loop of input by using EOF symbols but it is not stopping the loop of input.
I have tried using cin.ignore() function but it also takes spacebar in count
i only want to stop input when enter key is pressed.
below is the most recent code i made:
#include<bits/stdc++.h>
using namespace std;
int main(){
vector<int> v;
char c;
for(int i=0;;i++){
cin>>c;
if(c=='\n'){
break;
}
int x = c - '0';// typecasting char into integer.
v.push_back(x);
}
cout<<v.size()<<endl;// just to check if it is done taking input and what is the size of vector now.
}
You can use std::getline() to get the entire line and then std::istreamstream to get the integers into a vector:
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <iterator>
int main() {
std::string input;
std::getline( std::cin, input );
std::istringstream is( input );
std::vector<int> v( ( std::istream_iterator<int>( is ) ), std::istream_iterator<int>() );
std::cout << v.size() << "\n";
return 0;
}
Read the entire line as string and build each number. Something like that:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
string s; getline(cin, s);
int num = 0;
vector<int> v;
for(int i = 0; i < s.size(); ++i)
if(s[i] == ' ')
v.push_back(num), num = 0;
else
num = num*10 + (s[i]-'0');
v.push_back(num);
cout << v.size() << endl;
return 0;
}
You just have to input Vector elements as a single string and use Stringstream function to assign elements in increasing order of vector's indices respectively.
Here's the code :
#include<bits/stdc++.h>
using namespace std;
int main()
{
vector<int> v;
string buffer;
int data;
getline(cin,buffer);
istringstream iss(buffer);
while(iss>>data){
v.push_back(data);
}
cout<<v.size()<<" ";
cout<<"Vector Elements"<<endl;
for(int k=0;k<v.size();k++){
cout<<v[k]<<" ";
}
return 0;
}
When you read from std::cin, it will accept an entire line from the console. Your cin>>c will retrieve the first character of the line and put that character into the variable c.
This means your if(c=='\n') is pretty much pointless since the line will be consumed and you won't see an explicit '\n' as the first character...EVER.
c - '0' will convert a single ASCII character that is a digit (i.e. 0123456789) to a number you can use, but that is NOT typecasting a char into an integer. That's converting an ASCII character that happens to be a number into a numeric value. A type cast is when you change the TYPE of a value to another TYPE.
I think you want to do something like the following...
#include <iostream>
#include <vector>
#include <stdio.h>
#include <conio.h>
int main( int cArguments, const char** apszArguments ) {
std::vector<char> vchars;
char c;
do {
c = getche();
vchars.push_back( c );
} while( c != '\n' );
std::cout << vchars.size() << " characters received" << std::endl;
return 0;
}
Note that on macOS and some Linux variants, getch/getche are not defined and you'll need to use termios or ncurses functions instead.

Best way of summing up an input of string of numbers

The Problem
Currently I am looking at a problem on HackerRank where the input comes in the format of:
4
6 7 8 9
Basically the first line specifies the number of input integers and the second line specifies all the integers that follow. Seems pretty easy, but not sure as to why my program is not working.
My Solution
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <string>
#include <algorithm>
int main(){
int n;
std::cin >> n;
// Get all the numbers
std::string rawInput;
std::cout << "we have reached here 1";
std::cin >> rawInput;
std::cout << "we have reached here 2";
std::vector<std::string> numbers;
std::string number = "";
for (int i = 0; i < rawInput.size(); i++) {
char c = rawInput[i];
if (c == ' ') {
numbers.push_back(number);
}
number += c;
}
// Get all the ints
int sum = 0;
std::cout << sum;
for (int j = 0; j < n; j++) {
sum += stoi(numbers[j]);
}
std::cout << sum;
return 0;
}
Errors
Now I don't see the debugging cout line: std::cout << "we have reached here 2";. I am not sure as to why this is the case.
Debugger Output
DB trace:
Reading symbols from solution...done.
[New LWP 18595]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `solution'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x0000000000401042 in __gnu_cxx::__stoa<long, int, char, int> (
__idx=<optimized out>, __str=<optimized out>, __name=<optimized out>,
__convf=<optimized out>) at /usr/include/c++/6/ext/string_conversions.h:68
68 const _TRet __tmp = __convf(__str, &__endptr, __base...);
#0 0x0000000000401042 in __gnu_cxx::__stoa<long, int, char, int> (
__idx=<optimized out>, __str=<optimized out>, __name=<optimized out>,
__convf=<optimized out>) at /usr/include/c++/6/ext/string_conversions.h:68
#1 std::__cxx11::stoi (__base=10, __idx=0x0, __str=...)
at /usr/include/c++/6/bits/basic_string.h:5414
#2 main () at solution.cc:32
The direct cause of the crash is the assumption that n is correct. You never confirmed it in your code, but go on to use it when iterating over numbers. You then overrun numbers and cause stoi to blow up.
In fact, n is not 4! It's only 1 because your second line of input is broken. Simply print out the value of rawInput and you'll see.
To read the line 6 7 8 9, you want std::getline(std::cin, rawInput). Formatted extraction to a std::string (which you're using now) will only pull out the first "token"; i.e., just 6.
However, when switching to std::getline, you will now need the newline-skipping antics explored in Topological Sort's answer, since non-formatted extraction does not skip whitespace in the same way.
Finally, you never clear number after adding it to the vector, and you never handle the final value.
I also suggest adding some newlines to the ends of your output statements.
Here's a fixed program:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <string>
#include <algorithm>
int main(){
int n;
std::cin >> n;
// Get all the numbers
std::string rawInput;
std::cin.ignore(256,'\n');
std::getline(std::cin, rawInput);
std::vector<std::string> numbers;
std::string number = "";
for (size_t i = 0; i < rawInput.size(); i++) {
char c = rawInput[i];
if (c == ' ') {
numbers.push_back(number);
number = "";
}
number += c;
}
// One more! If there wasn't a space at the end of it.
if (!number.empty())
numbers.push_back(number);
// Get all the ints
int sum = 0;
for (size_t j = 0; j < numbers.size(); j++) {
sum += stoi(numbers[j]);
}
std::cout << sum << '\n';
}
(live demo)
I would actually recommend just sticking with formatted extraction throughout, which is much simpler:
#include <vector>
#include <iostream>
#include <numeric>
#include <algorithm>
int main()
{
int n;
std::cin >> n;
// Get all the numbers
std::vector<int> numbers;
int temp;
while (std::cin >> temp)
numbers.push_back(temp);
const int sum = std::accumulate(numbers.begin(), numbers.end(), 0);
std::cout << sum << '\n';
}
Note that we don't need n at all any more! But if you want to artificially constrain the extraction to just n numbers, you can do that in your while loop.
(live demo)
This line reads a single whitespace-delimited token (see the documentation):
std::cin >> rawInput;
and this loop runs once for every character in that token, not for every integer on the line (rawInput will only contain the first integer)
for (int i = 0; i < rawInput.size(); i++) {
and finally this loop doesn't check whether n and numbers.size() are at all related:
for (int j = 0; j < n; j++) {
So you:
overrun the bounds of numbers by using the wrong loop condition
didn't understand or check the contents of rawInput
didn't understand or check how the formatted input operators work.
Just printing your variable values (or examining them in gdb) would show this - printing we have reached here 1 is much less useful than printing the value of rawInput is "6" (which would have given you a very strong hint).
On top of those, the correct code can actually use those formatted input operators to do most of the work:
#include <iostream>
int main()
{
unsigned N = 0;
std::cin >> N;
if (!std::cin) return -1;
unsigned SUM = 0;
for (unsigned i = 0; i < N; ++i) {
unsigned val;
std::cin >> val;
if (!std::cin) return -2;
SUM += val;
}
std::cout << SUM << '\n';
}
I even included sample error-checking, which you could probably omit from a hackerrank test. It's still much, much shorter and simpler than your version.
The approach you are using is not correct! You are assuming that the number will only have one digit which might not be the case always.
You can simply use cin in a for loop and store all the numbers in a vector.
#include <iostream>
#include <vector>
int main() {
int n;
std::vector<int> numbers;
std::cin >> n;
for(int i=0;i<n;++i)
{
int no;
std::cin >> no;
numbers.push_back(no);
}
long sum = 0;
for (auto i : numbers)
sum += i;
std::cout << sum;
return 0;
}
Input
5
1 2 31 4 5
Output
43
Oh, I see this all the time. It's subtle.
std::cin >> n;
only reads in the first int. It doesn't pay any attention to the end-of-line that comes after. So when you're ready to read in that string, it goes to the end of the line -- the first line, the one that's got n on it.
Fix:
std::cin >> n;
std::cin.ignore(256,'\n'); //ignore up thru next '\n' or 256 chars, whichever is first
This skips that end of line and lets you start on the next.
Another fix, less robust:
std::cin >> n;
std::cin.get(); //Gets the next char, which in this case happens to be '\n'
You also need to change std::cin >> rawInput; to
char rawInputCharStar [SOMEBIGNUM];
std::cin.getline (rawInputCharStar,SOMEBIGNUM);
rawInput = rawInputCharStar
so it can read in more than one of the strings. (I had to go to char* because getline expects a char*. There may be a more elegant way.)
When you get to the for loop, you'll find that the number of numbers in the string is NOT the size of the string, so you need different bounds.
(Of course, I dont' know why you're not just reading them all in as ints, but you must have a reason.)

get several integer numbers with c++-CIN and put them into array

i need to get couple integer numbers and put them into an array in c++.
assume the count of numbers in CIN are the same count as array length.
int numbers[10];
cin>>numbers;
In fact i want to enter 10 numbers to cin within one line somehow it automatically allocates the numbers to array. how should i do it?
Here is a C++11 solution using std::vector and std::copy_n.
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
int main()
{
std::vector<int> v;
std::copy_n(std::istream_iterator<int>(std::cin), 3, std::back_inserter(v));
}
You can use a loop:
#include <iostream>
int main()
{
int numbers[10];
for (int i = 0; i < 10; ++i)
std::cin >> numbers[i];
}
UPDATE:
If it has to be one line then you could use this (somewhat clumsy solution):
#include <iostream>
int main()
{
int numbers[3];
std::cin >> numbers[0] >> numbers[1] >> numbers[2];
}
Alternatively, you can use std::cin.getline and then parse the string.
UPDATE (again):
#include <iostream>
int main()
{
int numbers[3];
int* input = numbers;
while (std::cin >> *input++ and input != 3 + numbers) ;
}

C++ Using std::getline in place of cin >>

In a problem were i have to take n number of strings as input and count the ones containing a given substring(case insensitive).
Here's my code:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include<string>
using namespace std;
int main()
{
std::string str2 = "hello";
std::string str3 = "HELLO";
short int n,count=0,i;
cin>>n;
std::string str1[n];
for(i=0;i<n;i++)
{
std::getline(std::cin,str1[i]); //here getline is taking only n-1 inputs
std::size_t found1=str1[i].find(str2);
std::size_t found2=str1[i].find(str3);
if(found1!=std::string::npos || found2!=std::string::npos)
count++;
}
cout<<count;
return 0;
}
Since i cant use cin as string includes spaces or cin.getline() as have to use string type in place of char[].
Problem with my code is std::getline() is only taking n-1 inputs.Cant figure out why?
The first getline after cin reads the remainder of the line, which is probably empty. This is why when reading user input, it is usually better to use getline and process input using code.
After cin >> n the input stream is positioned just after the number n. You can use a getline just to read the newline and then throw it away to position to the start of the next line.
This code should work
#include <iostream>
#include <string>
using namespace std;
int main() {
int n = 0, count = 0;
cin >> n;
do {
string str;
getline(cin, str);
if (str.find("HELLO") != string::npos || str.find("hello") != string::npos) {
count++;
}
} while (n-- && n >= 0);
cout << count << endl;
return 0;
}

String not getting stored in vector?

#include <iostream>
#include <vector>
using namespace std;
int main()
{
string n, m;
vector <string> dingdong;
cin >> n;
dingdong.push_back(n);
cin >> m;
dingdong.push_back(m);
for (int i = 0; i <2; i ++) {
cout << dingdong[i];
}
return 0;
}
When I run the program and I input "hay sombody there" and hit enter. The program prints "haysombody." So I figured if I increase 'i' to 3 the program will print "haysombodythere" but no, main just crashes. why is this happening and how do I make it so that the entire strings (including the spaces) get stored?
"why is this happening and how do I make it so that the entire strings (including the spaces) get stored?"
To get more than a single word from the input you should use
std::getline(cin,n);
instead of
std::cin >> n;
White spaces are used as delimiters by default, so each call of std::istream's operator>> will just store the text read up to the next white space character.
See a fully fixed version of your program here please.
Also if you really want to read into the vector word by word, you use a loop doing so
string word;
vector <string> dingdong;
while(cin >> word) {
if(word.empty) {
break;
}
dingdong.push_back(word);
}
and print out like
for (int i = 0; i < dingdong.size(); ++i) {
cout << dingdong[i];
}