Random swap of array elements- stack smashing detected - c

In my program to swap array elements randomly, value of j is determined as shown below:
int j = rand() % (i+1);
Instead of (i+1), I tried using i, i+2 which returned valid output.
But for i+3 onward invalid outputs occur,sometimes with an error as:
*** stack smashing detected ***: ./a.out terminated
Aborted (core dumped)
Can someone please explain why only a value less than 3 must be added?
Program code is as shown below:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void swap (int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void printArray (int arr[], int n)
{
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
}
void randomize ( int arr[], int n )
{
srand ( time(NULL) );
for (int i = n-1; i > 0; i--)
{
int j = rand() % (i+1);
swap(&arr[i], &arr[j]);
}
}
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8};
int n = sizeof(arr)/ sizeof(arr[0]);
randomize (arr, n);
printArray(arr, n);
return 0;
}
Thank you in advance :)

Instead of (i+1), I tried using i, i+2 which returned valid output. But for i+3 onward invalid outputs occur
For anything greater than i+1 (such as i+2, i+3, etc), the resulting index j from:
int j = rand() % (i+2);
might be, depending on what rand() returns, outside the bounds of the array arr and thus it could result in undefined behaviour.
Can someone please explain why only a value less than 3 must be added?
That's not correct conclusion, either. As said you can't add anything greater 1. It's so happens to "work" with 2 (as with anything undefined behaviour, you just can't rely on it and should avoid it).
You can print the value of j and see for yourself whether it could be outside the bounds of the array.

Your array has n elements in it, and the indexes of those elements range from 0 to n-1.
When you choose a new index with rand() % (i+1), this results in a value from 0 to i. Since i starts at n-1 and goes down to 0, this gives you an index that is in range.
If you use rand() % (i+2) for your random index, the resulting values range from 0 to i+1. On the first iteration of the loop i is equal to n-1, which means you could get the value n as a result, which is out of the range of the array.
At this point, the problem can only occur on the first iteration, and only if the random value is n, so the chance if this happening is about 1 out of 9 runs so it won't happen all the time. If you use i+3, the chance of going out of range doubles on the first iteration of the loop, plus it could happen on the next iteration.
The proper way to generate a random value here is rand() % (i+1). Anything larger than i+1 risks going out of range, and the risk goes up the larger the value is.

Related

How to keep while loop in bubble sort function in C

I'm trying to make my own bubble-sort function in C.
As you can see in the code below this, I'm trying to only using while / if loop to create this function. I put 5 numbers (1,3,2,5,4) so that size of array of this would be 5, and I got 5 (I checked it with Python(C)tutor. However, It works well until tab[j] gets 3. I'm trying to figure it out, but couldn't figure it out why it keeps going out when tab[j] gets 3.
Could you anybody explain what's wrong to me? I would appreciate it.
Here is my code below:
#include <stdio.h>
void ft_sort_integer_table(int *tab, int size)
{
int i;
int j;
int tem;
i = 0;
j = 0;
while(tab[i] < size)
{
if(tab[j] > tab[j+1])
{
tem = tab[j];
tab[j] = tab[j+1];
tab[j+1] = tem;
printf("%d ", tab[j]);
j++;
}
else if(tab[j] < tab[j+1])
{
printf("%d ",tab[j]);
j++;
}
i++;
}
}
int main(void)
{
int tab[] = {1,3,2,5,4};
int size = sizeof(tab)/sizeof(*tab);
ft_sort_integer_table(tab, size);
return(0);
}
You'll need an inner loop in your bubble sort, which is responsible for moving the largest element to the back and performing swaps i times (these large elements are "bubbling up"). Start the inner loop at 0 on each iteration and iterate through size - i (we know that the last i elements are sorted and in their final positions).
i controls your outer loop and should be incremented at the end of the loop (just as you would with a for loop). j controls the inner loop and should be incremented at the end of the loop.
While you're at it, it's a good idea to move your printing out of the sort function, which causes an unnecessary side effect and might frustrate your debugging efforts.
Also, it's worth mentioning that (1) for loops are more semantically appropriate here and (2) there is an optimization available by adding a boolean--as soon as you have a pass through the inner loop that performs no swaps, end early!
#include <stdio.h>
void ft_sort_integer_table(int *tab, int size)
{
int i = 0, j, tem;
while (i < size)
{
j = 0;
while (j < size - i)
{
if (tab[j] > tab[j+1])
{
tem = tab[j];
tab[j] = tab[j+1];
tab[j+1] = tem;
}
j++;
}
i++;
}
}
int main(void)
{
int tab[] = {1,3,2,5,4,6,7,1,5,6,8,9,1,4,5,1,2};
int size = sizeof(tab) / sizeof(*tab);
ft_sort_integer_table(tab, size);
for (int i = 0; i < size; i++)
{
printf("%d ", tab[i]);
}
return(0);
}
Output:
1 1 1 1 2 2 3 4 4 5 5 5 6 6 7 8 9
I'm trying to figure it out, but couldn't figure it out why it keeps
going out when tab[j] get 3.
From your code above, j increment in the same fashion as i. That means both variables will have the same value since j will be incremented by one after the if-then-else statement, and i will also be incremented by one at the end of each loop. Therefore, tab[j] is referencing the same value as tab[i]
With that being said, the boolean condition in the while loop checks whether the value in the tab[i] is less than the value of size.
When i == 3, tab[i] == 5 since in the loop, only the values in the array of index less then i are swapped/changed. Since the size variable holds that value of 5, tab[i] < size will result in a false value and exit the loop.
More information on bubble sort can be found here, https://www.geeksforgeeks.org/bubble-sort/

