How to get the row size of an 2 dim array in C - c

Hi there I was trying to make a varation of bucket sort. My Programm is easy because I'm a beginner in C but i don't know how print the 2 dim array when one row was realloc after putting in the numbers. I have tried int lenght= sizeof(buckets[0])/sizeof(buckets[0][0]) but then lenght=1. My alternativ solution in the main and it is not very dynamic therefore can anybody tell me how to get the size of the row in a 2 dim array?? If I would add a number in the first bucket the bucket will be too small so i realloc the bucket but how can i print it now?
Sorry for the bad english :)
#include <stdlib.h>
#include <stdio.h>
#define MAXZAHL 50
int compare(const void * a, const void * b){// compare for the qsort
return(*(int*)a - *(int*)b);
}
int** init_bucket(int l,int teile,int teilgr){// to init the buckets
int **bucket;
bucket=(int**)malloc(teile*sizeof(int));
for (int i=0;i<teile;i++){
bucket[i]=(int *)malloc(teilgr*sizeof(int));
}
for (int i=0;i<teile;i++){
for (int j=0;j<teilgr;j++){
bucket[i][j]=0;
printf("%3i",bucket[i][j]);
}
printf("\n");
}
return bucket;
}
void bucket_int(int**bucket,int bucketsize,int nextVal,int n){// to write the array in the buckets
int start=bucketsize;
for (int i=0;i<n;i++){
if(nextVal< start && bucket[0][i]==0){
bucket[0][i]=nextVal;
break;
}
if(nextVal< start && bucket[0][i]!=0&& i==n-1){
bucket[0][n]=(int)realloc(bucket,sizeof(int));
++i;
bucket[0][i]=nextVal;
break;
}
if((nextVal<(start*2)&& nextVal>=(start))&&(bucket[1][i]==0)){
bucket[1][i]=nextVal;
break;
}
if((nextVal<(start*3)&&nextVal>=(start*2))&&(bucket[2][i]==0)){
bucket[2][i]=nextVal;
break;
}
if((nextVal<(start*4)&&nextVal>=(start*3))&&(bucket[3][i]==0)){
bucket[3][i]=nextVal;
break;
}
if((nextVal<(start*5)&&nextVal>=(start*4))&&(bucket[4][i]==0)){
bucket[4][i]=nextVal;
break;
}
}
}
int main(){
int arr[]={3,26,2,10,33,45,20,15,11,9,34,40,19,16,4,5,26,49,1,0,6,8,7,3};
int len=sizeof(arr)/sizeof(int);//
int teile=5;
int teilgr=MAXZAHL/5;
int **buckets;
buckets=init_bucket(len,teile,teilgr);
for (int i=0;i<len;i++){//write the numbers in the buckets
bucket_int(buckets,teilgr,arr[i],len);
}
printf("\n");
//print Buckets
for (int i=0;i<teile;i++){
for (int j=0;j<teilgr;j++){// is there a way to say j<sizeof(buckets)??
printf("%3i",buckets[i][j]);
}
printf("\n");
}
//sorting the buckets with qsort
for (int i=0;i<teile;i++){
for (int j=0;j<teilgr;j++){
qsort(buckets[i],teilgr,sizeof(int**),compare);
}
}
printf("\n");
//print Buckets
for (int i=0;i<teile;i++){
for (int j=0;j<teilgr;j++){
printf("%3i",buckets[i][j]);
}
printf("\n");
}
printf("\n");
int f=0;
//Putting the buckets back to the array
for (int i=0;i<teile;i++){
for (int j=0;j<teilgr;j++){
if (buckets[i][j]!=0){
arr[f]=buckets[i][j];
f++;
}
}
}
printf("The sorted Array:\n");
for (int i=0;i<len-1;i++){
printf("%i ",arr[i]);
}
printf("\n");
return EXIT_SUCCESS;
}

how to get the size of the row
Read it from where you stored it, when you still knew it.
In C you cannot derive from a pointer to how much memory it points.

