Well I have been studying a little C this winter break and in my adventures I stumbled upon an issue with a Dynamic Array.
It's a fairly simple program really. What I am trying to do is to create an array that holds the numbers of the Fibonacci series. Here is the code:
#include <stdio.h>
#include <stdlib.h>
int dynamic_arry_append(int* arry, int* number, int* size);
int main() {
int i, n, size = 3, *arry = NULL, fibarr[size];
printf("Dynamic array, Fibonacci series. \n");
printf("Capture upto element: ");
scanf("%d", &n);
i = 0;
// passing the first elements
fibarr[0] = 0;
fibarr[1] = 1;
fibarr[2] = 1;
while ( i < n ) {
printf("**%d\n",fibarr[0]);
dynamic_arry_append( arry, &fibarr[0], &size );
fibarr[0] = fibarr[1];
fibarr[1] = fibarr[2];
fibarr[2] = fibarr[1] + fibarr[0];
i++;
}
for ( i = 0 ; i < size ; i++)
printf("Element %d of the array: %d.\n", i, arry[i]);
return 0;
}
int dynamic_arry_append(int* arry, int* number, int* size) {
int i;
int bacon = *size; // first name i thought of
bacon++;
int *new_addr = realloc(arry, bacon * sizeof(int));
if( new_addr != NULL ) {
arry = new_addr;
arry[bacon-1] = *number;
// printf for easier debugging, or so i thought
for ( i = 0 ; i < bacon ; i++ )
printf("%d\t%d\n", i+1, arry[i]);
printf("\n");
*size = bacon;
} else {
printf("Error (re)allocating memory.");
exit (1);
}
return 0;
}
At least in my mind this works. However, in practice I get funny results:
Dynamic array, Fibonacci series.
Capture upto element: 5
**0 // next fibonacci number
1 5256368
2 5246872
3 1176530273
4 0
**1
1 5256368
2 5246872
3 1768053847
4 977484654
5 1
**1
1 5256368
2 5246872
3 1551066476
4 1919117645
5 1718580079
6 1
**2
1 5256368
2 5246872
3 977484645
4 1852397404
5 1937207140
6 1937339228
7 2
**3
1 5256368
2 5246872
3 1551071087
4 1953724755
5 842231141
6 1700943708
7 977484653
8 3
/* Code::Blocks output */
Process returned -1073741819 (0xC0000005) execution time : 17.886 s
Press any key to continue.
I am really baffled by this error, and after searching around I found no solution...Can anyone help? Thank you very much.
#include <stdio.h>
#include <stdlib.h>
int * dynamic_array_append(int * array, int size);
int main() {
int i, n, size=0, *array = NULL;
printf("Dynamic array, Fibonacci series. \n");
printf("Capture upto element: ");
scanf("%d", &n);
for (i=0 ; i<n ; i++)
array = dynamic_array_append(array, i);
for (i=0 ; i<n ; i++)
printf("array[%d] = %d\n", i, array[i]);
return 0;
}
int * dynamic_array_append(int * array, int size)
{
int i;
int n1, n2;
int new_size = size + 1;
int * new_addr = (int *) realloc(array, new_size * (int)sizeof(int));
if (new_addr == NULL) {
printf("ERROR: unable to realloc memory \n");
return NULL;
}
if (size == 0 || size == 1) {
new_addr[size] = size;
return new_addr;
}
n1 = new_addr[size-1];
n2 = new_addr[size];
new_addr[new_size-1] = new_addr[new_size-2] + new_addr[new_size-3];
return new_addr;
}
/*
Output:
Dynamic array, Fibonacci series.
Capture upto element: 10
array[0] = 0
array[1] = 1
array[2] = 1
array[3] = 2
array[4] = 3
array[5] = 5
array[6] = 8
array[7] = 13
array[8] = 21
array[9] = 34
*/
Points to note:
The newly (re)allocated array should be returned back to main and stored in a pointer-to-int (or) pass pointer-to-pointer-to-int and update it accordingly once after reallocing
The fibarr is not needed. It doesn't solve any problem.
You don't have to pass the size and the number. Just send the size and it will pick the n-1 and n-2 to calculate n.
This is considered to be highly inefficient. Because if you know the n then you can allocate memory for n integers in one shot and calculate the fib series.
The problem may be that the arry pointer variable is passed by value to the function dynamic_arry_append. That means, that changes that you make to the arry variable within that function will not be reflected by any variables outside of that function. For example:
int *a = NULL;
someFunc(a);
// a will still be NULL here no matter what someFunc does to it.
You should declare your fibarr as a pointer (so name it differently) not an array. And you should pass to your dynamic_arry_append the address of that pointer, like &fibarr. And you should initialize fibarr in your main with calloc. At last you should dynamically update (and keep, and pass) the size of the allocated array.
You are not returning the new address of the array... and you are reading/writing not your memory. Run the program with all error messages under debugger and you'll see the problem is in this line:
dynamic_arry_append( arry, &fibarr[0], &size );
Related
For some reason, the first output my program is giving, is garbage value, while the second output is correct.
This is a problem from HackerRank.
I know this question has already been asked by someone else. I just want to know what the problem is in my code.
#include <stdio.h>
int main()
{
int index,query;
int count1 = 0;
scanf("%d%d",&index,&query);
for(int i=0;i<index;i++)
{
int b;
scanf("%d",&b);
int A[index][b];
for(int j=0;j<b;j++)
{
scanf("%d",&A[i][j]);
}
count1++;
if(count1<index)
{
continue;
}
int count2=0;
while(count2<query)
{
int d,e;
scanf("%d%d",&d,&e);
printf("%d\n",A[d][e]);
count2++;
}
}
return 0;
}
If the input is:
2 2
3 1 5 4
5 1 2 8 9 3
0 1
1 3
Then the output should be:
5
9
But instead, my output is:
garbage
9
Disclaimer
I didn't even click the link, so I do not know if the solution is correct, but assuming that you got the logic right..
The problem
is that you populate in stages a local to the body of the for loop 2D array, which at the end of your processing, you expect to have it accessible (I mean the complete matrix, populated from every single iteration of the for loop).
Instead, you get only the last's iteration declared array, that's why you get only the A[1][3] element right, and not the A[0][1], since the 2nd row is populated in the last (2nd iteration), while the 1st row is populated in the first iteration (of the firstly declared A), which goes out of scope as soon as the first iteration terminates.
The fix
So, what you need to fix this is to dynamically allocate memory for your matrix, and every time a new dimension for the columns is inputed, resize it with realloc().
I believe that the explanation I have in 2D dynamic array (C) will help you, since what you want is the number of rows fixed, and the number of columns adjustable on every iteration.
Below is an illustration based on the link I shared above, which visualizes what exactly is your matrix (a 1D array of pointers), and shows how the code below manipulates it:
Full code example:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int index,query;
int count1 = 0;
scanf("%d%d",&index,&query);
// An array of `index` (e.g. 2) pointers to integers
int *A[index];
// Initialize all the pointers to NULL
for(int k = 0; k < index; ++k)
A[k] = NULL;
for(int i=0;i<index;i++)
{
int b;
scanf("%d",&b);
// Replaced your 'int A[index][b];' with the following:
// Every time a new number of columns (that's 'b') is read,
// we need to adjust the numbers of columns our matrix ('A') has.
// That means, that for every pointer (row), we need to re-allocate
// the number of columns it points to, which is basically a 1D array, of dimension 'b'
for(int k = 0; k < index; ++k)
A[k] = realloc(A[k], b * sizeof(int) );
for(int j=0;j<b;j++)
{
scanf("%d",&A[i][j]);
}
count1 ++;
if(count1<index)
{
continue;
}
int count2=0;
while(count2<query)
{
int d,e;
scanf("%d%d",&d,&e);
printf("%d\n",A[d][e]);
count2++;
}
}
// Free the dynamically allocated memory
for(int k = 0; k < index; ++k)
free(A[k]);
return 0;
}
Output (for the input provided):
5
9
Pro-tip: The typical methodology of calling realloc() is to use a specific pointer for the reallocation, test that pointer and, if everything worked out ok, change the old pointer, as explained in Does realloc overwrite old contents?, which I didn't do in that post for the sake of being "laconic".
The C VLA is not suitable here. It seems you need to allocate memory dynamically. The only VLA that can be used is an array of pointers to other arrays. All other arrays should be allocated dynamically.
Something like the following.
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
size_t number_of_arrays;
size_t number_of_queries;
scanf( "%zu%zu", &number_of_arrays, &number_of_queries );
int **a = malloc( number_of_arrays * sizeof( int * ) );
for ( size_t i = 0; i < number_of_arrays; i++ )
{
size_t size;
scanf( "%zu", &size );
a[i] = malloc( size * sizeof( int ) );
for ( size_t j = 0; j < size; j++ ) scanf( "%d", &a[i][j] );
}
for ( size_t i = 0; i < number_of_queries; i++ )
{
size_t array_index;
size_t element_index;
scanf( "%zu%zu", &array_index, &element_index );
printf( "%d\n", a[array_index][element_index] );
}
for ( size_t i = 0; i < number_of_arrays; i++ ) free( a[i] );
free( a );
}
If to input
2 2
3 1 5 4
5 1 2 8 9 3
0 1
1 3
then the program output will be
5
9
As for your code then it is invalid. For example the variable b is not initialized so the declaration of the array has undefined behavior.
int b;
scanf("%d",&b);
int A[index][b];
^^^
Hint : Variable sized arrays need to be dynamically allocated, here's how to it in C
int rows;
scanf("%d",&rows);
//2D array
int**A = malloc(sizeof(int*)*rows); //allocate number of rows
//for each row allocate number of colums
for(int i = 0; i < rows; i++)
{
int cols;
scanf("%d",&cols);
A[i] = malloc(sizeof(int)*cols);
}
The goal of this program is to add the first and last elements of an array together and set that value as the first element of an output array, and then continue moving inwards as such. All of the sums will be stored in an output array. For this program, the rules stipulate that I may only use pointers and pointer arithmetic (i.e. no subscripting, no '[]', etc.) I have gotten the program to work for arrays of length 2 as well and length 4 (as I have only implemented functionality for even-lengthed arrays) however when I try any array of length 6 or above, the program adds together incorrect values that are not in the first array.
I have already tried using two different debuggers to isolate where the problem is coming from and for the life of me I can not figure it out. I have spent a few hours looking over my notes on C and going through the code, reworking it however I can. I feel as if there is something wrong with how I am interacting between the array and the pointer variables, but I am unsure. I couldn't seem to find any questions on Stack Overflow too similar to this one (yes, I looked).
void add(int *a1, int array_size, int *a2) {
int * p;
int * temp = (a1+(array_size-1));
if (array_size % 2 == 0) {
array_size = array_size/2;
for (p = a2; p < (a2+array_size); p++) {
*p = *a1 + *temp;
printf("%d", *a1);
printf(" + %d", *temp);
a1++;
temp--;
printf(" = %d\n", *p);
}
}
}
For arrays of length 2 and 4 (again, I am only testing even numbers for now), the code works fine.
Example Output:
Enter the length of the array: 2
Enter the elements of the array: 1 2
1 + 2 = 3
The output array is: 3
Enter the length of the array: 4
Enter the elements of the array: 1 2 3 4
1 + 4 = 5
2 + 3 = 5
The output array is: 5 5
Now this is where it is going wrong.
When I do this:
Enter the length of the array: 6
Enter the elements of the array: 1 2 3 4 5 6
I expect:
1 + 6 = 7
2 + 5 = 7
3 + 4 = 7
The output array is: 7 7 7
But instead, the output is:
1 + 0 = 1
2 + 3 = 5
3 + 4 = 7
The output array is: 1 5 7
My best guess is that something went wrong with my use of pointers or perhaps pointer syntax. Any help I can get, positive or negative, would be greatly appreciated.
This is the main() function:
int main() {
int size = 0;
int out_size = 0;
int arr[size];
printf("Enter the length of the array: ");
scanf("%d", & size);
printf("\nEnter the elements of the array: ");
for (int i = 0; i < size; i++) {
scanf("%d", & arr[i]);
}
if (size % 2 == 0) {
out_size = size/2;
}
else{
out_size = ((size-1)/2) + 1;
}
int out[out_size];
//calling the add function and using the addresses of arrays + array size
add(arr, size, out);
//iterating through and printing output array which has now been
//altered by the move function
printf("\nThe output array is: ");
for (int i = 0; i < out_size; i++) {
printf("%d ", out[i]);
}
return 0;
}
You are using an array of size 0:
int main() {
int size = 0;
int out_size = 0;
int arr[size]; // <- Here is your problem
You could move the array declarations after the size reading:
int main() {
int size = 0;
int out_size = 0;
printf("Enter the length of the array: ");
scanf("%d", & size);
int arr[size];
printf("\nEnter the elements of the array: ");
for (int i = 0; i < size; i++) {
scanf("%d", & arr[i]);
}
Heyo!
I'm new to C and have hit a brick wall trying to sort a set of numbers.
If I input '5 3 0 9 5', it will correctly return 9 5 5 3 0.
However, '5 3 0 0 9 9 10 11 13 14 9' doesn't return a thing. Some debugging shows it gets to the 3, then just stops.
Where should I start looking?
Here's my code, but general suggestions are fine:
#include <stdio.h>
#include <stdlib.h>
int getvals(int A[]);
void val_swap(int *a,int *b);
int main() {
int len = 0;
int vals[len];
len = getvals(vals);
int i = 0, j = 0;
/* Search through the values from start to finish */
for (; i < len; i++) {
/* Search back through the values, right to left. If we find a smaller value, swap. */
for (j = i-1; j >= 0 && vals[j+1] > vals[j]; j--) {
/* Swap */
val_swap(&vals[j], &vals[j+1]);
}
}
/* Print the sorted array */
int k = 0;
for (; k < len; k++) {
printf("%d ", vals[k]);
}
return 0;
}
int getvals(int A[]) {
/* Gets a list of integer values from the user */
int num, arr_len = 0;
printf("Enter numbers. CTRL + D to end: ");
while(scanf("%d", &num)) {
A[arr_len] = num;
arr_len++;
}
return arr_len;
}
void val_swap(int *a, int *b) {
int tmp;
/* Save the value of b to temp var */
tmp = *b;
/* Swap the pointer values */
*b = *a;
/* Reassign value */
*a = tmp;
}
Maybe the returned value of getvals is less than the amount of '5 3 0 0 9 9 10 11 13 14 9' , so many data.
But I am wondering whether it can pass the compilation, int vals[len], when len is 0, we don't say whether this is right, but the size of vals has already fixxed because the space of vals is in stack, no heap's.
So in my opinion, there are no enough spaces to run the program.
I SOMETIMES get errors when executing this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int digits(int n){
int count = 0;
while(n!=0)
{
n/=10; /* n=n/10 */
++count;
}
return count;
}
int fib(int n){
int r;
if(n == 1 || n == 0)
return 0;
else if(n == 2)
return 1;
r = fib(n-1) + fib(n-2);
return r;
}
void function(void){
char* test; //number you want to scan
int* table;
int length, length2, test2 = 0, number, l, random = 0, j = 1, buffer;
test = malloc(sizeof(test));
table = malloc(sizeof(table));
scanf("%s", test);
number = atoi(test);
length = strlen(test); //length of input test number
while(test2 < length + 1){
printf("fib(%d) = %d\n", j, fib(j));
buffer = table[j - 1] = fib(j);
test2 = digits(buffer);
j++;
}
//input size of "table" into "length2"
length2 = j - 1;
for(l = 0; l < length2; l++){
if(table[l] == number){
printf("YES\n");
random = 1;
break;
}
}
if(random == 0)
printf("NO\n");
free(table);
free(test);
}
int main(void){
int num, i;
scanf("%d", &num);
for(i=0; i < num; i++){
function();
}
return 0;
}
And this is the output:
3
2
fib(1) = 0
fib(2) = 1
fib(3) = 1
fib(4) = 2
fib(5) = 3
fib(6) = 5
fib(7) = 8
fib(8) = 13
YES
*** Error in `./Am_I_a_Fibonacci_Number': free(): invalid next size (fast): 0x08384018 ***
Aborted (core dumped)
First number is to count how much input the user wants, (in this case 3) and the 2nd(in this case, 2nd, 3rd and 4th) number is the number you want to test whether its a Fibonacci number or not.
Sorry if this is very hard-to-read code, I have a lot to learn.
You are not allocating enough memory, thus you corrupt the heap. sizeof() applied on a pointer (as in your program) usually results in 4 or 8, depending on the architecture. Obviously, this might just be enough for test, but is definitely too little for table.
You need to figure out how much memory you really need, and use this as argument in malloc.
test = malloc(sizeof(test));
table = malloc(sizeof(table));
"test" is a variable of type char*. Such a variable has typically a size of 4 or 8 bytes. So you allocate memory for 4 or 8 bytes, which is enough for 4 or 8 chars.
"table" is a variable of type int*. Again, typically 4 or 8 bytes. Allocating 4 or 8 bytes is usually enough for 1 or two int's. If you try to store more, things will go badly wrong.
Figure out how many chars and ints you want to allocate, then call for example table = malloc (required_elements * sizeof (int)).
I've been at this problem for like 3 days and I've combed my entire code to try to figure out why I'm getting incorrect output. The purpose of this program is to do a merge sort using threads. The first part is simply sorting the elements in parallel into however many segments a user inputs. The only inputs tested will be 2, 5, and 10. And the array to be sorted will always be 50 int array of randomly generated numbers.My code works fine when the segments entered (denoted by the variable 'segments' at the top of main) is 2. However, when I change segments to 5 or 10, I don't get a sorted array at the end. I've tried debugging by using print statements (which I've commented out but you can still see) and there seems to be a problem during the first two merge iterations. For some reason the resulting of those merge iterations are not in order, and they contain duplicate numbers that don't exist in duplicate in the original array passed to it. My sorting method and merging methods work fine when I just pass arrays to them, and don't use threads but when I do use threads I get behavior that I can't explain. Below is my program in its entirety, to merge an array of 50 it should do the following:
split the array into 10 segments of 5, and sort each segment.
pass the segments in pairs, in rounds. So round one should pas segment 0-5 in one segment and 5-10 in another, 10-15 and 15-20, 20-25 and 25-30, and so on until it reaches 40-45 and 45-50.
then it will go into round two which does same thing as round one but it passes the segments in pairs of 10. So 0-10 and 10-20, 20-30 and 30-40, then it leaves the last part of 10 untouched
round three passes the segments to merge in pairs of 20: 0-20 and 20-40, then stops.
Finally it should merge the segments 0-40 with 40-50.
My program: (you should mainly focus on my main function, sort is fine, and merge seems fine too, but i've included them anyways just in case)
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <pthread.h>
/**
* Struct to contain an array partition as well as the size of the partition.
* Use struct to pass multiple parameters to pthread_create
*/
struct array_struct{
int *partition;
int size;
};
/**
* Struct that contains two arrays (should be sorted) to merge
* Use struct to pass multiple parameters to pthread_create
*/
struct arrays_to_merge{
int *array1;
int *array2;
int size1;
int size2;
};
//comparison function to use with qsort, sorts in ascending order
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
/**
* Method that takes a struct containing a pointer to the first int in an array
* partition, as well as the partition size. Object must be type void, used with pthread_create
* #param pointer to the partition object. Type void
*/
void *sort(void *object){
struct array_struct *structure;
structure = (struct array_struct *) object;
int *array = structure->partition;
int size = structure->size;
int *i, j = 0;
qsort(array, size, sizeof(int), cmpfunc);
printf("Sorted %d elements.\n", size);
}
void *merge(void * object){
struct arrays_to_merge *arrays_struct;
arrays_struct = (struct arrays_to_merge *) object;
int *array1 = arrays_struct->array1;
int *array2 = arrays_struct->array2;
int size1 = arrays_struct->size1;
int size2 = arrays_struct->size2;
int tempArray[size1 + size2];
int i = 0, j = 0, k = 0, duplicates = 0;
while (i < size1 && j < size2) {
// printf("Merge number : %d Comparing %d and %d\n", mergenumber, array1[i], array2[j]);
if (array1[i] <= array2[j]) {
// printf("Picking %d\n", array1[i]);
tempArray[k] = array1[i];
if (array1[i] == array2[j])
{
duplicates++;
}
i++;
k++;
}else {
// printf("Merge number : %d Picking %d\n", mergenumber, array2[j]);
tempArray[k] = array2[j];
k++;
j++;
}
}
while (i < size1) {
// printf("Merge number : %d left over Picking %d\n", mergenumber, array1[i]);
tempArray[k] = array1[i];
i++;
k++;
}
while (j < size2) {
// printf("Merge number : %d left over Picking %d\n", mergenumber, array2[j]);
tempArray[k] = array2[j];
k++;
j++;
}
array1 = arrays_struct->array1;
for(i = 0; i < size1 + size2; i++){
array1[i] = tempArray[i];
}
printf("Merged %d and %d elements with %d duplicates\n", size1, size2, duplicates);
}
//return an array of size 50 with randomly generated integers
int *randomArray(){
srand(time(NULL));
static int array[50];
int i;
for (i = 0; i < 50; ++i){
array[i] = rand() % 51;
}
return array;
}
int main(int argc, char const *argv[])
{
int segments = 10;//make equal to argv input after testing
pthread_t threads[segments];
int i, *numbers; //iterator i, and pointer to int array 'numbers'
numbers = randomArray(); //return an array of random ints and store in 'numbers'
struct array_struct array[segments];
for(i = 0; i < segments; i++){
int *partition = numbers + (i * (50/segments));//obtain the first index of partition
array[i].partition = partition;
array[i].size = 50/segments;
pthread_create(&threads[i], NULL, sort, (void *) &array[i]);
}
for(i = 0; i < segments; i++){
pthread_join(threads[i], NULL);
}
int count = segments;
struct arrays_to_merge arrays[segments];
int j;
int size = 50/ segments;
while(count > 1){
for(i = 0, j = 0; i < count-1; j++, i += 2){
int *partition = numbers + (i * (size));
int *partition2 = numbers + (i+1 * (size));
arrays[j].array1 = partition;
arrays[j].array2 = partition2;
arrays[j].size1 = size;
arrays[j].size2 = size;
pthread_create(&threads[j], NULL, merge, (void *) &arrays[j]);
}
for(i = 0; i < j; i++){
pthread_join(threads[i], NULL);
}
size = size * 2;
count = count/2;
}
if(segments != 2){//for segments = 2, no need for his
int *partition = numbers;
int *partition2 = numbers + (size);
arrays[0].array1 = partition;
arrays[0].array2 = partition2;
arrays[0].size1 = size;
arrays[0].size2 = 50 - size;
pthread_create(&threads[0], NULL, merge, (void *) &arrays[0]);
pthread_join(threads[0], NULL);
}
for(i = 0; i < 50; i++){
printf("%d\n", numbers[i]);
}
pthread_exit(NULL);
return 0;
}
this is my output:
Sorted 5 elements.
Sorted 5 elements.
Sorted 5 elements.
Sorted 5 elements.
Sorted 5 elements.
Sorted 5 elements.
Sorted 5 elements.
Sorted 5 elements.
Sorted 5 elements.
Sorted 5 elements.
Merged 5 and 5 elements with 0 duplicates
Merged 5 and 5 elements with 0 duplicates
Merged 5 and 5 elements with 0 duplicates
Merged 5 and 5 elements with 0 duplicates
Merged 5 and 5 elements with 0 duplicates
Merged 10 and 10 elements with 3 duplicates
Merged 10 and 10 elements with 1 duplicates
Merged 20 and 20 elements with 7 duplicates
Merged 40 and 10 elements with 17 duplicates
0
6
9
11
12
13
13
14
15
17
19
23
25
25
25
26
26
28
28
28
28
30
32
32
32
34
39
41
41
44
44
44
44
44
50
50
9
15
50
9
15
19
26
50
50
9
15
11
14
50
Sorry for the long wall of text, I've tried resolving this on my own and after countless hairs pulled I can't figure it out. Please help me figure out what I'm doing wrong. I think my problem lies in either the way I'm joining threads, or my merge function but since I cant be sure, i just included the whole thing.
It took a while but finally I got there :)
The problem is with this line:
int *partition2 = numbers + (i+1 * (size));
which is equivalent to (due to operator precedence).
int *partition2 = numbers + (i + size);
and is not what you want.
It should be:
int *partition2 = numbers + ((i+1) * (size));
Notice the additional brackets. Without which, the partition2 index is calculated incorrectly. Hence, merging with different parts of the array.