Why does the last element of an array change? - c

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.

Related

How do i decrease the size of array?

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
void main()
{
int i=0,pos;
int *ptr;
clrscr();
ptr=(int *)malloc(10*sizeof(int));
printf("Enter 10 Elements:\n");
while(i<10)
{
scanf("%d",&ptr[i]);
i++;
}
printf("Current Array:\n");
for(i=0;i<10;i++)
{
printf("%d\t",ptr[i]);
}
printf("Enter the position to be deleted:");
scanf("%d",&pos);
for(i=pos;i<10;i++)
{
ptr[pos-1]=ptr[pos];
pos++;
}
for(i=0;i<10;i++)
{
printf("%d\t",ptr[i]);
}
getch();
}
Array i enter : 1 2 3 4 5 6 7 8 9 0
Suppose 4th position has been deleted
Array after deletion: 1 2 3 5 6 7 8 9 0 0
How can i make the program to print only 9 integers but without decresing the times the loop run.
i.e. without using
for(i=0;i<9;i++)
C doesn't allow you to do that. So, alternative is to dynamically allocate an array, put what you want in it, then when you get the size you want, transfer that data to a newly allocated array of the appropriate size and delete the old one.
Use a variable to keep track of how many elements of the array are being used.
When you start:
unsigned num_elements = 10;
int *ptr = malloc(num_elements * sizeof(int));
When you delete, do the following as well:
--num_elements;
When you print:
for (unsigned i=0; i<num_elements; ++i) {
...
}
Since you print the array in multiple places in the code, it would be nice to create a small function to do it.
void print_array(int *a, unsigned size) {
if (size == 0) {
printf("[empty]\n");
return;
}
printf("%d", a[0]);
for (unsigned i=1; i<size; ++i) {
printf("\t%d", a[i]);
}
printf("\n");
}
print_array(ptr, num_elements);
Your questions refers to 2 issues here:
Deleting an element of an dynamically allocated array
Printing values of an dynamically allocated array without adjusting for loop parameters
1)
for(i=pos;i<10;i++)
{
ptr[pos-1]=ptr[pos];
pos++;
}
Does not decrease the array at all - you just overwrite the particalur position with another element but you still have memory allocated for 10 int
One way to reach that would be using realloc after you moved the values by to the left beginning at the target element:
for (i = pos; i < array_size - 1; i++)
{
ptr[i] = ptr[i+1];
}
ptr = realloc(ptr, --array_size)
To 2)
Simple answer: This wont be possible. When you decrease the size of your array and dont adjust the loop's paramter you will access memory which doesnt belong to the array anymore.
Of course you dont want to adjust every for-loop by hand but you can simplify life if you always remember the array's size, preferably in immediate reference to it within a struct:
typedef struct
{
size_t size;
int *array;
} my_array_t;
If you ensure that size is properly adjusted everytime you allocate the array's memory (functions are your friend), you can always print the values with:
my_array_t a;
a.size = 10;
a.array = malloc(a.size * sizeof(int));
for (i=0; i < a.size; i++)
// ...

Random swap of array elements- stack smashing detected

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.

Correctly passing an array from a function