sizeof() should do the trick, there was a similar question on SO, did you search?

Related

Radix sort gives wrong answer by changing just one loop of count subroutine

It seems a very trivial problem but after a lot of thinking I still can't figure it out. I worte these two codes for Radix sort.
Code 1
#include <stdio.h>
#include <malloc.h>
#define BUCKET_SIZE 10
void prin(int* arr,int n)
{
int i;
for(i=0;i<n;i++)
printf("%d ",*(arr+i));
printf("\n");
}
int maxi(int* arr,int n)
{
int i,max=0;
for(i=0;i<n;i++)
{
if(arr[i]>max)
max=arr[i];
}
return max;
}
int* count(int *arr,int n,int k)
{
int* count,i,index;
int* output;
count=(int*)calloc(BUCKET_SIZE-1,sizeof(int));
output=(int*)malloc(n*sizeof(int));
for(i=0;i<n;i++)
{
index=(arr[i]/k)%10;
count[index]++;
}
for(i=0;i<BUCKET_SIZE;i++)
count[i]+=count[i-1];
for(i=n-1;i>=0;i--)
{
index=(arr[i]/k)%10;
output[count[index]-1]=arr[i];
count[index]--;
}
return output;
}
int* radixsort(int* arr,int n)
{
int i,max,k=1;
max=maxi(arr,n);
while(max>0)
{
max/=10;
arr=count(arr,n,k);
k=k*10;
}
return arr;
}
void main()
{
int n,i;
scanf("%d",&n);
int* arr;
arr=(int*)malloc(n*sizeof(int));
for(i=0;i<n;i++)
scanf("%d",(arr+i));
arr=radixsort(arr,n);
prin(arr,n);
}
Now if I change the sort subroutine like below, this code will not sort the given array and I can't figure why this happened, I am still traversing the whole array so and I am still calculating the right index so my elements should be filled in the right place and I should have a sorted array.
Code 2
Only count function last loop changed.
int* count(int *arr,int n,int k)
{
int* count,i,index;
int* output;
count=(int*)calloc(BUCKET_SIZE-1,sizeof(int));
output=(int*)malloc(n*sizeof(int));
for(i=0;i<n;i++)
{
index=(arr[i]/k)%10;
count[index]++;
}
for(i=0;i<BUCKET_SIZE;i++)
count[i]+=count[i-1];
for(i=0;i<n;i++)
{
index=(arr[i]/k)%10;
output[count[index]-1]=arr[i];
count[index]--;
}
return output;
}
When I am doing just counting sort both functions work well. Can someone point me out where I am going wrong with radix sort, or what is the thing I am missing, and how both well in counting sort.
Thanks.
In your final loop in your count function,
when these lines copy the contents of each "bucket",
they write the last element of the output "bucket" first,
followed by the next-to-last, ending with the first element:
output[count[index]-1]=arr[i];
count[index]--;
In the first version of your program, since you visit the elements of the input array starting at the end of the array and working your way back toward the beginning,
you encounter the last element of each bucket first (and therefore put it in the last position in the output bucket), then the next-to-last element
(which you put in the next-to-last position in the output),
and so forth. The first element of each bucket is the last copied
and is copied to the first position in the bucket.
In the second version of your program, you continue to fill in the spaces in each output bucket from back to front, but you read the input from front to back. This has the result of putting the first element of each bucket in the last position within that bucket, and the last element of the bucket in the first position.
That is, each time you run the count function it reverses the order of elements within each bucket.
If you want to copy the input array reading it from front to back,
you need to fill in each output bucket from front to back
by using ++count[index] instead of --count[index].
You also have to start each entry of count[index] at a lower number so that you write to the correct locations.
Aside: your program does a lot more allocation than it needs to, and doesn't free any memory, so you have a potentially massive memory leak.
You might consider passing already-allocated arrays into count instead of always allocating new ones.
Here is a front to back example, that also replaces the original array with a sorted array, freeing the original array. An alternative would be to do a one time allocation of a second working array, radix sort back and forth between original and working arrays, then keep the sorted array, and free the "other" array.
#include <stdio.h>
#include <stdlib.h>
#define BUCKET_SIZE 10
void prin(int* arr, int n)
{
int i;
for(i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
}
int maxi(int* arr, int n)
{
int i,max = 0;
for(i = 0; i < n; i++)
{
if(arr[i] > max)
max = arr[i];
}
return max;
}
/* replaces array with sorted array, frees original array */
void count(int** parr, int n, int k)
{
int* count, i, index;
int* arr = *parr;
int* output;
int sum, cur;
count=calloc(BUCKET_SIZE, sizeof(int));
output=malloc(n*sizeof(int));
for(i = 0; i < n; i++){
index = (arr[i]/k)%10;
count[index]++;
}
sum = 0;
for(i = 0; i < BUCKET_SIZE; i++){
cur = count[i];
count[i] = sum;
sum += cur;
}
for(i = 0; i < n; i++){
index = (arr[i]/k)%10;
output[count[index]++] = arr[i];
}
free(arr);
free(count);
*parr = output;
}
void radixsort(int** parr,int n)
{
int max,k=1;
max=maxi(*parr,n);
while(max>0)
{
max/=10;
count(parr,n,k);
k=k*10;
}
}
int main()
{
int n,i;
int* arr;
scanf("%d",&n);
arr = malloc(n*sizeof(int));
for(i = 0; i < n; i++)
scanf("%d",&arr[i]);
radixsort(&arr,n);
prin(arr,n);
free(arr);
return 0;
}

saving data from an array in C

I should mention that I am in my 1st 2 weeks of an intro to programming class before people get too crazy with answers.
Using this array as an example,
int scores[30] = {90,85,100,50,50,85,60,70,55,55,80,95,70,60,95,
80,100,75,70,95,90,90,70,95,50,65,85,95,100,65}
I am trying to parse through it to create 2 new parallel arrays to use later. The idea is to make one array that holds the "scores" and one that holds the "occurrences" of each score. I end up compiling with no errors however during run time it crashes.
void frequency(int scores[], int max){
int i, x=0, temp=0, count=0, sum=0, mode=0;
int score[sum]; //unknown length of array, sum gets added after the while loop
int freq[sum];
printf("score\tfrequency\n");
printf("-----\t---------\n");
fprintf(fp, "score\tfrequency\n");
fprintf(fp, "-----\t---------\n");
for (i = 0; i < max; ++i){
while (scores[i]==scores[x]){
x++;
count++;
sum++;
temp = x-1;
if(scores[i] != scores[x]){
//printf(" %d\t %d\n",scores[i], count);
freq[i] = count;
score[i] = scores[i];
count=0;
i=temp;
x=temp+1;
sum++;
printf("%d\t%d", score[i], freq[i]);
fprintf(fp, "%d\t%d", score[i], freq[i]);
}
}
}
}
This part:
int i, x=0, temp=0, count=0, sum=0, mode=0;
int score[sum];
int freq[sum];
looks wrong.
You set sumto zero and then use it for the array dimension. Did you mean to do:
sum = max;
I end up compiling with no errors however during run time it crashes.
Reason:
The reason why your program crashes is because you have not allocated sufficient memory to the arrays that you use int the frequency() function
void frequency(int scores[], int max){
int i, x=0, temp=0, count=0, sum=0, mode=0;
int score[sum];
int freq[sum];
Solution:
So, is there a way to provide memory during run time according to requirements or change memory size of blocks during compile time?
Yes, that's the very reason why Dynamic memory allocation is used.... though you send a fixed array to the frequency() function in your code, the function I've provided works for any integer array you send..
Here I've provided code in which
one array stores all the unique scores
and other array stores number of occurrences of each score
I've done this using dynamic memory allocation.. I think it's easy to understand if you have basic understanding of dynamic memory allocation functions.. if you have any doubts, ask me through the comments :) and by the way I've assumed your main function to be :
int main()
{
int scores[30] = {90,85,100,50,50,85,60,70,55,55,80,95,70,60,95,
80,100,75,70,95,90,90,70,95,50,65,85,95,100,65};
frequency(scores,30);
return 0;
}
Code:
#include <stdio.h>
#include <stdlib.h>
void frequency(int scores[], int max);
int main()
{
int scores[30] = {90,85,100,50,50,85,60,70,55,55,80,95,70,60,95,
80,100,75,70,95,90,90,70,95,50,65,85,95,100,65};
frequency(scores,30);
return 0;
}
void frequency(int scores[], int max)
{
int i,j,count=0,flag=0,occur=0;
int *score=malloc(sizeof(int));
if(malloc==NULL)
{
printf("memory allocation failed");
exit(1);
//it's good to check if memory allocated was successful or not
//I've avoided it for further allocations,to decrease the size of post :)
}
int *freq=malloc(sizeof(int));
printf("score\tfrequency\n");
printf("-----\t---------\n");
//building array which has only scores
for(i=0;i<max;i++)
{
if(count==0) //first time
{
score=realloc(score,(count+1)*sizeof(int));
//increasing size of array by 1*sizeof(int)
score[count]=scores[i];
count++;
}//first one requires no checking whether it's repeated or not
else
{
flag=0; //resetting flag value
for(j=0;j<count;j++)
{
if(scores[i]==score[j])
{
flag=1; //
break;
}
}
if(flag==0) // if not repeated need to add new element
{
score=realloc(score,(count+1)*sizeof(int));
score[count]=scores[i];
count++;
}
}
}
//allocating memory for frequency array
freq=realloc(freq,count*sizeof(int));
//building array which has frequency of each score
for(i=0;i<count;i++)
{
occur=0;
for(j=0;j<max;j++)
{
if(score[i]==scores[j])
occur++;
}
freq[i]=occur;
}
for(i=0;i<count;i++) //printing output
printf("\n %d\t %d\n",score[i],freq[i]);
free(score); //freeing the blocks
free(freq);
}
My approach is quite simple to understand
first I create array score which creates extra memory whenever it encounters unique elements and stores in it
and then I check occurrences for each of the element of score array in the scores array and store them in freq array.
Output:
score frequency
----- ---------
90 3
85 3
100 3
50 3
60 2
70 4
55 2
80 2
95 5
75 1
65 2
I hope this is what you were trying to achieve :)

