Variables being affected by 'bad' instructions - c++

Below is my code, for solving problem 7 of PE ("find the 10001th prime"):
#include <iostream>
using namespace std;
bool isPrime(int n, int primes[], int l){
int i=0;
for (int i=0; i < l; i++){
if (primes[i] != 0 && n%primes[i] == 0){
return false;
}
}
return true;
}
int main()
{
int k=3;
int primes[10001] = {0};
primes[0]=2;
const int l=sizeof(primes)/sizeof(primes[0]);
int N=0;
while (N < l){
if(isPrime(k, primes, l)==true){
primes[++N]=k;
}
k+=2;
}
cout << primes[l-1] << endl;
return 0;
}
This code solves the problem, but there is a mistake in it: on the final iteration of the while loop, the instruction is to set primes[10001]=k;, which attempts to change a value of an element of an array that doesn't exist. If I don't declare it to be constant, and (as a means of troubleshooting) replace l by 10001 in the while loop, the value of l becomes equal to the 10002th prime at the end of the loop.
Here is the main function part of this happening:
int main()
{
int k=3;
int primes[10001] = {0};
primes[0]=2;
int l=sizeof(primes)/sizeof(primes[0]);
int N=0;
while (N < l){
if(isPrime(k, primes, 10001)==true){
primes[++N]=k;
}
k+=2;
}
cout << l << endl;
return 0;
}
My question is, why does this happen? I do know that a simple fix is to stop the loop at l-1 (or better, initialize with N=1 instead and increment N after), but I'm more interested in how this code can affect a variable that isn't being explicitly (directly?) involved in the bad part of the code.
Thank you!

The [] Operator does no bounds checking. some_array[102], will simple go 102 * sizeof(type) if thats outside your array, thats outside your array. C++ won't care.
These are some of the nastiest bugs that can generated if you are lucky you program will crash, sometimes you can just end up changing somebody else's variable.
Which is why I harp on at work about using std::array and std::vector alot because they come with .at(i) functions which have bounds checking.

Related

Why doesn't my recursive longest increasing subsequence function work for large inputs?

I wrote it to work on a single test case at a time.
It either takes too long on online judges or returns wrong answers
Source: The problem I used to test it on
It works perfectly for small cases:
#include <iostream>
#include <algorithm>
#include <vector>
int LIS[100000];
void LS (int *arr , int n)
{
if (n == 0)
{
LIS[0] = 1;
return;
}
if (LIS[n])
{
return;
}
int i = 0;
int max = 0;
while (i < n)
{
if (arr[i] < arr[n])
{
LS(arr,i);
if (LIS[i] + 1 > max)
{
max = 1 + LIS[i];
}
}
++i;
}
LIS[n] = max;
}
int main()
{
int n;
std::cin >> n;
int arr[n];
for(int i = 0 ; i < n ; ++i) std::cin >> arr[i];
LS(arr,n-1);
std::sort (LIS , LIS+n);
std::cout << "\n" << LIS[n-1] << "\n";
}
You said it works perfectly small cases.. than maybe it is stack overflow..
A function call consume stack memory..
If recursive call depth is too deep, stack memory runs out, and crash..
When you read int n value from std::cin, you have to dynamically allocate memory for your array arr, so you should first declare int *arr, then get the user input the same way as you're doing it now, and then allocate memory using arr = new int[n].
When it comes to the long time it takes to compute next values using recursive function, you should think about remaking the function to use tail recursion, which is much closer to iteration. You can check the difference by writing two programs for counting Fibonacci numbers - one recursive and another one iterative, then check how long it takes to compute ~50th value using both methods.

bubble sort broken

