c/c++ scanf/cin reads int from multiple lines - c++

I'm doing some basic input parsing in c/c++.
format: number of values, followed by space separated values:
3
5 2 4
The problem here is the lack of a space after the first line. This causes cin and scanf to read 35 into the first variable, instead of 3.
int num;
scanf("%d", &num);
int array[num];
for (int i = 1; i <= num; i++) {
scanf("%d", &array[i]);
}
How do I get cin, or scanf, to stop parsing at a newline?
Edit:
Is it bad not to init variables even if they are written to later, before being read? (int num)
It works if I type the input in, but not if I paste it. Any clue?

std::cin interprets newline characters as spaces so there is the possibility the file you are working with contains something other than a newline. You are also using a non-standard extension to declare the array. This is not portable and not guaranteed to be supported by all compilers. I suggest you switch to using std::vector instead.
Your for loop is also incorrect. Array's used zero based indexing to access their elements. Because of this you end up accessing the array out of bounds which is undefined behavior. This means your program might crash, it may overwrite other variables or you might not notice any symptoms at all. This may also cause the symptom you are experiencing if it overwrites other variables.
The example below uses C++ input streams instead of scanf to provide better error checking.
#include <istream>
#include <vector>
std::vector<int> load(std::istream& in)
{
std::size_t count;
std::vector<int> data;
// If the user does not enter a number "in >> count" will fail.
if (in >> count)
{
int value;
while (count-- && in >> value)
data.push_back(value);
}
return data;
}
#include <iostream>
int main()
{
auto data = load(std::cin);
for (auto i : data)
std::cout << i << std::endl;
}
You can test this without reading from a file by using std::stringstream as the input.
#include <iostream>
#include <sstream>
int main()
{
std::stringstream text("3\n5 2 4");
auto data = load(text);
for (auto i : data)
std::cout << i << std::endl;
}

Within the for loop you started the array at position 1 and not 0. Which would cause going out of bounds, as you wanted to write to element 2 of the array. If you allocate an array of 2 elements the valid elements are going to be 0 and 1. This code works:
int num;
scanf("%d", &num);
int array[num];
for (int i = 0; i < num; i++)
{
scanf( "%d", &array[i] );
}

Start array from 0 as array indexes start from 0 - like:
for (int i = 0; i < num; i++)
You are starting first element from 1 that makes it undefined. Moreover, you should make dynamic array.

I liked Lidong Guo's code, and have modified it to run with Microsoft's C Compiler.
The only change was to move all of the data definitions ahead of any executable code, plus I added a space between the printed numbers.
#include <stdio.h>
#include <stdlib.h>
main()
{
int num;
int *array; //[num];
int i;
scanf("%d\n", &num);//here deal with the newlinw
array= malloc(sizeof(int) *num);//[num];
for (i = 0; i < num; i++)
{//the loop .start 0 end num -1
scanf("%d", &array[i]);
}
for (i = 0; i < num; i++)
{
printf("%d ", array[i]);
}
free(array);
}

[Edit: The Answere is specific to C++, as the Question also have a C++ tag]
Well first thing first.
You array defination is wrong .
int array[num]; // Super wrong way
You are not supposed to pass a variable as index while defining an array, its not allowed. Else, it will cause "nasal demon".
int * array = new int[num] //correct way
The code might be working correctly now but the array definition given by you lies under the category of UB.

#include <stdio.h>
#include <stdlib.h>
int main()
{
int num;
scanf("%d", &num);
int *array= malloc(sizeof(int) *num); // num is known at runtime
int i;
for (i = 0; i < num; i++) { //starts at 0, ends at num - 1
scanf("%d", &array[i]);
}
for (i = 0;i< num; i++) {
printf("%d", array[i]);
}
free(array);
}

Change the
scanf
statement to
scanf("%d", &array[i]);
Also array indexing starts from 0 and ends at num-1

Start your loop from 0 and end it at num-1,i.e
for (int i = 0; i < num - 1; i++)
scanf("%d", &array[i]);
And the reason for pasted input does not work is that it doesn't contain newline between two lines

Related

C++ problem where the value assigned to a variable is getting changed even though it hasn't been modified yet [duplicate]