How to store the sum of two integers into a long variable in C?

I created a matrix of ints for example have {1 , 2 , 3 , 4 , 5}
and then I'm trying to store the sum of the matrix into a long variable:
#include<stdio.h>
#define m 5
int main (){
int i;
int matrix[m];
long matrix_sum;
for(i = 0; i < m ; i++) //filling the matrix
matrix[i] = matrix[i-1]+1;
for(i = 0; i < m ; i++) //adding ints to long
matrix_sum += matrix[i];
printf("%lo \n",matrix_sum);
return 0;
}
when I run this code I have "17" on output instead of "15" !!
Think about what happens on the first iteration of this loop:
for(i = 0; i < m ; i++) //filling the matrix
matrix[i] = matrix[i-1]+1;
Notice that you'll be reading from index -1 of this array (oops!) This leads to undefined behavior, which means that in principle anything can happen. Your program could get garbage data, get the wrong answer, or even outright crash!
It's up to you to decide how to avoid this case. Consider changing the loop indices so that you start at a higher index.
Also, look at the remaining variables in main. Are they initialized? If not, adding values to them will again result in undefined behavior and pretty much anything can happen to them.
Finally, look at how you're printfing things:
printf("%lo \n",matrix_sum);
The %lo specifier means "the argument is a long, and it should be printed in octal (base-8)." This means that you're not printing the value in decimal, so even if you'd expect to get the value 15dec, you'd instead see 17, the octal representation of the number.
I have not seen a matrix. It seems you mean an array or a vector.
For starters according to the C Standard the function main without parameters shall be declared like
int main( void )
The variable matrix_sum was not initialized.
In this loop
for(i = 0; i < m ; i++) //filling the matrix
matrix[i] = matrix[i-1]+1;
^^^^
there is an attempt to access memory beyond the array when the variable i is equal to 0.
And it looks like you wanted to use the conversion specifier %ld in this statement
printf("%lo \n",matrix_sum);
^^^
Otherwise the output will be as an octal number.
I think you mean the following. At least the program output is exactly equal to 15.:)
#include <stdio.h>
#define N 5
int main(void)
{
int a[N];
int i;
long sum;
for ( i = 0; i < N ; i++ ) a[i] = i + 1;
sum = 0;
for ( i = 0; i < N ; i++ ) sum += a[i];
printf( "%ld\n", sum );
return 0;
}

Why does this code gives segmentation fault with some inputs?

