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.)
Related
For solving problems on Leetcode, Kickstart or other competitive competitions, we need to take input of multiple integers in a single line and store them in an array or vector, like
Input : 5 9 2 5 1 0
int arr[6];
for (int i = 0; i < 6; i++)
cin >> arr[i];
or
vector<int> input_vec;
int x;
for (int i = 0; i < 6; i++) {
cin >> x;
input_vec.push_back(x);
}
This works, but also contributes to the execution time drastically, sometimes 50% of the execution time goes into taking input, in Python3 it's a one-line code.
input_list = list(int(x) for x in (input().split()))
But, couldn't find a solution in C++.
Is there a better way to do it in c++?
Take the help of std::istringstream:
#include <iostream>
#include <vector>
#include <sstream>
#include <string>
int main(void) {
std::string line;
std::vector<int> numbers;
int temp;
std::cout << "Enter some numbers: ";
std::getline(std::cin, line);
std::istringstream ss(line);
while (ss >> temp)
numbers.push_back(temp);
for (size_t i = 0, len = numbers.size(); i < len; i++)
std::cout << numbers[i] << ' ';
return 0;
}
How to take multiple integers in the same line as an input and store them in an array or vector in c++?
Like this:
int arr[6]; for(int i=0;i<6;i++){ cin>>arr[i]; }
I am working on a programming exercise, "Count of camel case characters" using C++. The goal of the exercise is to count the number of upper-case letters in a given string (what the exercise calls "camel case").
So given the following two inputs:
ckjkUUYII
HKJT
I would expect to get the following counts respectively:
5
4
Based on the code I've include below, however, I am instead getting:
0
5
This is clearly incorrect, but I've having difficulty isolating the problem in my code. How can I reason through this problem, or debug my error?
#include <iostream>
#include <cstring>
using namespace std;
int main() {
int t;cin>>t;
while(t--)
{
int res=0;
string str;
getline(cin,str);
int len= str.length();
for(int i=0;i<len;i++)
{
int c=str[i];
if(isupper(c))
res=res+1;
}
cout<<res<<endl;
}
//return 0;
}
After entering integer value as t, in input buffer newline character is left. So first call of getline gives you empty string as a result. You have to do:
int t;
cin >> t;
cin.ignore();
while (t--) {
...
}
to consume newline character, then both calls of getline will return entered strings properly.
The main problem is that you are trying to convert a character into an integer in line 15. An integer can't be either uppercase or lowercase. hence it gives the wrong answer. Simply check isupper(s[i]) as it would give the correct answer.
Consider my code,
#include <bits/stdc++.h>
using namespace std ;
int main() {
int t ; cin >> t ;
while(t--) {
string s ; cin >> s ;
int cnt = 0 , ln = s.size() ;
for(int i = 0 ; i < ln ; i ++) {
if(isupper(s[i])) cnt ++ ;
}
cout << cnt << endl ;
}
return 0;
}
So guys, Actually What I wanna do here is that when I input 3,12,36 the output will be:
3
12
36
But here I have difficulty on how to make it output all the answer. What I have been doing is that when you input 3,12,36 it will output 3 12 only and if you type 3,12,36,48 it will output 3 12 36.
So it will always miss the last integer because my while loop is not correct I guess. but if I change it into
while(output >> life|| output >> ch)
It doesn't work either. I've done a lot of research but it still makes me confused and I'm still stuck on this part.
vector<int> parseInts(string str) {//23,4,56
vector<int>lifeishard;
stringstream output;
string lifeisgood = str;
output.str(lifeisgood);
int life;
char ch;
while(output >> life >> ch){
lifeishard.push_back(life);
//lifeishard.push_back(life2);
//lifeishard.push_back(life3);
}
return lifeishard;
}
int main() {
string str;
cin >> str;
vector<int> integers = parseInts(str);
for(int i = 0; i < integers.size(); i++) {
cout << integers[i] << "\n";
}
return 0;
}
On your last number, the while loop fails because there's no character at the end. Just the end of the string. So it doesn't execute the push_back inside the loop.
Change it so that the while loop just gets the number. Then do the push_back in the loop. Then in the loop, after the push, get the comma character. Don't bother checking for failure getting the comma because when it goes around the while loop again it will fail and exit.
I changed to using getline in your main. I changed your loop index to size_t because it is never a good idea to mix signed and unsigned integers, and whenever you use a size() function, it's a size_t. When posting your program it really should include everything. My fixed up version of your program:
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
using namespace std;
vector<int> parseInts(string str) {//23,4,56
vector<int>lifeishard;
stringstream output;
string lifeisgood = str;
output.str(lifeisgood);
int life;
char ch;
while(output >> life){
lifeishard.push_back(life);
output >> ch;
}
return lifeishard;
}
int main() {
string str;
getline(cin, str);
vector<int> integers = parseInts(str);
for(size_t i = 0; i < integers.size(); i++) {
cout << integers[i] << "\n";
}
// Here is how we do for loops over containers in modern C++
for(auto x: integers) {
cout << x << '\n';
}
return 0;
}
A combination of stringstream, getline with delimiter and stoi would be enough for the conversion:
From the C++ reference for getline with delimiter:
Extracts characters from is and stores them into str until the delimitation character delim is found.
With this in mind, the code example below assumes the input is well-formed:
Example
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
vector<int> parseInts(const string& str, const char delim = ',')
{
vector<int> parsed;
stringstream ss(str);
string s;
while (getline(ss, s, delim)) // <- stores input in s upon hitting delimiter
parsed.push_back(stoi(s)); // <-- convert string to int and add it to parsed
return parsed;
}
int main()
{
string str = "3,12,36"; // <-- change to cin if you'd like
vector<int> ints = parseInts(str);
for (auto& i : ints)
cout << i << "\n";
}
Output
3
12
36
See more: getline, stoi
#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];
}
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.