trying to fix possibly a memory issue? - c

I'm running a 4x4 matrix in my code. Sometimes I get the correct answer, sometimes I get some of the right solution and the rest is weird numbers. For instance, my matrices are both
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
My solution should be
10 20 30 40
10 20 30 40
10 20 30 40
10 20 30 40
but sometimes I get
10 20 30 40
10 20 30 40
10 20 20 20
10 20 30 40
I believe I have a memory problem but I'm not sure how to fix it. I have tried deallocating memory but it didn't change anything, however, I could have put it in the wrong place.
Heres my code
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
//Create a typedef to pass vectors into the dot product
typedef struct {
int L;
float *v1;
float *v2;
} dotVectors;
//Prototype for the readMatrix method
float** readMatrix(int *nRows, int *nCols,FILE* f);
//Threaded dot product
void* pDotProduct(void *p){
//Recast the void pointer to a dotVectors pointer
dotVectors *p1 = (dotVectors*) p;
//Get all the stuff where the pointer is pointing
int L = p1->L;
float *v1 = p1->v1;
float *v2 = p1->v2;
float *sum = (float*)malloc(sizeof(float));
//Do the dot product
*sum=0;
int i; for(i=0;i<L;i++){
*sum+=v1[i]*v2[i];
} free(v2);
//Return the sum
pthread_exit((void*)sum);
}
//Creates an empty matrix with r rows and c columns
float** createFloatMatrix(int r, int c) {
float** newMatrix =(float**)malloc(r*sizeof(float*));
int i;
for(i=0; i<c; i++) newMatrix[i]=(float*)malloc(c*sizeof(float));
return newMatrix;
}
//Initializes a matrix with "value"
void initMatrix(float **M, int r, int c, float value){
int i,j;
for (i=0; i<r; i++)
for(j=0; j<c; j++)
M[i][j]=value;
}
//Prints out a matrix with r rows and c columns
void printMatrix(float** m, int r, int c) {
int i,j;
for(i=0;i<r;i++){
for(j=0; j<c; j++){ printf("%g ", m[i][j]);}
printf("\n");}
}
main() {
float **m1,**m2;
int i,j,r1,c1,r2,c2;
//Read in the first matrix from a file M1
FILE* f;
f=fopen("m1","r");
//Reads the matrices from standard input - one file at a time
m1 = readMatrix(&r1,&c1,f);
fclose(f);
//Read in a second matrix from a file M2
f=fopen("m2","r");
m2 = readMatrix(&r2,&c2,f);
fclose(f);
//*************//
pthread_t t[r1][c2];
//****************//
//Create a dotVectors and fill it in
int cr=c1; int rc; int k;
for(i=0;i<r1;i++){
for(j=0;j<c2;j++){
dotVectors *d= (dotVectors*)malloc(sizeof(dotVectors));
//Create a vector to store the jth column of the second matrix
float* temp = (float*)malloc(cr*sizeof(float));
for(k=0; k<cr; k++){ temp[k]=m2[k][j];}
d->L=c1;
d->v1=m1[i];
d->v2=temp;
rc = pthread_create(&t[i][j],NULL,pDotProduct,(void*)d);
}
}
//****************//
void* dp;
float** result=createFloatMatrix(r1,c2);
//initMatrix(result, r1, c2, 0);
for(i=0;i<r1;i++){
for(j=0;j<c2;j++){
pthread_join(t[i][j],&dp);
result[i][j] = *((float*)dp);
}
}printMatrix(result, r1,c2);
pthread_exit(NULL);
}
//Read a matrix from a file f
float** readMatrix(int *nRows, int *nCols, FILE* f) {
int i=0;
int j=0;
int k=0;
char c;
*nRows=1; //The number of rows
*nCols=1; //The number of columns
float nums[30][30];
char* num;
while(1) {
//Read in the numbers on a row
j=0; // j = the index of the number on the row - start at zero
while(1) {
//We will re-use the index i, so set to zero
i=0;
num = (char*)malloc(10*sizeof(char));
//Read characters from standard input until a space or EOL
while((c=getc(f))!=' ' && c!=10 && c!=EOF ) {
num[i++]=c;
}
//Null terminate the array of characters
num[i]=0;
//Changes the array of characters to a float
nums[k][j++]=atof(num);
//If we are at the end of the line or end of file - break
if( c==10 || c==EOF) break;
//Set the number of numbers
(*nCols)=j+1;
}
//Stop if you are at the end of file
if (c==EOF) break;
//Go to the next row
k++;
} //End while(1) outer loop
*nRows=k;
//Allocate memory for the row pointers
float** retMat = (float**)malloc((*nRows)*sizeof(float*));
//Allocate memory for the rows themselves
for(i=0; i<(*nRows); i++) retMat[i]=(float*)malloc((*nCols)*sizeof(float));
//Copy the nums matrix into the return matrix
for(i=0; i<(*nRows); i++) for(j=0; j<(*nCols); j++) retMat[i][j]=nums[i][j];
return retMat;
If I run through the debugger twenty or so times I get a segmentation fault that says it's in pthread_join (). But I do not see how it could be. Does anyone have any advice or help on this issue?

I just compiled this (missing a } at the end of your listing) with gcc -g -lpthread, then ran the resulting executable through valgrind. It generated lots of errors (memory allocated but not freed) but no segmentation faults - and the output was correct.
I definitely recommend getting this to work properly without threading first. You want to re-think your memory allocation strategy. For example, you can create a block of memory all at once, then create an array of pointers to it. This is what Numerical Recipes in C does - it allows you to "fake" a variable length 2D matrix. For each create you need a free as well. And make sure you keep track of rows vs columns. In your original code for creating an rxc matrix, you actually created cxc space - so if you had called it with r>c you would have had a segmentation fault just from that...
Example of doing this "better":
float** createFloatMatrix(int r, int c) {
float** newMatrix =(float**)malloc(r*sizeof(float*));
newMatrix[0] = malloc(r*c*sizeof (float) );
for(i=1; i<r; i++) newMatrix[i]=newMatrix[0] + i*c;
return newMatrix;
}
And the corresponding
void freeFloatMatrix(float** m) {
free(m[0]); // this frees the whole block
free(m); // this frees the array of pointers
}
Of course your readMatrix function is doing some horrible things - it is assuming that the input matrix cannot be larger than 30x30 but doesn't test to make sure that it stays in bounds; when you create a return matrix you don't use your own createFloatMatrix function, ...
Finally - it seems like you are doing matrix multiplication in an incredibly complex way. The following would appear to do the same thing, but in fewer lines. Is there a reason why you don't do it this way?
#include <stdio.h>
#include <stdlib.h>
//Prototypes
float** readMatrix(int *nRows, int *nCols,FILE* f);
void freeFloatMatrix(float**);
//Prints out a matrix with r rows and c columns
void printMatrix(float** m, int r, int c) {
int i,j;
for(i=0;i<r;i++) {
for(j=0; j<c; j++) {
printf("%g ", m[i][j]);
}
printf("\n");
}
}
// rewritten function for allocating float matrix:
float** createFloatMatrix(int r, int c) {
int i;
float** newMatrix =(float**)malloc(r*sizeof(float*));
newMatrix[0] = malloc(r*c*sizeof (float) );
for(i=1; i<r; i++) newMatrix[i]=newMatrix[0] + i*c;
return newMatrix;
}
// need a function to free the matrix!!
void freeFloatMatrix(float** m) {
free(m[0]); // this frees the whole block
free(m); // this frees the array of pointers
}
int main(void) { // <<<< let's get the signature right...
float **m1,**m2;
int i,j,r1,c1,r2,c2;
//Read in the first matrix from a file M1
FILE* f;
f=fopen("m1","r");
m1 = readMatrix(&r1,&c1,f);
fclose(f);
//Read in a second matrix from a file M2
f=fopen("m2","r");
m2 = readMatrix(&r2,&c2,f);
fclose(f);
// make sure that the dimensions match up:
if(c1 == r2) {
float temp, **m3;
int ii, jj, kk;
m3 = createFloatMatrix(r1, c2);
for(ii = 0; ii < r1; ii++) {
for(jj = 0; jj < c2; jj++) {
temp = 0;
for(kk = 0; kk < c1; kk++) {
temp += m1[ii][kk] * m2[kk][jj];
}
m3[ii][jj] = temp;
}
}
printf("The product of the matrices is:\n");
printMatrix(m3, r1, c2);
freeFloatMatrix(m3);
}
else printf("dimensions don't match!\n");
freeFloatMatrix(m2);
freeFloatMatrix(m1);
return 0;
}
//Read a matrix from a file f
float** readMatrix(int *nRows, int *nCols, FILE* f) {
int i=0;
int j=0;
int k=0;
char c;
*nRows=1; //The number of rows
*nCols=1; //The number of columns
float nums[30][30];
char num[10];
while(1) {
//Read in the numbers on a row
j=0; // j = the index of the number on the row - start at zero
while(1) {
//We will re-use the index i, so set to zero
i=0;
//Read characters from standard input until a space or EOL
while((c=getc(f))!=' ' && c!=10 && c!=EOF && i < 10) {
num[i++]=c;
}
//Null terminate the array of characters
num[i]=0;
//Changes the array of characters to a float
nums[k][j++]=atof(num);
//If we are at the end of the line or end of file - break
if( c==10 || c==EOF || j == 30) break;
//Set the number of numbers
(*nCols)=j+1;
}
//Stop if you are at the end of file
if (c==EOF) break;
//Go to the next row
k++;
if (k == 30) break;
} //End while(1) outer loop
*nRows=k;
//Allocate memory for the row pointers using the function we defined before
float** retMat = createFloatMatrix(*nRows, *nCols);
return retMat;
}
Note - there are plenty of other places where this code can be improved... but at least the above will do an OK job of matrix multiplication when you have well conditioned inputs which do not exceed the size you assumed in your code.
Once you convince yourself that this works you could consider adding threading at some level - assuming that your assignment includes making this code multi-threaded. My personal approach would be to #include <omp.h> and just add #pragma omp for in the appropriate place, but then I'm lazy when it comes to multi-threading.