I'm trying to code a bubble sort. I'm unable to find the error, I think it has to do with swapping. Can someone tell me where the bug is? It's throwing some unwanted elements at the end of the array.
#include <iostream>
#include <windows.h>
using namespace std;
void swap(int* a,int* b) {
int *c;
c = a;
a = b;
b = c;
return;
}
int main()
{
int array[4], a = 0;
cout << "Enter 5 numbers to be bubble sorted" << endl;
for (a = 0; a <= 4; a++)
{
std::cin >>array[a];
Sleep(1000);
}
for (int b = 0; b <= 4; b++)
{
for(int f = 4;f >= b; f--)
{
if (array[f] < array[f-1])
{
swap(array[f],array[f-1]);
}
}
}
for(int d = 0; d <= 4; d++)
{
cout << '\n';
cout << array[d] << '\n';
}
return (0);
}
You are getting confused over array sizes. It's actually really simple, you want an array of size 5, so just use 5 in your code everywhere
int array[5]; not int array[4];
for (a=0; a<5; a++) not for (a=0; a<=4; a++)
The second one isn't wrong, it's just easier to understand if you always use 5 instead of a mix of 4 and 5.
Your swap function doesn't work and is not being called correctly. Your version swaps pointers not what is being pointed at. One of the more common things that newbies get wrong about pointers is getting confused about the pointer and what the pointer is pointing at. Here's how it should look:
void swap(int* a,int* b) {
int c;
c=*a;
*a=*b;
*b=c;
}
Finally you are calling the swap function wrongly. Your swap function uses pointers so you have to call it with pointers:
swap(array[f],array[f-1]);
should be
swap(&array[f],&array[f-1]);
The maximum index in your for loop is 5, but the size of the array is only 4. Accessing array[4] is likely to modify other local variables, such as a, b, and f.
Your swap is never invoked in your code. array[i] returns int& and your invocation of swap actually calls std::swap.
using namespace std is not a good habit, in my opinion.
If you say that "Its throwing some unwanted elements at the end of the array", I guess that the problem is in indexing. The inner loop iterates from the end of array down to b (inclusive), but you compare the element with the previous one. While the first iteration of the outer loop (b = 0) the inner loop will iterate over 4, 3, 2, 1, 0. In the last moment it would compare array[0] vs array[-1]. Even if the exception is not thrown, god knows what does this memory location contain (and I guess that the value is greater than the minimum element you use as the input). At the end of the day your smallest element goes to the location array[-1] (very dangerous...), and the garbage goes to the (possibly) last element of your array.
Another issue is that the last "element" of your array (array[4]) is actually the memory location where the variable a (most probably) is stored. When you read the last element from the stream (a = 4), you override this variable with the input value. What happens next? a++. The "last element" is being incremented. If by accident it is larger than 4, you exit the loop.
There are many other issues with your code, but these are the most probable reasons of observed behavior.
Change array[4] to array[5] and change the condition of inner loop from
for(int f=4;f>=b;f--) to for(int f=4;f>=(b+1);f--)
#include<iostream>
#include<windows.h>
using namespace std;
void swap(int* a,int* b) {
int *c;
c=a;
a=b;
b=c;
return;
}
int main(){
int array[5],a=0;
cout<< "Enter 5 numbers to be bubble sorted"<<endl;
for (a=0; a<=4; a++)
{
std::cin >>array[a];
Sleep(1000);
}
for (int b=0;b<=4;b++)
{
for(int f=4;f>=(b+1);f--){
if (array[f]<array[f-1])
{
swap(array[f],array[f-1]);
}
}
}
for( int d=0; d<=4;d++){
cout << '\n';
cout << array[d]<< '\n';
}
return (0);
}

How to solve RUN_ERROR even though it compiles normally?