This question already has answers here:
Uninitialized variable behaviour in C++
(4 answers)
Closed 1 year ago.
Please help me with this strange problem where the input value is given as 4 (i.e. n = 4) and after a for loop the same value is getting displayed as 2, but why? It was not used anywhere (AFAIK) and it shouldn't get changed (I have no clue about it).
The original problem on HackerRank.
MY CODE >>
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int n;
int arr[n];
cin >> n; // input given from stdin is 4
cout << n << "\n"; // outputs 4
for(int i=0; i<n; i++){
scanf("%d",&arr[i]);
}
cout << n << "\n"; // outputs 2 (but why?)
for(int i=n-1; i>=0; i--){
printf("%d ",arr[i]); // if it were n = 4, then i will go from 3 to 0, but it goes from 1 to 0 (as n=2, but again, why?)
}
return 0;
}
Thank you for any help!
int n;
int arr[n]; // <<<<<< I magically know what n will be after the user types it!
cin >> n; // input given from stdin is 4
First of all, that's not even legal in C++. As a gcc extension to support C style VLA's, what is the value of n when the array declaration is seen? You have not read it yet!!
Instead, use:
int n;
cin >> n;
std::vector arr(n);
Although this still is not the "C++ way" as you are pre-defining the entire collection and then assigning to each element in turn; as opposed to adding each element to the collection. This is not a big deal with an int but more generally you don't want dead unused items in a collection; rather they simply don't exist at all.
std::vector arr; // don't pre-allocate any size
for(int i=0; i<n; i++){
int val;
scanf("%d",&val); //<<< uhhhhhh. you know about `cin` why this?
arr.push_back(val);
}

Modification of counting sort