//difference of two diagonals of a N x N matrix
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main() {
int N, j, i,k,l;
scanf("%d",&N);
int array[N-1][N-1], sum1=0, sum2=0, sum=0;
for(i=0;i<N; i++)
{
for(j=0; j<N; j++)
{
scanf("%d",&array[i][j]);
}
}
for(k = 0; k<N; k++){
sum1 += array[k][k];
}
for(l=0; l<N; l++){
sum2 += array[N-1-l][l];
}
sum = abs(sum1 - sum2);
printf("%d",sum);
return 0;
}
The above code generates segmentation fault for some inputs. The program calculates absolute difference between the summation of all the values in the two main diagonal.
The main problem, I think, is that you're declaring your array of size N - 1 × N - 1, but then filling in N elements. Do try declaring it N×N.
You declared array array as having N-1 rows and N-1 columns
int array[N-1][N-1], /*...*/;
So the valid range of indices for rows and columns of the array is [0, N-2]
However in the loops of the program you are trying to access elements of the array with indices N-1. For example
for(i=0;i<N; i++)
{
for(j=0; j<N; j++)
{
scanf("%d",&array[i][j]);
}
}
that is you are trying to access memory beyond the array and as result the program has undefined behaviour.
Simply write the declaration of the array like
int array[N][N], /*...*/;
Take into account that the sizes of the array shall be positive values.
Also you may remove headers
#include <string.h>
#include <math.h>
because no declaration from the headers is used in the program.
First of all, invalid input will cause Undefined Behavior.
You need to ensure that the input is valid, for that you can check scanf()'s return value, like this
if (scanf("%d", &N) != 1)
return -1;
Then you need to ensure that N > 0, because you allocate space for N - 1 items, so
if (N <= 1) /* this also prevents `int array[0][0];' */
return -1;
should be added.
Then you have to fix your loops, you allocate space for N - 1 items but you do N iterations from 0 to N - 1, N - 1 is an invalid index if you have only allocated N - 1 elements, you need to do one of two things
Fix the loop
for (int i = 0 ; i < N - 1 ; ++i) /* ... etc. */
Allocate space for N elements,
int array[N][N];
in this case you should change the check on N, to
if (N < 1)
return -1;
The reason why different input triggers different behavior, is because accessing an array beyond it's limits causes undefined behavior. So it will sometimes work some other times it will cause a segmentation fault and even some other times something else because it's undefined.
But there is yet another source of undefined behavrior that also depends on input and it's the way you used scanf(). If you type asdasd then N will be uninitialized when you declare your array variable, hence undefined behavior will happen too.

Why does the last element of an array change?

I have the following code:
void generate_random_array(int8_t array[], int array_size){
srand(time(NULL));
for(int i = 0; i < array_size + 1; i++){
array[i] = rand() % 21 + (-10);
printf("%d, %d\n", array[i], i);
}
}
int main(){
int8_t some_array[100];
generate_random_array(some_array, 100);
for(int i = 0; i < 101; i++){
printf("%d %d\n", some_array[i], i);
}
return 0;
}
The program generates random elements of a given array in the range from -10 to 10 and then it displays them. The problem is that the last element of an array changes to 100 when I print elements the second time. I would like to know why.
Indexing of an array starts at zero.
int array[3];// an int array with 3 elements
array[0]; //first element
array[1]; //second element
array[2]; //third element
array[3]; //undefined because it is beyond the end of the array
In your function generate_random_array you are iterating the i upto array_size + 1. And you have declared an array of size 100; int8_t some_array[100]; OS will reserve the 100*sizeof(int8_t) bytes memory for you.
Indexes of your array would be lying in range [0,100) ie. excluding the 100th location.
Now, what you are doing is that you modifying the some_array[100] which you have not claimed in your declaration. Its being possible because C doesn't do any out-of-bound access checking.
But key point to note is that you are trying to modifying/reading the unclaimed memory. So this is undetermined behavior. It might be possible that you might get different value other than 100, sometimes.
But all story short, this behavior is undetermined because you are accessing the out-of-bound index of array.

function to perform bubble sort in C providing unstable results