I am currently writing a script about finding the nearest duplicate from a user entered size array.
The array must be between 1 and 10^5 and its value has to be between 1 and 10^5 also.
It compiles normally on my computer but whenever I submit it, it returns a run_error.
Here's what I wrote.
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
void input (int *);
int main(){
int n;
input (&n);
int a[n];
for(int i=0;i<n;i++){
if (scanf("%d",&a[i])!=1)
return 0;
if ((a[i]>100000)||(a[i]<1))
return 0;
}
for (int i=0;i<n;i++){
if (a[abs(a[i])]>=0){
a[abs(a[i])]=-a[abs(a[i])];
} else {
printf("%d",abs(a[i]));
return 0;
}
}
return 0;
}
void input(int *x){
if (scanf("%d",x)!=1)
exit(0);
if ((*x>100000)||(*x<1))
exit(0);
}
This program is logically incorrect. There is no connection between the size of the array defined in n and the limit of the allowed elements.
Since you have allowed a[i]>100000 to go up to 10^5 with no regards to the size of the array defined by a[n], the following access will attempt to access outside the bounds of the array, a[abs(a[i])] for any a[i] > n.
Also, you can pass by reference for syntactical simplicity
input(n);
void input(int &x){
if (scanf("%d",&x)!=1)
exit(0);
if (x>100000 ||x<1)
exit(0);
}
First of all, if you are writing in C, please tag this question as C question, and not as C++ one. scanf & printf are C functions, as much as your includes stdio.h & stdlib.h & math.h. In c++ you have the include iostream, and in this case it's all you really need.
The second problem here is the way you handle the input validation when it wrong. exit is very dangerous way, and very not recommended. If you want to throw exception use throw method (Read about the difference between the two: https://stackoverflow.com/a/56406586/8038186). But, in this case I don't understand why do you need to throw exception at all. you can simply finish the program in more gentle way. Consider the following flow:
#include <iostream>
using namespace std;
// Num is moved by reference and not by pointer
bool input(int &num) { // return true if the input is good, otherwise return false.
cout << "Please enter number: " << endl; // Tell the user that he should enter a number.
cin << num;
bool is_valid = num >= 1 && num <= 1e5; // 1e5 = 100000
if (!is_valid) cout << "Invalid input." << endl;
return is_valid;
}
int main() {
int n;
if (!input(n)) {
return 0;
}
int a[n];
int i;
for (i = 0; i < n && input(a[i]); i++);
if (i < n) {
return 0;
}
for (i = 0; i < n; i++) {
// The following if is useless, the validation make sure already that all of the numbers are legal.
//if (a[a[i]] >= 0) { // You don't need abs(a[i]), a[i] > 1
if (a[i] < n)
a[a[i]] = -a[a[i]];
else cout << "Consider what do you want to do" << endl;
/*} else {
printf("%d", a[i]);
return 0;
}*/
}
return 0;
}
Read about the difference between reference and pointer: What are the differences between a pointer variable and a reference variable in C++?

Check if a number appears in an array C++

I took a coding sample test and I think it's really easy. They ask to find if a number appears in the array (print out YES) or not (print out NO). At first, I want come up with binary search method. But when I see their given function, I think it's not suitable to use that method.
In the description, they mention arr[] and k as the number we need to check if k appears in arr[].
char* findNumber(int arr_count, int arr[], int k)
{
int n = sizeof(arr)/sizeof(arr[0]);
for(arr_count = 0; arr_count < n; arr_count++)
{
if(arr[arr_count]==k)
cout<<"YES";
else
cout<<"NO";
}
return 0;
}
But when I compiled, it showed the output is null. I don't know why? I solved many more difficult problems. So I feel so bad when I got error in an easy task like this. Please tell me the wrong part.
Here
char* (int arr_count, int arr[], int k) { }
Compiler changes int arr[] into int *arr that's because of array decaying. So when you do
int n = sizeof(arr)/sizeof(arr[0]);
sizeof(arr) will be size of int* and n is always 1.
Hence this
for(arr_count = 0; arr_count < n; arr_count++) {
/* some stuff */
}
iterates only once.
int n = sizeof(arr)/sizeof(arr[0]);
At least this is incorrect, as your array arr decays to a pointer when passing it to function.
So sizeof(arr)/sizeof(arr[0]) is actually sizeof(pointer)/sizeof(int). And so n is always 1. And your for loop always runs for one iteration only (when arr_count == 0).
for(arr_count = 0; arr_count < n; arr_count++)
This is also incorrect - as you are not supposed to modify arr_count which is the input array size. You should use a separate variable for the loop.
for( int i = 0; i < arr_count; ++i )
#include<iostream>
const char* findNumber(int arr_count, int arr[], int k)
{
for(int i = 0; i < arr_count ; i++)
{
if(arr[i]==k)
return "YES";
}
return "NO";
}
int main()
{
int array[] = { 2,36,42,8,85,35,225,100};
std::cout << findNumber(sizeof(array)/sizeof(array[0]),array,43) << std::endl;
std::cout << findNumber(sizeof(array)/sizeof(array[0]), array, 85) << std::endl;
return 0;
}
there you go. fixed and working fine. outputs NO and then YES.

Reversing an Array Results In SegFault

#include <iostream>
using namespace std;
/*
*
*/
int main() {
int k, in[k],reversea[k],i,m,n;
cin>>k;
for (i=0;i<k;i++){
cin>>in[i];
}
for (m=k-1;m>=0;m--){
for (n=0;n<k;n++){
in[m]=reversea[n];
}
}
for(i=0;i<k;i++){
cout<<reversea[i];
}
return 0;
}
I have no idea why it says segmentation fault even before i start debugging it. I compile another one on calculating the frequency of 1, 5, and 10 in an array of k numbers, and it says the same thing...
Here is the other one:
#include <iostream>
using namespace std;
int main() {
int k,i,m,n,count5,count1,count10;
int input[k];
cin>>k;
for (i=0;i<k;i++){
cin>>input[i];
}//input all the numbers
for(i=0;i<k;i++){
if (input[i]=1){
count1++;
}
if (input[i]=5){
count5++;
}
if (input[i]=10){
count10++;
}
}
cout<<count1<<"\n"<<count5<<"\n"<<count10<<"\n";
return 0;
}
Please help me. Thanks.
On this line
int k, in[k],reversea[k]
How are you supposed to initialize an array with k elements if k isn't initialized? The size of an array must be known at compile time not run time. If k isn't know until run time, use a std::vector
int k;
std::cin >> k;
std::vector<int> in(k);
std::vector<int> reversea(k);
Both your programs have two major faults.
You need to know the size of an array while creating it. In your code, k is still uninitialized and you are using this value as the size of your array. Instead, change it to
int k,i,m,n;
cin >> k;
int in[k];
int reversea[k];
While reversing the array, you should be filling reversea using values from in, and not the other way round. Also, you don't need 2 for loops, just use 1 for loop.
for (m=k-1; m>=0; m--){
reversea[m] = in[k-1-m];
}
In the second program, you again need to get the value of k before creating the array input[k].
You are testing for equality with a = instead of == . Change your code from
if (input[i]=1){
to
if (input[i] == 1) {