Related

How to return a double pointer from a function and send it as input into another function?

I am new to programming and am trying to use two functions for matrix (2D array) operations, where the output of one function is the input for the next.
However, I do not find a way to correctly deliver the values from one function to another. When I print the outputs of the first function in main (), they are correct, but when I input them into the 2nd function and print them, the values make no sense. I have tried it a lot of ways, but it probably fails due to my lack of understanding double pointers.
I am thankful for any hint or advise!
#include <stdio.h>
#include <stdlib.h>
int** td (int r_in, int c_in, int r_p, int c_p, int input[][c_in],int params[][c_p]){
int i, j, k;
int**y_td;
// memory allocation
y_td = (int*)malloc(sizeof(int*)*r_in);
for (i=0; i < r_in; i++){
y_td[i] = (int*)malloc(sizeof(int)*c_p);
}
//
for (i=0; i < r_in; i++){
for (j=0; j < c_p; j++){
y_td[i][j]=0; // Initialization
for (k=0; k < c_in; k++){
y_td[i][j]+= input[i][k]*params[k][j];
}
}
}
return y_td;
}
int** cnv (int r_in, int c_in, int filter, int f_size, int input[][c_in], int params[][f_size][c_in]){
int x,i,j,k,l,m,n;
int min_len = ((r_in < f_size)? r_in:f_size);
int max_len = ((r_in > f_size)? r_in:f_size);
int r_out = max_len - min_len + 1;//rows_out
int kernel;
int** y_cnv;
// Print input to check if it was correctly transmitted to the function
printf("Input CV (should be equal to TD result):\n");
for (i=0;i<r_in;i++){
for (j=0;j<c_in;j++){
printf("%d ", input[i][j]);
}
printf("\n");
}
printf("\n\n");
//memory allocation
y_cnv = (int*)malloc(sizeof(int*)*r_out);
for (i=0; i < r_out; i++){
y_cnv[i] = (int*)malloc(sizeof(int)*filter);
}
//
for (i=0; i < filter; i++){
for (k=0; k < r_out; k++){
y_cnv [k][i]=0; //initialize
}
for (j = 0; j < c_in; j++){
for (n = min_len-1; n < max_len; n++){
x = n-min_len+1;
for (m= 0; m < r_in; m++){
kernel = (((n-m) < min_len && (n-m) >= 0)? params[i][n-m][j]:0);
y_cnv[x][i] += input[m][j]*kernel;
}
}
}
}
return y_cnv;
}
int main() {
// create test arrays
int A [4][2]= {{1,1},{2,2},{3,3},{4,4}};
int B [2][3]= {{1,2,3},{2,3,4}};
int C [2][2][3]= {{{1,1,1},{2,2,2}},{{3,3,3},{4,4,4}}};
int** matrix;
int i, j;
matrix = td(4,2,2,3,A,B);
// print the result of first function, which is input in 2nd function
printf("The TD result is:\n");
for (i=0;i<4;i++){
for (j=0;j<3;j++){
printf("%d ",matrix[i][j]);
}
printf("\n");
}
printf("\n\n");
matrix = cnv(4,3,2,2,matrix,C);
return 0;
}
I expect the matrix printed in main () after the first function td () to be the same as when I read it in the second function cnv () and print it there, but it is not.
take a look at this question. You were hit by the same underlying problem.
Turning
int** cnv (int r_in, int c_in, int filter, int f_size, int input[][c_in], int params[][f_size][c_in])
into
int** cnv (int r_in, int c_in, int filter, int f_size, int** input, int params[][f_size][c_in])
fixes the problem you asked for.
The reason is that you allocate an array of pointers called y_td in your first function. Each of this pointers is a number naming a memory segment where you stored some real numbers. By using int input[][c_in] you tell the computer to interpret these pointers as integer numbers and when you print them you get the addresses in memory instead of the expected values, because then input[x][y] is translated to *((int *)input+x*c_in+y).
Please allow me one more comment: You should follow the comments below the question and care for all compiler warnings: If there is a warning you should treat it as an compiler error unless you exactly know what you are doing, especially in C. Your code contains some possible problem sources like the one above.