I am participating in Harvard's opencourse ware and attempting the homework questions. I wrote (or tried to) write a program in C to sort an array using bubble sort implementation. After I finished it, I tested it with an array of size 5, then 6 then 3 etc. All worked. then, I tried to test it with an array of size 11, and then that's when it started bugging out. The program was written to stop getting numbers for the array after it hits the array size entered by the user. But, when I tested it with array size 11 it would continuously try to get more values from the user, past the size declared. It did that to me consistently for a couple days, then the third day I tried to initialize the array size variable to 0, then all of a sudden it would continue to have the same issues with an array size of 4 or more. I un-did the initialization and it continues to do the same thing for an array size of over 4. I cant figure out why the program would work for some array sizes and not others. I used main to get the array size and values from the keyboard, then I passed it to a function I wrote called sort. Note that this is not homework or anything I need to get credit, It is solely for learning. Any comments will be very much appreciated. Thanks.
/****************************************************************************
* helpers.c
*
* Computer Science 50
* Problem Set 3
*
* Helper functions for Problem Set 3.
***************************************************************************/
#include <cs50.h>
#include <stdio.h>
#include "helpers.h"
void
sort(int values[], int n);
int main(){
printf("Please enter the size of the array \n");
int num = GetInt();
int mystack[num];
for (int z=0; z < num; z++){
mystack[z] = GetInt();
}
sort(mystack, num);
}
/*
* Sorts array of n values.
*/
void
sort(int values[], int n)
{
// this is a bubble sort implementation
bool swapped = false; // initialize variable to check if swap was made
for (int i=0; i < (n-1);){ // loops through all array values
if (values[i + 1] > values [i]){ // checks the neighbor to see if it's bigger
i++; // if bigger do nothing except to move to the next value in the array
}
else{ // if neighbor is not bigger then out of order and needs sorting
int temp = values[i]; // store current array value in temp variable for swapping purposes
values[i] = values[i+1]; //swap with neighbor
values[i+1] = temp; // swap neighbor to current array value
swapped = true; // keep track that swap was made
i++;
}
// if we are at the end of array and swap was made then go back to beginning
// and start process again.
if((i == (n-1) && (swapped == true))){
i = 0;
swapped = false;
}
// if we are at the end and swap was not made then array must be in order so print it
if((i == (n-1) && (swapped == false))){
for (int y =0; y < n; y++){
printf("%d", values[y]);
}
// exit program
break;
}
} // end for
// return;
}
You can easily use 2 nested for loops :
int i, j, temp ;
for ( i = 0 ; i < n - 1 ; i++ )
{
for ( j = 0 ; j <= n - 2 - i ; j++ )
{
if ( arr[j] > arr[j + 1] )
{
temp = arr[j] ;
arr[j] = arr[j + 1] ;
arr[j + 1] = temp ;
}
}
}
also you should now it's a c++ code not a c, because c doesn't have something like :
int mystack[num];
and you should enter a number when you're creating an array and you can't use a variable (like "int num" in your code). This is in C, but in C++ you're doing right.
The first thing to do when debugging a problem like this is ensure that the computer is seeing the data you think it should be seeing. You do that by printing out the data as it is entered. You're having trouble with the inputs; print out what the computer is seeing:
static void dump_array(FILE *fp, const char *tag, const int *array, int size)
{
fprintf(fp, "Array %s (%d items)\n", tag, size);
for (int i = 0; i < size; i++)
fprintf(fp, " %d: %d\n", i, array[i]);
}
int main(void)
{
printf("Please enter the size of the array \n");
int num = GetInt();
printf("num = %d\n", num);
int mystack[num];
for (int z = 0; z < num; z++)
{
mystack[z] = GetInt();
printf("%d: %d\n", z, mystack[z]);
}
dump_array(stdout, "Before", mystack, num);
sort(mystack, num);
dump_array(stdout, "After", mystack, num);
}
This will give you direct indications of what is being entered as it is entered, which will probably help you recognize what is going wrong. Printing out inputs is a very basic debugging technique.
Also, stylistically, having a function that should be called sort_array_and_print() suggests that you do not have the correct division of labour; the sort code should sort, and a separate function (like the dump_array() function I showed) should be used for printing an array.
As it turns out the reason why it was doing this is because when comparing an array's neighbor to itself as in:
if (values[i + 1] > values [i])
The fact that I was just checking that it is greater than, without checking if it is '=' then it was causing it to behave undesirably. So if the array is for example [1, 1, 5, 2, 6, 8] then by 1 being next to a 1, my program did not account for this behavior and acted the way it did.

Resources