LCP array for Suffix Array

How to compute the LCP array for a suffix array? It doesn't have to be the most efficient. O(n log n) or O(n) will do. Something relatively easy to code if possible.
Here is a simple C++ implementation.
Longest common prefix(LCP) will be saved in lcp[MAX] array :)
char str[MAX];
int n,gap,sa[MAX],pos[MAX],tmp[MAX],lcp[MAX];
// sa stores the sorted index of the suffixes
// pos stores the serial number of a index in the sorted sequence
bool sufCmp(int i, int j)
{
if(pos[i]!=pos[j])
return pos[i]<pos[j];
i+=gap;
j+=gap;
return (i<n&&j<n)?pos[i]<pos[j]:i>j;
}
void buildSA()
{
n=strlen(str);
for(int i=0;i<n;i++)
sa[i]=i,pos[i]=str[i];
for(gap=1;;gap*=2)
{
sort(sa,sa+n,sufCmp);
for(int i=0;i<n-1;i++)
tmp[i+1]=tmp[i]+sufCmp(sa[i],sa[i+1]);
for(int i=0;i<n;i++)
pos[sa[i]]=tmp[i];
if(tmp[n-1]==n-1)
break;
}
}
void buildLCP()
{
for(int i=0,k=0;i<n;++i)
{
if(pos[i]==n-1)
lcp[pos[i]]=0;
else
{
for(int j=sa[pos[i]+1];str[i+k]==str[j+k];)
k++;
lcp[pos[i]]=k;
if(k)
k--;
}
}
}