Allocating memory to 2D array using an array of NULL (c)

thanks for taking the time in reading this.
In my question a "vector" is defined as a 1D dimensional array of integers.
Therefore an array of vectors would be a 2D dimensional array in which every vector can be of a different length.
I'm asked to use:
int** vectors- the 2D array
int size -an integer that represents how many vectors exist inside **vectors
int* sizes-a 1D array of integers that represents the length of the vectors
for example,for:
vectors = {{4,3,4,3},{11,22,33,44,55,66},NULL,{5},{3,33,333,33,3}}.
size is 5 (there are 5 vectors inside vectors).
sizes is {4,6,0,1,5} (4 is the length of the first vector and so on).
size is inputted by the user at the beginning of main() and **vectors&*sizes are dynimacilly allocated with size's value.
I'm asked to write the function:
int init(int ***vectors, int **sizes, int size) which initializes **vectors to be an array of NULLs and *sizes to be an array of zeros.
I came up with this code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int init(int*** vectors, int** sizes, int size)
{
int i, k,j;
printf("check\n");
*vectors = (int**)malloc(size * sizeof(int*));
if (*vectors == NULL)
return 0;
for (i = 0; i < size; i++)
{
*(vectors + i) = NULL;
}
printf("check 2\n");
for (k = 0; k<size; k++)
{
if (*(vectors+k) != NULL)
printf("didn't work\n");
else
printf("current is null\n");
}
*sizes= (int*)malloc(size * sizeof(int));
if (*sizes == NULL)
return 0;
for (j= 0; j < size; j++)
{
*(sizes + j) = 0;
printf("%d ", *(sizes + j));
}
printf("\n");
return 1;
}
int main()
{
int size, i;
int** vectors = NULL;
int* sizes = NULL;
printf("\nPlease enter an amount of vectors:\n");
scanf("%d", &size);
printf("%d\n", init(&vectors, &sizes, size));
printf("size is %d now\n", size);
// for (i = 0; i < size; i++)
// printf("%d ", *(sizes+i));
printf("check 3\n");
free(sizes);
free(vectors);
printf("check 4\n");
printf("check 5\n");
return 0;
}
forgot to mention that init returns 0 if it fails to allocate memory and 1 otherwise.
printing the "checks" was so I could see where the program fails.
the problem is that no matter what,after printing the last check (check 5)
the program fails.(Run-Time Check Failure #2)
if anyone could help me understand what I'm doing wrong I would HIGHLY appreciate it.
thanks alot for reading and have an amazing day.
edit:
i also printed the array sizes/vectors inside init just to see if it prints zeros/nulls,i don't actually need to do it.
One problem of OP's code is in the pointer arithmetic. Given:
int ***vectors;
*vectors = malloc(size * sizeof(int*));
This loop:
for (i = 0; i < size; i++)
{
*(vectors + i) = NULL;
}
Would iterate over the next unallocated pointer to pointer to pointer to int, while what the OP needs is
for (i = 0; i < size; i++)
{
*(*vectors + i) = NULL; // or (*vectors)[i] = NULL;
}
The same holds in the following loops, where *(sizes + j) is used instead of *(*sizes + j) (or (*sizes)[j]).

Sparse matrix multiplication using MKL

I am implementing sparse matrix multiplication using MKL library and benchmarking on various Intel processors like Intel Xeon E5 and Intel Xeon Phi.
Although I am able to benchmark with satisfactory results on Xeon E5, everytime I run the same code on Xeon Phi, I get segmentation fault after 3 iterations from the called "mkl_dcsrmultcsr" function. I am not able to figure out the reason for this, please let me know what might be the reason.
Following is the code
#include "stdio.h"
#include "stdlib.h"
#include "time.h"
#include "omp.h"
#include "mkl.h"
#include "mkl_spblas.h"
double timerval ()
{
struct timeval st;
gettimeofday(&st, NULL);
return (st.tv_sec+st.tv_usec*1e-6);
}
int main(){
double *nz, *nzc;
int *ia,*ja, *ic,*jc,*pos;
int info=1;
int i, j, k;
FILE *fp1,*fp2,*fp3,*fp4;
double avg_time = 0, s_time, e_time;
//open file to write results
//FILE *fp1;
char trans = 'N';
int sort = 1;
int m=4;
int iterations;
int request = 0;
/* iterate the loop for input size from 2exp3 to 2exp10 */
for (iterations=0; iterations<8; iterations++)
{
m *= 2; // increase the dimension of Matrix with every iteration
int n = m; // Assuming a square matrix.
int nzmax =m*n ;
double dense_const = 0.05;
int temp5, temp6,temp3,temp4;
int density=(m*n)*(dense_const);
//memory allocation for matrix A and B
nz = calloc((m*n),sizeof(double));
ia = calloc((m*n),sizeof(int));
ja = calloc((m*n),sizeof(int));
//memory allocation for product matrix C
nzc =calloc((m*n),sizeof(double));
ic = calloc((m*n),sizeof(int));
jc = calloc((m*n),sizeof(int));
//Configuration parameters
k=0;
//density of the sparse matrix to be created. Assume 5% density.
//position array for random initialisation of positions in input matrix
pos= calloc((m*n), sizeof(int));
int temp,temp1;
// printf("the density is %d\n",density);
// printf("check 1:\n");
//randomly initialise positions
for(i=0;i<density;i++)
{
temp1=rand()%(m*n);
pos[i]=temp1;
}
// printf("check 2:\n");
//sort the 'pos' array
for (i = 0 ; i < density; i++)
{
int d = i;
int t;
while ( d > 0 && pos[d] < pos[d-1])
{
t = pos[d];
pos[d] = pos[d-1];
pos[d-1] = t;
d--;
}
}
//printf("check 3:\n");
// initialise with non zero elements and extract column and row ptr vector
j=1;
ja[0]=1;
int p=0;
for(i = 0; i < density; i++)
{
temp=pos[i];
nz[k] = rand();
// nz[k] = 1;
ia[k] = temp%m;
k++;
p++;
temp5= pos[i];
temp6=pos[i+1];
temp3=temp5-(temp5%m);
temp4=temp6-(temp6%m);
if(!(temp3== temp4))
{
if((temp3+m==temp6))
{}
else
{
ja[j]=p+1;
j++;
}
}
}
printf("check1\n");
request = 0;
s_time = timerval();
for(i=0; i<1000;i++)
{
#pragma omp parallel
{
mkl_dcsrmultcsr(&trans, &request, &sort, &n, &n, &n, nz, ia, ja, nz, ia, ja, nzc, jc, ic, &nzmax, &info);
}
}
e_time = timerval();
avg_time = (e_time - s_time);
/* write the timing information in "output.txt"*/
avg_time = avg_time / 1000;
printf("check 5:\n");
if((fp2 = fopen("output.txt","a"))==NULL)
{
printf("error opening file\n");
}
//fseek(fp1,1000,SEEK_END);
fprintf (fp2, "\n Input size: %d x %d ,Time: %lf and density is %d and info is %d \n", m,n, avg_time, density,info);
fclose(fp2);
//mkl_free_buffers();
free(ja);
free(ia);
free(nz);
free(pos);
free(jc);
free(ic);
free(nzc);
}
return 0;
}
You can use mkl_(thread_)free_buffers() before a call to the multiplication functions. That worked out for me!

Dynamically allocated array - elements not accessible

I was writing a matrix multiplication program, and to save code space I created a function make that takes a pointer to a double pointer and dynamically allocates a 2-dimensional array of given size. The arrays a and b are intialised to random values in [-2, 2]. However, when I try to run the code on gcc, I get a seg fault.
I ran the code through gdb, and the error arises when I try to set b[0][0] to a random number. When I try to print b[0][0] in gdb, I get the error:
Cannot access memory at address 0xbfebfdc3f5d77f80
However, I'm actually able to access b[0][0] before this. I can print the array just after allocating it without errors. For some reason, it's always the array b that seems to cause problems.
I've a feeling it's a pointer issue, but I can't see where. I'm not that inexperienced a programmer, but I spent the guts of 2 days trying to find out why this error keeps appearing. Can anyone shed some light?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void make(double ***a, int m, int n)
{
int i;
double *tmp;
(*a) = (double **) malloc(m*sizeof(double *));
tmp = (double *) calloc(m*n,sizeof(double));
if(tmp == NULL)
{
printf("Error with malloc.\n");
exit(EXIT_FAILURE);
}
for(i=0;i<m;i++)
(*a)[i] = &tmp[i*n];
free(tmp);
if(a == NULL)
{
fprintf(stderr, "Error with the matrix, dimensions: %d, %d. \n", m, n);
exit(EXIT_FAILURE);
}
}
int main()
{
int i, j;
int l, m, n;
double **a, **b, **c;
l = m = n = 8;
srand48(time(NULL));
make(&a, l, m);
make(&b, m, n);
make(&c, l, n);
for(i=0; i<l; i++)
for(j=0; j<m; j++)
a[i][j] = (drand48()*4.0) - 2.0;
for(i=0; i<m; i++)
for(j=0; j<n; j++)
b[i][j] = (drand48()*4.0) - 2.0;
free(a);
free(b);
free(c);
return 0;
}
One problem is the call to free(tmp) in make. That is the memory that was allocated for the array. It should not be freed if you plan to continue using it.
You need to allocate memory for every row in the "would-be 2D array", you only allocate memory for the first row, then have every pointer point at that same data. This doesn't make any sense.
You don't check if the first malloc call succeeded.
You shouldn't call free from this function.
It is always best to create a true 2D array with adjacently allocated memory cells, rather than some pointer-to-pointer mess.
i have pasted my partial code over here
int *nn,*kk;
int main()
{
int t=0,i;
scanf("%d",&t);
int maxx=0;
nn = new int [t];
kk = new int [t];
for(i=0;i<t;i++)
{
scanf("%d%d",&n,&k);
nn[i] = n;
kk[i] = k;
if(maxx<n)
maxx=n;
cout<<nn[i]<<" "<<kk[i]<<endl;
}
t=0;
for(i=0;i<t;i++)
{
n = nn[i];
k = kk[i];cout<<nn[i]<<" "<<kk[i]<<endl;
//cout<<setprecision(6);
if(k<34&&n>k)
//cout<<a[n][k]<<endl;
printf("%0.7lf\n",a[n][k]);
else
printf("0.000000\n");//cout<<"0\n";
}
delete []nn;
delete []kk;
return 0;
}

changing rows into column and column into rows of that 2d array

I want to change rows into column and column into rows of that 2-D array
I want a program which takes input and gives output as below.
Input: 1 2 3
4 5 6
Output: 1 4
2 5
3 6
Input: 1 2 3
4 5 6
7 8 9
Output: 1 4 7
2 5 8
3 6 9
I did a sample which in hardcoded array as below
int main()
{
int i,j;
int grades[2][3] = { {55, 60, 65},
{85, 90, 95}
};
for( j = 0; j < 3; j++)
{
for( i = 0; i < 2;i++)
{
printf("%d\t",grades[i][j]);
}
printf("\n");
}
return 0;
}
Its long time since i programmed in C , is there anyway we can make things dynamic or better way of doing the same. Right now its hardcoded.
I remember we have to use malloc or so , is that right.
psuedo code is also fine.
Taking from Zhehao Mao user and fixing it, the would look like this:
#include <stdio.h>
void transpose(int *src, int *dest, int rows, int cols){
int i,j;
for(i=0; i<rows; i++){
for(j=0; j<cols; j++){
dest[j*rows + i] = src[i*cols + j];
}
}
}
int main(void)
{
int oldar[2][3] = {{1,2,3},{4,5,6}};
int newar[3][2];
transpose(&oldar[0][0], &newar[0][0], 2, 3);
int i, j;
for(i = 0; i < 2; i++)
{
for(j = 0; j < 3; j++)
printf("%d ", oldar[i][j]);
printf("\n");
}
for(i = 0; i < 3; i++)
{
for(j = 0; j < 2; j++)
printf("%d ", newar[i][j]);
printf("\n");
}
}
The reason the original post can't work is that int ** expects a pointer to pointers like:
int **a ---------> int *int1 --> 1
int *int2 --> 2
int *int3 --> 3
which is not what we get when we say int a[n][m]. Rather we have the array organized like this
a[0][0]
\
1 2 3 4 5 6
\___/ \___/
"a[0]" / \____ "a[1]"
or something like this. The picture likely does not explain it well, but currently I can't do better.
void main()
{
clrscr();
int in[10][10];
int out[10][10];
int row,column,i,j;
printf("enter row");
scanf("%d",&row);
printf("Enter column");
scanf("%d",&column);
//storing values in matrix
for(i=1;i<=row;i++)
{
for(j=1;j<=column;j++)
{
printf("Enter (%d,%d)th value",i,j);
scanf("%d",&in[i-1][j-1]);
}
}
//show stored values
printf("\ninput is\n\n");
for(i=0;i<row;i++)
{
for(j=0;j<column;j++)
{
printf("%d\t",in[i][j]);
}
printf("\n");
}
//show transposed value. it is also stored in out matrix
printf("\nOutput is\n\n");
for(i=0;i<column;i++)
{
for(j=0;j<row;j++)
{
printf("%d\t",in[j][i]);
out[i][j]=in[j][i];
}
printf("\n");
}
getch();
}
//////////////////////////////////////
input matrix is stored in in[][] matrix and output matrix stored in out[][] matrix.
this program will work for any matrix with row and column below 10 if we increase the matrix variable value ,it will work for larger matrix also .
Here is a rather naive implementation. I'm pretty sure there are more efficient ways, but this is all I could think of.
void transpose(int **src, int **dest, int rows, int cols){
int i,j;
for(i=0; i<rows; i++){
for(j=0; j<cols; j++){
dest[j][i] = src[i][j];
}
}
}
int main(void){
int oldar[2][3] = {{1,2,3},{4,5,6}};
int newar[3][2];
transpose(oldar, newar, 2, 3);
}
Double pointers can represent double arrays, so there is no need to allocate on the heap here.
This is a half-done program the way I would do it in C:
int main()
{
int **data;
int rows = 0,
columns = 0;
char in[256];
int *irow;
// Get user input.
for(rows = 0; 1; ++rows)
{
scanf("%255s", in);
if(strcmp(in, "exit") == 0)
break;
// Parse row here. Remove all the tabs. Set column count.
for(int icolumn = 0; 1; ++icolumn)
{
/* ... */
}
// Set columns if first time.
if(rows == 0)
columns = icolumn;
// Check to make sure user inputs correct amount of columns.
if(columns != icolumns)
{
printf("OMG! The user is a hacker!\n");
break;
}
// Push parsed row into **data.
data[rows] = irow;
}
// Display output.
for(int i = 0; i < columns; ++i)
{
for(int j = 0; j < rows; ++j)
{
printf("%d\t", data[j][i]);
}
printf("\n");
}
return 0;
}
I'm a C++ programmer, so the user input part is kind of messed up.
hey here is a simple solution without using malloc,i did this when i was on the 0th level for c and had no idea about "alloc.h" functions,
You can have the square array having #rows = #cols = max(#rows,#cols),if we take your example then the matrix would be a 3x3 matrix,then add any special char in the blank entries,so the matrix will look like this
matrix:1 2 3
4 5 6
# # #
now you can easily convert the matrix in the way you want...
Bottom line:To make the matrix operations simpler try to convert them in square matrix...
One more thing using MALLOC is the best possible way ,this is just in case you are not handy with all those alloc.h function defs...
theoretically, you have two arrays
Array x and y
Int grades [x] [y]
you can swap these two arrays and you get
int grades [y] [x]
to do that there are many methods e.g. by copying the arrays to another two 1D, or one 2D Array, or simple Pointer Swap

Resources