Bubble Sort Algorithm in C – Is this it? - c

I'm currently a CS50x student.
I've been toying around with the search and sorting algorithms. Trying to understand them in code. Now, on the topic of bubble sort: I created what I think is a bubble sort algorithm. But I couldn't quite fit in the idea of the swap count that needs to be set to non-zero value. My algorithm (below) does sort all numbers. Where would I fit in the swap idea though? If anyone could be so kind to explain I'd really appreciate it.
#import <stdio.h>
#import <cs50.h>
int main(void)
{
// Creating an unsorted array
int count = 10;
int array[count];
for (int z = 0; z < count; z++)
scanf("%i", &array[z]);
// Bubble Sort
int buffer;
for (int b = 0; b < count; b++)
{
int a = 0;
while (a < count)
{
if (array[a] > array[a+1])
{
buffer = array[a];
array[a] = array[a+1];
array[a+1] = buffer;
}
a++;
}
}
printf("Sorted: ");
for (int b = 0; b < count; b++)
printf("%i ", array[b]);
printf("\n");
}

The directive is #include, not #import. The idea of counting swaps is to break the outer loop if nothing is out of sequence (because there were no swaps needed in the inner loop). This code implements that:
#include <stdio.h>
int main(void)
{
// Creating an unsorted array
int count = 10;
int array[count];
for (int z = 0; z < count; z++)
scanf("%i", &array[z]);
putchar('\n');
printf("%8s:", "Unsorted");
for (int b = 0; b < count; b++)
printf(" %i", array[b]);
printf("\n");
// Bubble Sort
for (int b = 0; b < count; b++)
{
int a = 0;
int num_swaps = 0;
while (a < count - 1)
{
if (array[a] > array[a+1])
{
int buffer = array[a];
array[a] = array[a+1];
array[a+1] = buffer;
num_swaps++;
}
a++;
}
if (num_swaps == 0)
break;
}
printf("%8s:", "Sorted");
for (int b = 0; b < count; b++)
printf(" %i", array[b]);
printf("\n");
return 0;
}
Sample runs (source bs97.c compiled to bs97; home-brew random number generator random — the options used generate 10 numbers between 10 and 99 inclusive):
$ random -n 10 10 99 | bs97
Unsorted: 68 47 85 39 52 54 31 81 19 59
Sorted: 19 31 39 47 52 54 59 68 81 85
$ random -n 10 10 99 | bs97
Unsorted: 75 85 36 11 35 87 59 63 26 36
Sorted: 11 26 35 36 36 59 63 75 85 87
$ random -n 10 10 99 | bs97
Unsorted: 90 27 64 90 76 79 52 46 98 99
Sorted: 27 46 52 64 76 79 90 90 98 99
$ random -n 10 10 99 | bs97
Unsorted: 53 60 87 89 38 68 73 10 69 84
Sorted: 10 38 53 60 68 69 73 84 87 89
$
Note that the code avoids trailing blanks in the output.
You could also define int num_swaps = 1; outside the sorting for loop and test it in the main loop condition:
for (int b = 0; b < count - 1 && num_swaps > 0; b++)
{
num_swaps = 0;
and remove the if (num_swaps == 0) break; from the end of the loop. The inner loop could be a for loop too. And the first cycle of the outer loop moves the largest value to the end of the array, so you can shorten the inner cycle so it has less work to do. The printing code should be factored into a function, too.
#include <stdio.h>
static void dump_array(const char *tag, int size, int data[size])
{
printf("%8s (%d):", tag, size);
for (int i = 0; i < size; i++)
printf(" %i", data[i]);
printf("\n");
}
int main(void)
{
// Creating an unsorted array
int count = 10;
int array[count];
for (int z = 0; z < count; z++)
{
if (scanf("%i", &array[z]) != 1)
{
fprintf(stderr, "Failed to read number %d\n", z + 1);
return 1;
}
}
putchar('\n');
dump_array("Unsorted", count, array);
// Bubble Sort
int num_swaps = 1;
for (int b = 0; b < count - 1 && num_swaps > 0; b++)
{
num_swaps = 0;
for (int a = 0; a < count - b - 1; a++)
{
if (array[a] > array[a + 1])
{
int buffer = array[a];
array[a] = array[a + 1];
array[a + 1] = buffer;
num_swaps++;
}
}
}
dump_array("Sorted", count, array);
return 0;
}
Sample output:
$ random -n 10 10 99 | bs97
Unsorted (10): 31 82 81 40 12 17 70 44 90 12
Sorted (10): 12 12 17 31 40 44 70 81 82 90
$

Related

Printing 2D array elements within a function is causing a segmentation fault

I created an 2D array, each line receiving 6 random different values between 1-60.
#define QTE 50
#define NUM 6
void mostrar();
int main(void)
{
int sorteios[QTE][NUM], repeticao[61] = {};
srand(time(NULL));
for (int i = 1; i < QTE; i++)
{
for (int j = 0; j < 6; j++)
{
int gerado = rand() % 60 + 1;
for (int k = j; k > 0; k--)
{
if (j == 0)
{
break;
}
while (gerado == sorteios[i][k])
{
gerado = rand() % 60 + 1;
}
}
sorteios[i][j] = gerado;
int aleatorio = sorteios[i][j];
repeticao[aleatorio] += 1;
}
printf("Sequência %04d:\t %02d\t%02d\t%02d\t%02d\t%02d\t%02d\n", i, sorteios[i][0], sorteios[i][1], sorteios[i][2], sorteios[i][3], sorteios[i][4], sorteios[i][5]);
}
mostrar(sorteios[QTE][NUM]);
}
This code itself is working if there's a for loop inside the main function but using the function to execute causes segmentation fault(core dumped).
void mostrar(int *array[QTE][NUM])
{
printf("Mostrando..\n");
for (int p = 0; p < QTE; p++)
{
printf("Sequência %04d:\t %02d\t%02d\t%02d\t%02d\t%02d\t%02d\n", p, *array[p][0], *array[p][1], *array[p][2], *array[p][3], *array[p][4], *array[p][5]);
}
}
A piece of the console result..
...
Sequência 0043: 35 59 08 31 16 40
Sequência 0044: 26 47 27 52 32 08
Sequência 0045: 35 34 26 35 31 14
Sequência 0046: 07 44 13 22 35 46
Sequência 0047: 50 17 16 53 49 29
Sequência 0048: 27 39 37 50 10 44
Sequência 0049: 29 35 30 55 18 53
Mostrando..
Segmentation fault (core dumped)
Aside from the way you pass the array to the function, already discussed in the comments, there are some other issues in your code, here is a corrected version with comments where fixes are needed:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define QTE 50
#define NUM 6
// if you want the access the array, jut use that as an argument, no pointer needed
void mostrar(int array[][NUM])
{
printf("Mostrando..\n");
for (int p = 0; p < QTE; p++)
{
// correcting the dereference to match the argument...
printf("Sequência %04d:\t %02d\t%02d\t%02d\t%02d\t%02d\t%02d\n", p, array[p][0], array[p][1], array[p][2], array[p][3], array[p][4], array[p][5]);
}
}
int main(void)
{
int sorteios[QTE][NUM], repeticao[61] = {0};
srand(time(NULL));
// beginning at index 1 would leave the first index empty, also messing up the
// indexing in the function, so start at index 0
for (int i = 0; i < QTE; i++)
{
for (int j = 0; j < 6; j++)
{
int gerado = rand() % 60 + 1;
for (int k = j; k > 0; k--)
{
if (j == 0)
{
break;
}
while (gerado == sorteios[i][k])
{
gerado = rand() % 60 + 1;
}
}
sorteios[i][j] = gerado;
int aleatorio = sorteios[i][j];
repeticao[aleatorio] += 1;
}
}
// pass only the array, if you include indexes you are just passing an element
// of the array, and sorteios[QTE][NUM] would be outside of the bounds of the array
// and wouldn't match the original function argument either
mostrar(sorteios);
}
Live demo

how to generate an array of diffrent integers

i have been trying to make an array of complitely diffrent random integers, 25 of them between 1-75. have been getting stuck in an infinite loop. help greatly appreciated!
ive tried to look up solutions but i either didnt understand them or just didnt find anything that suits my level.
btw i have made sure that i used srand(time(NULL));
for (i = 0; i < 25; i++)
{
while (k != 1)
{
arr[i] = rand() % 75 + 1;
for (j = 0; j < 25; j++)
{
if (arr[i] == arr[j])
{
k++;
}
}
}
k = 0;
}
whole code:
/*********************************
* Class: MAGSHIMIM C2 *
* Week: *
* Name: *
* Credits: *
**********************************/
#include <stdio.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int main(void)
{
srand(time(NULL));
int i = 0;
int j = 0;
int k = 0;
int arr[25] = { 0 };
for (i = 0; i < 25; i++)
{
while (k != 1)
{
arr[i] = rand() % 75 + 1;
for (j = 0; j < 25; j++)
{
if (arr[i] == arr[j])
{
k++;
}
}
}
k = 0;
}
for (i = 0; i < 25; i++)
{
printf("%d", arr[i]);
}
getchar();
return 0;
}
expecetd: a nice diffrent array but i got an infinite loop.
One way to do it is to make a pool or bag of numbers in the required range and pick from them. It is not much harder than repeated checking to see if the number has already been picked, and more efficient. Your modified program is now:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define ARRLEN 25 // how many to pick
#define NUMBERS 75 // range of available numbers
#if NUMBERS < ARRLEN // precaution
#error Impossible job!
#endif
int cmp(const void *a, const void *b)
// optional, for qsort
{
return *(int *)a - *(int *)b;
}
int main(void)
{
int arr[ARRLEN]; // final array
int bag[NUMBERS]; // bag of available numbers
int avail = NUMBERS; // size of bag available
srand((unsigned)time(NULL));
// prepare the bag of available numbers
for(int i = 0; i < NUMBERS; i++) {
bag[i] = i + 1;
}
// fill the array with values from the bag
for(int i = 0; i < ARRLEN; i++) {
int index = rand() % avail; // random index into array
arr[i] = bag[index]; // take that number
avail--;
bag[index] = bag[avail]; // replace with the one from the top
}
// just to check, sort the array, can be deleted
qsort(arr, ARRLEN, sizeof arr[0], cmp);
// output the result
for (int i = 0; i < ARRLEN; i++) {
printf("%d ", arr[i]);
}
printf("\n");
getchar();
return 0;
}
I sorted the array to make it easy to see if there are duplicates. That qsort line and the cmp function can be deleted.
Program output from three runs
6 7 8 9 12 16 17 19 21 27 31 35 43 46 47 50 51 53 59 64 65 66 70 71 72
2 6 7 14 17 23 24 25 30 31 32 34 36 37 45 58 59 61 65 68 69 71 73 74 75
5 10 13 18 20 21 25 30 34 36 39 40 41 43 49 50 54 58 60 63 64 66 67 72 75
... but i got an infinite loop.
just replace
while (k != 1)
{
arr[i] = rand() % 75 + 1;
for (j = 0; j < 25; j++) {
...
}
}
k = 0;
by
do
{
k = 0;
arr[i] = rand() % 75 + 1;
for (j = 0; j < 25; j++) {
...
}
} while (k != 1);
Note it is also useless to check looking at all the array including the entries not set by a random value, so can be :
do
{
k = 0;
arr[i] = rand() % 75 + 1;
for (j = 0; j < i; j++)
{
if (arr[i] == arr[j])
{
k++;
}
}
} while (k != 0);
because now j cannot values i the test is (k != 0) rather than (k != 1)
or better because when an identical value is found there is no reason to continue
do
{
arr[i] = rand() % 75 + 1;
for (j = 0; j < i; j++)
{
if (arr[i] == arr[j])
break;
}
} while (j != i);
To see well the values also add a space between them and add a final newline:
for (i = 0; i < 25; i++)
{
printf("%d ", arr[i]);
}
putchar('\n');
AFter these changes, compilation and executions :
pi#raspberrypi:/tmp $ gcc -pedantic -Wextra -Wall r.c
pi#raspberrypi:/tmp $ ./a.out
74 60 16 65 54 19 55 45 41 24 39 59 66 36 27 22 68 49 29 14 28 5 71 56 72
pi#raspberrypi:/tmp $ ./a.out
16 34 62 29 74 41 3 43 69 17 61 22 28 59 7 65 5 46 60 20 66 14 49 54 45
pi#raspberrypi:/tmp $
edit
The implementation is simple but it can take time to find a not yet used value in that way, and the more the range of allowed values is closer to the number of values to return the higher the needed time is. So that solution is good when there are few values to return compared to the range of allowed values.
It is the reverse concerning the interesting proposal of Weather Vane, the number of call to rand is only equals to number of values to return, but the more the range of allowed values is large the more the array bag is large up to may be overflow the memory size.
Probably for 25 values from 1 to 75 the solution of Weather Vane is better ... even my proposal seems to need just 0.001 sec on my raspberry pi so almost nothing
int *fillint(int *arr, size_t size)
{
int added = 0;
int pos = 0
while(pos != size)
{
int rv;
do
{
added = 1;
rv = rand();
for(size_t index = 0; index < pos; index++)
{
if(arr[index] == rv)
{
added = 0;
break;
}
}
}while(!added)
arr[pos++] = rv;
}
return arr;
}
Another slight variation on Weather Vane's bag approach, is rather than preparing a bag of all available numbers, simply declare an array with the max number of elements equal to the range of numbers accepted initialized to all zero (e.g. int arr[75] = {0}; in this case). There is no need to populate the array, you will simply increment the element by 1 each time that number is used in filling your array.
To ensure you use only unique number you check whether the corresponding element of the array is zero, if it is, use that number and increment the element. If it is non-zero, you know that number has been used - generate another and try again.
For example with the number of integers for the array being 25 and the maximum value of any one integer being 75, you could do;:
#define NINT 25
#define MAXI 75
...
int arr[NINT],
seen[MAXI] = {0};
...
for (int i = 0; i < NINT; i++) { /* for each needed element */
int tmp = rand() % MAXI + 1; /* generate a random in range */
while (seen[tmp-1]) /* has been seen/used yet? */
tmp = rand() % MAXI + 1; /* if so, generate another */
seen[tmp-1]++; /* incement element */
arr[i] = tmp; /* assign unique value to arr */
}
(note: the seen indexes are mapped as tmp-1 to map to valid indexes 0-74 while the numbers generated for tmp will be 1-75 using rand() % MAXI + 1. You can accommodate any range needed by this type of mapping. Using a range of numbers from 1000001 - 1000075 would still only require a 75-element seen array.)
To output the numbers used in order, you simply need to output the index corresponding to each of the non-zero elements of the seen array (+1 to map back into the 1-75 values range), e.g.
for (int i = 0; i < MAXI; i++)
if (seen[i])
printf (" %d", i + 1);
putchar ('\n');
Putting it altogether in a short example you could do:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NINT 25
#define MAXI 75
int main (void) {
int arr[NINT],
seen[MAXI] = {0};
srand (time(NULL));
for (int i = 0; i < NINT; i++) { /* for each needed element */
int tmp = rand() % MAXI + 1; /* generate a random in range */
while (seen[tmp-1]) /* has been seen/used yet? */
tmp = rand() % MAXI + 1; /* if so, generate another */
seen[tmp-1]++; /* incement element */
arr[i] = tmp; /* assign unique value to arr */
}
puts ("array:");
for (int i = 0; i < NINT; i++) {
if (i && i % 5 == 0)
putchar ('\n');
printf (" %2d", arr[i]);
}
puts ("\n\nused:");
for (int i = 0; i < MAXI; i++)
if (seen[i])
printf (" %d", i + 1);
putchar ('\n');
}
(note: obviously the size of the seen array will be limited to the available stack size, so if your range of needed numbers exceeds the memory available for seen declared with automatic storage type, you will need to make seen an array with allocated storage type).
Example Use/Output
$ ./bin/randarr25-75
array:
1 18 70 26 75
29 31 58 22 9
5 13 3 25 35
40 48 44 57 56
60 50 71 67 43
used:
1 3 5 9 13 18 22 25 26 29 31 35 40 43 44 48 50 56 57 58 60 67 70 71 75
Whether you use a bag, or an array to track the numbers seen, the results are the same. No one better than the other. Add them both to your C-toolbox.
In the inner for loop, the one for j, iterate until j < i, to check if the value generated at step i has been already generated at a earlier step.
Also, initialize the value of k to be zero every time you check for previous occurrences, this makes the code more easy to read.
If one occurrence was found, just break, it make the algorithm to run faster, even if it only make a difference for big values.
Something like this:
for (i = 0; i < 25; i++)
{
k = 1;
while (k != 0)
{
arr[i] = rand() % 75 + 1;
k = 0;
for (j = 0; j < i; j++)
{
if (arr[i] == arr[j])
{
k++;
break;
}
}
}
}

To find and assign primes to an array

Hi I have made a simple program to print primes between 1 and 100 but I cannot figure a way to assign these values to an array of size 25 as we all know there are 25 primes between 1 and 100:
#include <stdio.h>
int main() {
int i, k;
for (i = 3; i < 100; i = i + 2) {
for (k = 2; k < i; k++) {
if (i % k == 0)
break;
}
if (i == k)
printf("%d\n", i);
}
}
Just create an array at the top, write to it, and then read out of it after you've found all your primes. Note that this could definitely be done more efficiently, but given the number of calculations you're doing, that's beside the point.
Code
#include<stdio.h>
int main() {
int primes[25];
int i, k;
int j = 0;
// find primes
for(i = 2; i < 100; i++) {
for (k = 2; k < i; k++) {
if (i % k == 0) {
break;
}
}
if (i == k) {
primes[j] = i;
j++;
}
}
// print primes
for (j = 0; j < 25; j++) {
printf("%d\n", primes[j]);
}
return 0;
}
Also note that 2 is prime, so you'll want to make sure that that's included in your output.
Output
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97
Make an array before you begin, then create a variable that increments while each prime is found. It might look something like this:
#include <stdio.h>
int main() {
int primes[25];
primes[0] = 2;
int count = 1;
for (int i = 3; i < 100; i += 2) {
int k;
for (k = 2; k < i; k++) {
if (i % k == 0) break;
}
if(i == k) {
primes[count] = i;
count++;
}
}
}
Warning: this is a humorous answer, not to be taken seriously.
Just like we all know there are 25 primes between 1 and 100, we might as well know the magic value to avoid using an array at all:
#include <stdio.h>
int main() {
long long magic = 150964650272183;
printf("2");
for (int i = 3; magic; magic >>= 1, i += 2)
magic & 1 && printf(" %d", i);
printf("\n");
return 0;
}
Output: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

Matrix Transpose With odd row Reversed

I know how to transpose a matrix, But how to transpose a matrix with odd row Reversed form.
Example 3*3 Matrix
1 2 3
4 5 6
7 8 9
Output
1 6 7
2 5 8
3 4 9
Here is a solution that breaks the problem into smaller subproblems. The function reverse_row() is a function that reverses an array in place, and the function transpose_array() transposes an array in place.
The first function, reverse_row() is called in a loop on the rows of the 2d array with odd indices, then the transpose_array() function is called on the resulting array. Note that the test if (i % 2) {} is used to determine if an array index is odd or even, since i % 2 evaluates to 0 only when i is even; you could also avoid this test and simply increment i by two at each iteration (starting from 1), as suggested by #Lưu Vĩnh Phúc in the comments:
for (size_t i = 1; i < MATRIX_SZ; i += 2) {
reverse_row(MATRIX_SZ, array[i]);
}
Also note that to transpose a square matrix in place, you do not need to iterate over all of the elements, but only the elements above or below the diagonal, swapping with the appropriate element. In this case, I have chosen to iterate over the elements below the diagonal, swapping with the corresponding element above the diagonal. Of course, the elements on the diagonal remain unchanged so are not iterated over at all.
Here is the code, using a 4X4 array as input. This code works for square matrices, and could be adapted to work for rectangular matrices. This would require care in choosing the size of the array used to represent the matrix, or dynamic allocation.
#include <stdio.h>
#define MATRIX_SZ 4
void print_array(size_t n, int arr[n][n]);
void reverse_row(size_t n, int arr[n]);
void transpose_array(size_t n, int arr[n][n]);
int main(void)
{
int array[MATRIX_SZ][MATRIX_SZ] = { { 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 },
{ 13, 14, 15, 16 } };
puts("Before transformation:");
print_array(MATRIX_SZ, array);
putchar('\n');
for (size_t i = 0; i < MATRIX_SZ; i++) {
if (i % 2) {
reverse_row(MATRIX_SZ, array[i]);
}
}
transpose_array(MATRIX_SZ, array);
puts("After transformation:");
print_array(MATRIX_SZ, array);
putchar('\n');
return 0;
}
void print_array(size_t n, int arr[n][n])
{
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
printf("%5d", arr[i][j]);
}
putchar('\n');
}
}
void reverse_row(size_t n, int arr[n])
{
size_t mid = n / 2;
for (size_t i = 0; i < mid; i++) {
size_t swap_dx = n - 1 - i;
int temp = arr[i];
arr[i] = arr[swap_dx];
arr[swap_dx] = temp;
}
}
void transpose_array(size_t n, int arr[n][n])
{
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < i; j++) {
int temp = arr[i][j];
arr[i][j] = arr[j][i];
arr[j][i] = temp;
}
}
}
And here is the program output:
Before transformation:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
After transformation:
1 8 9 16
2 7 10 15
3 6 11 14
4 5 12 13
If I have understood the assignment correctly then the program can look the following way.
#include <stdio.h>
#define MAX_VALUE 100
int main(void)
{
while ( 1 )
{
printf( "Enter the size of an array (0 - Exit): " );
size_t n;
if ( scanf( "%zu", &n ) != 1 || n == 0 ) break;
putchar('\n');
n %= MAX_VALUE;
int a[n][n];
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < n; j++ )
{
a[i][j] = n * i + j;
}
}
for (size_t i = 0; i < n; i++)
{
for (size_t j = 0; j < n; j++)
{
printf("%3d ", a[i][j]);
}
putchar('\n');
}
putchar('\n');
for (size_t i = 0; i < n; i++)
{
for (size_t j = i; j < n; j++)
{
if (j % 2 == 1 && i < n / 2)
{
int tmp = a[j][i];
a[j][i] = a[j][n - i - 1];
a[j][n - i - 1] = tmp;
}
if (i != j)
{
int tmp = a[i][j];
a[i][j] = a[j][i];
a[j][i] = tmp;
}
}
}
for (size_t i = 0; i < n; i++)
{
for (size_t j = 0; j < n; j++)
{
printf("%3d ", a[i][j]);
}
putchar('\n');
}
putchar('\n');
}
return 0;
}
Its output might look like
Enter the size of an array (0 - Exit): 10
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
50 51 52 53 54 55 56 57 58 59
60 61 62 63 64 65 66 67 68 69
70 71 72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87 88 89
90 91 92 93 94 95 96 97 98 99
0 19 20 39 40 59 60 79 80 99
1 18 21 38 41 58 61 78 81 98
2 12 22 37 42 57 62 77 82 97
3 13 23 36 43 56 63 76 83 96
4 14 24 34 44 55 64 75 84 95
5 15 25 35 45 54 65 74 85 94
6 16 26 33 46 53 66 73 86 93
7 17 27 32 47 52 67 72 87 92
8 11 28 31 48 51 68 71 88 91
9 10 29 30 49 50 69 70 89 90
Enter the size of an array (0 - Exit): 3
0 1 2
3 4 5
6 7 8
0 5 6
1 4 7
2 3 8
Enter the size of an array (0 - Exit): 0
The compiler should support Variable Length Arrays. Otherwise you can rewrite the program for an array with a fixed size.