I have some code to generate an array of size [user_input] in a function called array_generator, using size of array from scanf in main(), and then filling it with the numbers 0 to user_input (0, 1, 2, 3, if user input is 4). The array fills correctly as printf prints
`The array contains the value 1`
`The array contains the value 2`
`The array contains the value 3`, etc.
However when I pass the array to main and printf the array values I get equal statements filled with garbage numbers. I'm also 90% sure I have been passing the arrays and pointers incorrectly (new to them).
The code is below:
#include <stdio.h>
int *array_generator(int number_songs);
int main(void)
{
int input;
int *p;
int i;
int x;
printf("Enter number of songs wanted in random playlist: ");
scanf("%d", &input);
p = array_generator(input);
x = *p;
for (i = 0; i < input; i++)
{
printf("The array contains the values %d\n", x);
}
return 0;
}
int *array_generator(int n)
{
int a[n];
int *p;
int i;
for (i = 0; i < n; i++)
{
a[i] = i;
printf("The array contains the values %d\n", i);
}
return p = &a[n];
}
One simple solution is to define an array which is bigger than the largest list of songs reasonably possible. For example, since you print every entry, more than a few hundred are not reasonable. On a modern computer space is abundant. You would have a define for the max size on top of the prog, or later in some header:
#define MAX_SONGLIST_LEN 1000
The array can be global, or it can be static inside the function. Let's make it static because you want the function to return the address.
The change is minimal. Just say
static int a[MAX_SONGLIST_LEN];
You may want to change the loop and check for the max length as well:
for (i = 0; i < input && i < MAX_SONGLIST_LEN; i++)
inside array_generator() and main(). You also may want to inform your users about the maximum, and catch numbers which are too large. (You don't do any error handling of user input anyway -- what happens if the user enters a letter instead of a number? Look into the return value of scanf().)
The static array's life time is the lifetime of the program. It will be initialized to all zeroes by the way. If you want to randomly initialize it look at the rand() function.
You are correct in that you are using pointers wrong. The code below preforms the function that you want...
#include <stdio.h>
void array_generator(int n, int arr[]) {
for (int i = 0; i < n; i++) {
arr[i] = i;//array values
//printf("The array contains the values %d\n", i);
}
}
int main() {
int input;
printf("Enter number of songs wanted in random playlist: ");
scanf("%d", &input);
int array[input];//declare array with length of input
array_generator(input, array);
for(int i=0; i<sizeof(array)/sizeof(array[0]); i++) {//input could also be used at the limit to the for loop
printf("%d", array[i]);
}
printf("\n");
return 0;
}
What you are doing is you are over complicating your code. The first thing you do is you create a function and try to make it return an array. This is not necessary. All you need to do is pass a pointer to the array and all edits to the array will be made on the same scope as the array was declared on.
You also mentioned that you want to find the size of an array. This can be done with array *a of any type and sizeof(a)/sizeof(a[0]). This works by returning the number of bytes used by the array divided by the number of bytes used by the first element in the array.
One more thing that you have that you don't need is x = *p;. when you do this, you are essentially doing this x=*p=array_gen(input);
More information on pointers in C can be found here.

Array doesn't print in reverse in C using pointers

I am trying to make a program that takes 10 numbers as input and outputs them in reverse order using pointers in C.
#include<stdio.h>
#define N 10
int array[N]; //Global variable
int main(void) {
int j;
int i;
printf("Enter 10 numbers: ");
for (i=0;i<N;i++) {
scanf("%d",(array+(4*i))); //Works
}
for (j=N-1;j<0;j--) {
printf("%d",array[j]); //Doesn't print, using *(array+j*4) doesn't
//print also
}
printf("\n");
printf("%d\n",*(array)); //Works so scanf works
printf("%d\n",*(array+4)); //Works so scanf works
return 0;
}
I have tried a making a seperate function for the two for loops but still it doesn't work. I want to know WHY this for-loop doesn't print but the two printfs below it print.
EDIT:
My new code is
#include<stdio.h>
#define N 10
int array[N]; //Global variable
int main(void) {
int j;
int i;
printf("Enter 10 numbers: ");
for (i=0;i<N;i++) {
scanf("%d",(array+i)); //Works
}
for (j=N-1;j<0;j--) { //it is supposed to be j>=0 or j>0 WHY
printf("%d",array[j]); //Doesn't print, using *(array+j) doesn't
//print also
}
printf("\n");
printf("%d\n",*(array)); //Works so scanf works
printf("%d\n",*(array+1)); //Works so scanf works
return 0;
}
Thanks to all the posts, I have a better understanding of how indexing works in C now but the printf doesn't work still unless I change the for-loop conditions(see above). WHY doesn't it work with the initial conditions but with the latter conditions.
Whoa!
This:
scanf("%d",(array+(4*i))); //Works
is very wrong and is overwriting memory! Why are you multiplying the index? You don't need to do that, C can index by itself. It should just be:
scanf("%d", &array[i]);
You want the address of the i:th array member, so say that, don't beat around the bush with strange multiplications.
If you really want to be "using pointers", as mentioned in a comment, you can do so:
scanf("%d", array + i);
This works since array is a pointer to the first element of the array, and adding i to is a fully valid use of pointer arithmetic; C will compute the proper pointer, knowing the size of each int in the array.
Your array consists of 10 elements with type int (obviously). In expression array + i variable i is not an offset in bytes. It is an index of element. So when you read it like you do (scanf("%d",(array+(4*i)))) you basicly read array[0], array[4], array[8], array[12] (we're out of array bounds here already, it causes memory corruption and might cause crashes), etc. Elements array[1],[2],[3],[5], etc. are uninitialized. That's why your code doesn't work :)
UPDATE:
And #shilong-liu's note about array indices is important, too. I didn't notice it.
for (j=N-1;j<0;j--) {
printf("%d",array[j]); //Doesn't print, using *(array+j*4)
}
the for loop is not right. The correct one is that
for (j = N - 1; j > 0; j--)
I guess since the pointer used is of type int, you assume that you have to multiply i by 4 because depending on the compiler int is 4 bytes. I guess if you really care only about the output, then you could do it the way you did with reverse iteration.
What you have to do has been already mentioned by the others so I will give you my solution for actually swapping the pointers memory wise and you could choose from the given solutions:
#include<stdio.h>
#define N 10
int array[N]; //Global variable
int main(void) {
int j;
int i;
printf("Enter 10 numbers: ");
for (i=0; i<N; i++) {
scanf("%d", (array + i));
}
for (left = 0; left < N / 2; left++)
{
int right = N - left - 1;
int temporary = array[left];
array[left] = array[right];
array[right] = temporary;
}
for (i=0; i<N; i++) {
printf("%d", (array + i));
}
return 0;
}
I have been programming for algorithmic contests so you could trust me.

Recursive Sort Function

I've written a program to recursively sort an array.
However, I get the following error on line 11: syntax error before ']' token.
Here is the code:
//This program recursively sorts an array
#include<stdio.h>
void rec_sort(int values[], int n);
main()
{
int vals[4];
vals[0] = 37; vals[1] = 48; vals[2] = 56; vals[3] = 63;
printf("this array sorted: %x\n", rec_sort(vals[], 4));
system("Pause");
return 0;
}
void rec_sort(int values[], int n) {
//Base case
if (n<2) return;
int maxIndex=0;
int i;
//Find max item in array in indexes 0 through n-1
for(i=1; i<n;i++) {
if(values[i] > values[maxIndex])
maxIndex=i;
}
//Swap this element with one stored in n-1
//Set temp to n-1, set n-1 in array to max, set max to temp
int temp = values[n-1]; //Store temp as last element in array
values[n-1] = values[maxIndex]; //Store last element as max value in array
values[maxIndex] = temp; //temp will keep on changing, as array is sorted
//Recursively sort the array values of length n-1
sort(values, n-1);
}
It looks like you're trying print out the whole array, which C won't do in one call to printf. Instead, you need a loop to iterate through the array and print out each number individually:
for (i=0; i<4; i++)
printf("%x\n", vals[i]);
Since rec_sort isn't returning the array, you also need to invoke it separately from the call the printf, so you'd get something like:
// sort the data:
rec_sort(vals, 4);
// print the sorted values:
for (i=0; i<4; i++)
printf("%x\n", vals[i]);
Just remove the [] on line 11. But this is a naive answer to your question, and won't get you far. There are other problems - the most obvious is the idea of printf(..., rec_sort(...)...);
Considering rec_sort has void return type, how do you expect printf() to understand what to do? I am not sure what you want either, but this should be at least a start for you.
printf("this array sorted: %x\n", rec_sort(vals[], 4));
but rec_sort() is void. Doesn't return anything
void rec_sort(int values[], int n)
Also, declare your main as int main()
The problem is in this:
rec_sort(vals[], 4)
What exactly do you want to do there? The [] is an index operation, so either you need to put a number in there, or you leave them out completely (if you want to talk about the whole array).
The first thing you should do is remove the square brackets:
printf("this array sorted: %x\n", rec_sort(vals, 4));
Second, note that rec_sort returns void, so you cant use the return value
you need
int i; // at the top of the main
// ...
rec_sort(vals, 4);
printf("this array sorted: ");
for(i = 0; i < 4; ++i) printf("%x ", vals[i]);
printf("\n");
Third: you need to call rec_sort again
Fourth: what are you tryin to do with the system statement?

Resources