The Counting sort below sorts elements based on their ASCII value.
The code below works fine but I want to do some I/O modification. The code doesn't take custom input.
I tried to do some changes but getting undefined behavior. My first doubt is why I'm getting undefined behavior. secondly, Please provide me with the code which will make the below code run as expected. The comment portion is what I tried by myself.I want it to take input from user.
#include<bits/stdc++.h>
#include<string.h>
using namespace std;
#define RANGE 255
void countSort(char arr[]) //void countSort(char arr[],int n)
{
char output[strlen(arr)]; //char output[n];
int count[RANGE + 1], i;
memset(count, 0, sizeof(count));
for(i = 0; arr[i]; i++) {
count[arr[i]]++;
}
for (i = 1; i <= RANGE; ++i) {
count[i] += count[i-1];
}
for (i = 0; arr[i]; ++i) {
output[count[arr[i]]-1] = arr[i];
--count[arr[i]];
}
for (i = 0; arr[i]; ++i) {
arr[i] = output[i];
}
}
// Driver code
int main()
{
char arr[] = "geeksforgeeks";
countSort(arr);
cout<< "Sorted character array is "<<arr;
/*
int n;
cin>>n;
char arr[n];
for(int i=0;i<n;i++) {
cin>>arr[i];
}
countSort(arr,n);
for(int i=0;i<n;i++) {
cout<<endl<<arr[i];
}
*/
return 0;
}
So the OP asked, how to take an input from the user and sort this. And not a predefined string in a given char array.
I will give the answer. But the question is tagged with C++, and I will convert it to C++.
By the way. The code in the question is a one to one copy from GeeksforGeeks and tries to code the so called Counting Sort algorithm in C++ that is described here.
Since the code is taken from GeeksforGeeks I unfortunately need to blame user "rathbhupendra" for really bad C++ code. I am truly sorry.
The code is using:
C-Style arrays
Variable Length Arrays (Compiler extension. Not C++ compliant)
strlen
memset
#include<bits/stdc++.h> and #include<string.h>
using namespace std
unusal end conditions in for loops for(i = 0; arr[i]; ++i)
char arrays instead of std::strings
a Macro to define an array size (#define RANGE 255)
So, nothing C++.
And now, the answer.
You need to read the string from the user in a variable of type std::string with the function std::getline.
A std::string can be used like a character array. No difference.
Please see the C++ solution:
EDIT
Edited on the comments of MichaelDorgan
#include <iostream>
#include <string>
#include <vector>
constexpr size_t AsciiRange = 256;
// Convert signed char to unsigned size_t type.
inline size_t char2sizet(char c) { return static_cast<size_t>(static_cast<unsigned char>(c)); }
void countSort(std::string& stringToSort)
{
std::vector<size_t> count(AsciiRange, 0U);
size_t i { 0U };
for (i = 0U; i < stringToSort.size(); i++) {
count[char2sizet(stringToSort[i])]++;
}
for (i = 1U; i < AsciiRange; ++i) {
count[i] += count[i - 1U];
}
std::string output(stringToSort);
for (i = 0U; i < stringToSort.size(); ++i) {
output[count[char2sizet(stringToSort[i])] - 1U] = stringToSort[i];
--count[char2sizet(stringToSort[i])];
}
stringToSort = output;
}
int main()
{
std::cout << "\nPlease enter a string:\n\n";
// Get the string from the user
std::string inputString{};
getline(std::cin, inputString);
// Sort it by characters
countSort(inputString);
// Show result
std::cout << "\n\n\nString sorted by characters is:\n\n" << inputString << '\n';
return 0;
}
Hope this helps . . .
I geuss by 'getting undefined behavior' you meant segmentation fault which sometimes occured. The problem lies in this line
for(i = 0; arr[i]; i++)
instead you should write
for(i = 0; i < n; i++)
You can check that in the first case at the end of each loop arr[i] is sometimes some weird character(this character doesn't belong to the input string) and count[arr[i]] for this char returns negative number which produce segmentation fault here
output[count[arr[i]]-1] = arr[i];

Printing an array in reverse

Task
You'll be given an array of N integers and you have to print the integers in the reverse order.
Constraints
1<=N<=1000
1<=A_i<=10000, where A_i is the ith integer in the array.
Input
4
1 2 3 4
Output
4 3 2 1
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int N, y; //declaring N as the length of array
cin >> N; //intakes the length as an input
if (N>=1 && N<=1000){ //checks whether the length satisfies the rules
int a[N]; // makes an array containing N elements
for (int x =1; x<N; x++){ //starts transcription on the array
cin>>y; //temporarily assigns the input on a variable
if (y>=1&&y<=10000){ //checks if the input meets rules
a[x]=y; //copies the variable on the array
}
}
for (int z = N; z>1; z--){ //runs a loop to print in reverse
cout<<a[z]<<endl;
}
}
return 0;
}
Problem
Obtained output is
-1249504352
3
2
Indicating an error in transcription.
Question
Can somebody please tell me where I am making a mistake? Secondly, is it possible to directly check whether an input is meeting requirement rather than temporarily declaring a variable for it?
Here is a solution in idiomatic c++11, using std::vector, which is a dynamically resizable container useful for applications like this.
#include <vector>
#include <iostream>
#include <algorithm>
int main() {
int size;
std::cin >> size; // take in the length as an input
// check that the input satisfies the requirements,
// use the return code to indicate a problem
if (size < 1 || size > 1000) return 1;
std::vector<int> numbers; // initialise a vector to hold the 'array'
numbers.reserve(size); // reserve space for all the inputs
for (int i = 0; i < size; i++) {
int num;
std::cin >> num; // take in the next number as an input
if (num < 1 || num > 10000) return 1;
numbers.push_back(num);
}
std::reverse(numbers.begin(), numbers.end()); // reverse the vector
// print each number in the vector
for (auto &num : numbers) {
std::cout << num << "\n";
}
return 0;
}
A few things to note:
using namespace std is considered bad practice most of the time. Use (e.g.) std::cin instead for things which come from the std namespace.
numbers.reserve(size) is not necessary for correctness, but will make the program faster by reserving space in advance.
for ( auto &num : numbers ) uses a range-based for loop, available in c++11 and later versions.
You could make your for loop indices go from high to low:
for (int i = N-1; i > 0; --i)
{
std::cout << a[i] << "\n"; // Replace '\n' with space for horizontal printing.
}
std::cout << "\n";
This would apply with std::vector as well.
With std::vector, you can use a reverse iterator. There are other techniques available (as in other answers).

how can we do n nested for loops where n is dynamic [duplicate]

This question already has answers here:
c++ : dynamic number of nested for loops (without recursion)
(3 answers)
Closed 6 years ago.
I have read the following questions but have not found a solution to my problem:
c++ : dynamic number of nested for loops (without recursion)
variable nested for loops
actual problem statement is :-
Job and Jimmy both are playing with numbers. Job gives Jimmy an array of numbers and asks him to tell the minimum possible last number of a non decreasing sequence of length L.
Input Format
First input line consists of a number which is size of array N.
Next line contains N space separated elements of array.
Next line contains length of the non decreasing sequence i.e. L.
Output Format
You have to print the minimum possible last number of a sequence and if their is no non-decreasing sequence of length L, then print -1
Sample Input
7
9 7 2 5 4 11 12
3
Sample Output
11
Explanation
In sample input, possible non-decreasing sequences of length L=3 are (9,11,12) , (7,11,12) , (2,5,11) , (2,4,11) , (2,5,12) , (2,4,12) , (2,11,12) , (5,11,12) , (4,11,12) and the minimum last number is 11 for the sequences (2,5,11) and (2,4,11). Hence, the answer is 11."
my code...
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int fact(int y,int x)
{
static int temp=0;
if(temp==x)
{
temp=0;
return 1;
}
else
{
++temp;
return y*fact((y-1),x);
}
}
int main() {
int num,randmax,n,s,q,w last=-1, minlast=-1;
cin>>n;
vector<int> a(n);
for(int i=0;i<n; i++)
{
cin>>a[i];
}
cin>>s;
vector<vector<int>> c;
q=fact(s);
c.resize(q);
for(int i = 0 ; i < q ; ++i)
{
//Grow Columns by n
a[i].resize(s);
}
w=q;
randmax=n-1;
int k=0;
while(w)
{
for(int i=0 ; i<n ; i++){
}
num=rand()%randmax; // this works perfect as expected
c[][i]=a[num];
}
w--;
}
/*for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
for(int k=j+1;k<n; k++)
{
if((a[i]<=a[j])&&(a[j]<=a[k]))
{
last=a[k];
if(minlast=-1)
{
minlast=a[k];
}
if(last<minlast){
minlast=last;
}
}
}
}
}
*/
cout<<last;
return 0;
}
`
I would tell you what I tried to do... I thought of mapping the data by having them randomly assigned in one of my array and then computing them..
I got lost somewhere in my code...plz gimme an solution to it...and more imp. a good explanation of the same as I got stuck at times when I need a dynamic nested n loop type of thing...
also it would be more helpful if you edit in my code or algo so that I could learn where my mistakes are there...
Thanks in advance for you time...
As the answers your links have pointed out, you can imitate a dynamic amount of for loops by using an array David gives a fine implementation here.
For the actual problem you gave though, I see no need for a dynamic amount of for loops at all. The problem is a standard non-decreasing subsequence problem with a slight variation.
#include <iostream>
#include <fstream>
int N, L;
int arr[100], seq[100];
int bst;
int main() {
std::ifstream file ("c.txt");
file >> N;
for(int n = 0; n < N; ++n)
file >> arr[n];
file >> L;
file.close();
bst = 1e9;
for(int i = 0; i <= N; ++i) seq[i] = 1e9;
for(int i = 0; i < N; ++i)
{
int x = 0;
while(seq[x] < arr[i]) ++x;
seq[x] = arr[i];
if(x + 1 >= L)
bst = std::min(bst, arr[i]);
}
std::cout << bst << std::endl;
return 0;
}
This code should solve your problem. The first part does standard parsing and initialization. The rest is a variation on the LIS problem, which has several standard algorithms that solve it. Here, we just check that whenever we extend an array of length L or longer, we see if the element is smaller than our current.

C++ random 0xC0000005 errors

I made a program which converts n decimal numbers sk into other numerical system p but sometimes it crashes and the error code I get is 0xC0000005 (program still converts and outputs all the numbers) . One thing I just noticed that it happens then converted number is longer than 6 symbols (or it's just a coincidence).
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
long n,sk,p,j;
string liekanos;
ifstream f("u1.txt");
f >> n;
for (int i=0;i<n;i++)
{
f >> sk >> p;
j=0;
while (sk>0)
{
liekanos[j]=sk % p;
sk/=p;
j++;
}
for (j>=0;j--;)
{
if (liekanos[j]<10)
cout<<int(liekanos[j]);
else cout<<char(liekanos[j]+55);
}
cout<<endl;
}
return 0;
}
Example input:
3
976421618 7
15835 24
2147483647 2
With liekanos[j] you access element at index j but since you haven't specify size of this string, you are most likely trying to access non-existing element. You could call liekanos.resize(sk) before you enter your while loop to make sure it never happens.
Or if you know the maximum possible size of liekanos, you could declare it as string liekanos(N, c); where N is its size and c is the default value of each character in it.
You are getting undefined behavior because your liekanos string never has any size or capacity.
string liekanos;
By default string has zero size. But you try to
liekanos[j]=sk % p;
Better use std::vector<char> liekanos; instead of string liekanos;.
You'll need to do some modifications in your code:
for (int i=0; i<n; i++)
{
std::vector<char> liekanos;
f >> sk >> p;
while (sk>0)
{
liekanos.push_back(sk % p);
sk/=p;
}
for (long j = liekanos.size(); j>=0; --j)
{
if (liekanos[j]<10)
cout<<int(liekanos[j]);
else cout<<char(liekanos[j]+'a');
}
cout<<endl;
}