8-Queens snippet

I have currently learning backtracking and got stuck on the 8-queen problem, I am using a 8x8 matrix and I think I've got some problems regarding the matrix passing to functions, any help would be highly apreciated.I wouldn't mind if anyone would bring any optimisation to the code, thanks.
here is my code.
#include <stdio.h>
#include <stdlib.h>
#define MAX 7
//void azzera(int **mat);
void posiziona(int **mat, int r,int c);
void stampa(int **mat);
int in_scacchi(int **mat,int r ,int c);
int main(int argc, char *argv[])
{
int i=0,j=0;
int **mat=(int **)malloc(sizeof(int *)*MAX);
for(i=0;i<=MAX;i++){
mat[i]=(int *)malloc(MAX*sizeof(int));
for(j=0;j<=MAX;j++){
mat[i][j]=-1;
}
}
printf("insert pos of the first queen on the first row (1-8) :");
scanf("%d",&i);
i-=1;
mat[0][i]=1;
posiziona(mat,1,0);
stampa(mat);
system("PAUSE");
return 0;
}
/*void azzera(int **mat){
int i=0,j=0;
for(i=0;i<=MAX;i++){
for(j=0;j<=MAX;j++){
mat[i][j]=-1;
}
}
}*/
void stampa(int **mat){
int i,j;
for(i=0;i<=MAX;i++){
for(j=0;j<=MAX;j++){
printf(" %d",mat[i][j]);
}
printf("\n");
}
}
void posiziona(int **mat, int r,int c){
int i=0,riga=1,flag_col=-1,flag_riga=-1;
if(riga<=7&&flag_riga!=1){
if(flag_riga==1){
flag_riga=-1;
posiziona(mat,r+1,0);
}
else if(in_scacchi(mat,r,c)==1){
if(c==MAX)
posiziona(mat,r-1,0);
posiziona(mat,r,c+1);
}
else{
flag_riga=1;
}
}
}
int in_scacchi(int **mat,int r ,int c){
int i,j,k,m;
int flag=0;
//col
for(i=0;i<r;i++){
for(j=0;j<=c;j++){
if(((mat[i][j]==1)&&(c==j)))
return 1;
}
}
//diag \
for(i=0;i<MAX-r;i++){
for(j=0;j<=MAX-c;j++){
if(mat[MAX-r-i][MAX-c-j]==1)
return 1;
}
}
//antidiag
for(i=r+1;i<=MAX;i++){
for(j=c+1;j<=MAX;j++){
if(mat[r-i][c+j]==1) {
return 1;
}
}
}
return 0;
}
1. One glaring problem is the memory allocation:
int **mat=(int **)malloc(sizeof(int *)*MAX);
for(i=0;i<=MAX;i++){
mat[i]=(int *)malloc(MAX*sizeof(int));
Given that MAX is 7, both mallocs are allocating too little memory for the matrix (seven elements instead of eight).
To be honest, I'd rename MAX to SIZE or something similar, and change all your loops to use strict less-than, i.e.
for(i = 0; i < SIZE; i++) {
I would argue that this is slightly more idiomatic and less prone to errors.
2. I haven't tried to debug the logic (I don't think it's fair to expect us to do that). However, I have noticed that nowhere except in main do you assign to elements of mat. To me this suggests that the code can't possibly be correct.
3. Beyond that, it may be useful to observe that in a valid solution every row of the chessboard contains exactly one queen. This means that you don't really need an 8x8 matrix to represent the solution: an 8-element array of column positions will do.
edit In response to your question in the comments, here is a complete Python implementation demonstrating point 3 above:
def can_place(col_positions, col):
row = len(col_positions)
for r, c in enumerate(col_positions):
if c == col or abs(c - col) == abs(r - row): return False
return True
def queens(n, col_positions = []):
if len(col_positions) >= n:
pretty_print(n, col_positions)
return True
for col in xrange(n):
if can_place(col_positions, col):
if queens(n, col_positions + [col]):
return True
return False
def pretty_print(n, col_positions):
for col in col_positions:
print '.' * col + 'X' + '.' * (n - 1 - col)
queens(8)
Your matrix must iterate from 0 to MAX-1,
i.e
int **mat= malloc(sizeof(int *)*MAX);
for(i=0;i< MAX;i++){ //see for i<MAX
mat[i]= malloc(MAX*sizeof(int));
for(j=0;j<MAX;j++){ //see for j<MAX
mat[i][j]=-1;
}
}
malloc must be called with sizeof(...) * (MAX+1) in both the i- and j-loop.
Moreover, when I ran your program I got an access violation in the antidiag portion of in_scacchi(...) due to the fact that the code tries to access mat[r-i][c+j] which evaluates to mat[-1][1] because r==1 and i==2.
So there seems to be a logical error in your description of the anti-diagonal of the matrix.

How to create threads and sort correctly in a odd-even sorting program?

I am trying to implement the odd-even transposition sorting algorithm in c with multi-threading. The program will receive a file with a line of integers that need to be correctly sorted. I have created the array that the program will work with and I am reading in the data correctly. Although, I am not quite sure how to create the threads right. I know that amount of threads I will need will always be N/2. However the N will not always be 20, so I am handling a finite amount right now. That's a limitation though b/c N will not always be 20. It could be higher. My program is only able to handle twenty right now. I'm also having trouble with the sorting part as well even though I have a function named swap already. The start point function is where this all takes place. I am not sure where to begin on this issue as well.
This is my code so far:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
int list[20];
int n = 20;
int param[10];
pthread_t threads[10];
void readLINE(char *filename);
void do_swap(int R1, int R2);
void display();
void *startPoint( void *arg );
void readLINE(char *filename)
{
FILE* file;
int i,j;
file = fopen(filename,"r");
if(file==NULL)
{
printf("Error: can't open file.\n");
}
else
{
printf("File opened successfully.\n");
i = 0;
while(!feof(file))
{
fscanf(file,"%d", &list[i]);
i++;
}
printf("The numbers are: \n");
for(j=0; j< i-1; j++)
{
printf("%d\n", list[j]);
}
fclose(file);
}
n = i-1;
}
//swap positions of arguments in list array
void swap(int R1, int R2)
{
if (list[R1] > list[R1+1])
{
int temp = list[R1];
list[R1] = list[R2];
list[R2] = temp;
}
}
void display()
{
int count;
for (count = 0; count < n; count++)
{
//cout << list[count] << " " ;
printf("%d ",list[count]);
}
//cout << endl;
printf("\n");
}
void *startPoint( void *arg )
{
int R1 = *(int*)arg;
int count;
for (count = 0; count < n/2; count++)
{
}
return 0;
}
int main(int argc, char** argv)
{
pthread_attr_t tattr;
pthread_attr_init (&tattr);
pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
readLINE(argv[1]);
printf("list[] presorted:");
display();
//create n/2 threads to do the sorting algorithm
//the parameter to each thread is an int:
//first thread param is 0
//second thread param is 2
//third thread param is 4 etc....
int count;
for (count = 0; count < n/2; count++)
{
param[count] = count*2;
pthread_create( &threads[ count], NULL, startPoint, (void*) &param[count]);
}
//wait for all the reads to finish before exiting the program
//otherwise the process would exit and abort all the threads
for (count = 0; count < n/2; count++)
{
pthread_join(threads[count], NULL);
}
//display the sorted state of the list
printf("list[] after sorting: ");
display();
exit(0);
}
It has been roughly 10 years since I wrote standard C code, so forgive any minor errors. I do think I can help you conceptually.
You are allocating your buffers statically. Instead, determine the sizes involved and dynamically allocate the memory you need. Here's a good reference. Basically determine n as you read in the file, and use malloc to allocate list and param based on that value instead of allocating a fixed array.
What specific problem are you having with the sorting part? Do you get a compiler error, runtime error, incorrect sorting result, ...?
UPDATE:
Here's a discussion of serial and parallel sorting that includes an implementation of parallel odd even transition sorting in C.

Resources