Assigning values to 3d array in C

I have 2 arrays as follows -
int **data;
int ***count;
After running some analysis, I want make the following assignment-
count[i][j][k] = data[i][j];
However, I keep getting Segmentation fault which I think is related to some pointer assignment issues - Can anyone suggest how I can make this assignment?
Typical values of -
data[i][j] = 0/1/2.
Definition of ZALLOC:
#define ZALLOC(item,n,type) if ((item = (type *)calloc((n),sizeof(type))) == NULL) fatalx("Unable to allocate %d unit(s) for item\n",n)
// memory assignment
int **data;
int nrow, ncol;
ZALLOC(data, ncol, int *);
for (index = 0; index < ncol; index++)
{
ZALLOC(data[index], nrow, int);
}
int g=0, index1=0, index2=2;
data[index1][index2] = g;
int ***count;
int dim1 = 100, dim2 = 1, dim3=2;
ZALLOC(count, dim1, int **);
for (i = 0; i < dim1; i++)
{
ZALLOC(count[i], dim2, int *);
for (j = 0; j < dim2; j++)
{
ZALLOC(count[i][j], dim3, int);
}
}
// Initialize
for (i = 0; i < dim1; i++)
{
for (j = 0; j < dim2; j++)
{
for (k = 0; k < dim3; k++)
{
count[i][j][k] = 0;
}
}
}
// Assignment
count[0][1][2] = data[1][2];
Your organization of the allocations is a bit odd. If you have 3 dimensions (lets call them levels, rows, and columns), you would normally allocate space to hold the levels, and then for each level you would allocate the space for the rows within the level, and then finally you would allocate the space for the columns within the row.
Your code seems to start in the middle (rows); then does some work at levels; and finally at the columns.
This code is a complete rewrite of yours, but it works without crashing. I've not yet validated it with valgrind; I need to upgrade the version on this machine.
#include <stdio.h>
#include <stdlib.h>
#define ZALLOC(item, n, type) if ((item = (type *)calloc((n), sizeof(type))) == NULL) \
fatalx("Unable to allocate %d unit(s) for item\n", n)
static void fatalx(const char *str, size_t n)
{
fprintf(stderr, "%s: %zu\n", str, n);
exit(1);
}
static int ***alloc_3d(int levels, int rows, int cols)
{
int count = 0;
int ***array_3d;
ZALLOC(array_3d, levels, int **);
for (int i = 0; i < levels; i++)
{
int **data;
ZALLOC(data, rows, int *);
array_3d[i] = data;
for (int j = 0; j < rows; j++)
{
int *entries;
ZALLOC(entries, cols, int);
array_3d[i][j] = entries;
for (int k = 0; k < cols; k++)
{
array_3d[i][j][k] = count++;
}
}
}
return array_3d;
}
static void print_3d(int ***a3d, int levels, int rows, int cols)
{
for (int i = 0; i < levels; i++)
{
printf("%d:\n", i);
for (int j = 0; j < rows; j++)
{
printf(" %d: ", j);
for (int k = 0; k < cols; k++)
printf(" %3d", a3d[i][j][k]);
putchar('\n');
}
}
}
static void free_3d(int ***a3d, int levels, int rows)
{
for (int i = 0; i < levels; i++)
{
for (int j = 0; j < rows; j++)
free(a3d[i][j]);
free(a3d[i]);
}
free(a3d);
}
int main(void)
{
int d1 = 3;
int d2 = 5;
int d3 = 7;
int ***a3d = alloc_3d(d1, d2, d3);
print_3d(a3d, d1, d2, d3);
free_3d(a3d, d1, d2);
return(0);
}
Output:
0:
0: 0 1 2 3 4 5 6
1: 7 8 9 10 11 12 13
2: 14 15 16 17 18 19 20
3: 21 22 23 24 25 26 27
4: 28 29 30 31 32 33 34
1:
0: 35 36 37 38 39 40 41
1: 42 43 44 45 46 47 48
2: 49 50 51 52 53 54 55
3: 56 57 58 59 60 61 62
4: 63 64 65 66 67 68 69
2:
0: 70 71 72 73 74 75 76
1: 77 78 79 80 81 82 83
2: 84 85 86 87 88 89 90
3: 91 92 93 94 95 96 97
4: 98 99 100 101 102 103 104

Resources