Ansi C, Multithreading MatrixMultiplication - c

I have been programming this multiplethreaded matrix multiplication.
Somehow the programm works, but it does not give me the values of the result matrix.
Here it is the code:
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
int rowA, rowB, colA, colB;
int myNrThreads = 0;
double **matrixA, **matrixB, **matrixOut;
void *multiplyThread (void *param);
void fillAndCheckMatrice(double **matrix, FILE *myFile, int row, int column) {
char *line = NULL;
char *p;
ssize_t read;
int i = 0, j = 0;
size_t length = 0;
getline (&line, &length, myFile);
p = strtok(line, " ");
row = atoi(p);
p = strtok(NULL, " ");
column = atoi(p);
printf("%d, %d\n", row, column);
matrix = malloc(row * sizeof(double*));
for (j = 0; j < row; ++j) {
matrix[j] = malloc(column * sizeof(double));
}
i = 0;
while ((read = getline (&line, &length, myFile)) != -1) {
j = 0;
p = strtok(line, " ");
while (p != NULL) {
matrix[i][j] = atof(p);
++j;
p = strtok(NULL, " ");
}
++i;
}
free(line);
}
int main (int argc, char* argv[])
{
pthread_t *myThread;
int counter, j, r;
FILE *fileA = fopen("matrixA.txt", "r");
FILE *fileB = fopen ("matrixB.txt", "r");
if (argc!=2)
{
printf("Usage: %s number_of_threads\n",argv[0]);
exit(-1);
}
myNrThreads = (atoi)(argv[1]);
fillAndCheckMatrice(matrixA, fileA, rowA, colA);
fillAndCheckMatrice(matrixB, fileB, rowB, colB);
matrixOut = malloc(rowA * sizeof(double*));
for (counter = 0; counter < rowA; ++counter) {
matrixOut[counter] = malloc (colB * sizeof(double));
}
myThread = malloc(myNrThreads * sizeof(pthread_t));
for (counter = 1; counter < myNrThreads; ++counter) {
r = pthread_create (&myThread[counter], NULL, multiplyThread, (void*)counter);
if (r != 0 ) {
printf ("No threads create!");
free (myThread);
exit(-1);
}
}
multiplyThread(0);
for (counter = 1; counter < myNrThreads; ++counter) {
pthread_join(myThread[counter], NULL);
}
for (counter = 0; counter < rowA; ++counter) {
for (j = 0; j < colB; ++j) {
printf ("%.5f ", matrixOut[counter][j]);
}
printf("\n");
}
fclose(fileA);
fclose(fileB);
free(myThread);
free(matrixA);
free(matrixB);
free(matrixOut);
return 0;
}
/*
* The method gets on the first line the dimensions of the matrice.
* While filling every postion of our matrice, we control
* if the given dimensions are the real dimensions of the matrice.
* Everything is read from the .txt file, produced from our python
* generator.
*
*/
void *multiplyThread(void *param){
int myParam = (int)param;
int limitBegin = (myParam * rowA) / myNrThreads;
int limitEnd = ((myParam + 1) * rowA) / myNrThreads;
int counterI, counterJ, counterK;
for (counterI = limitBegin; counterI < rowA; ++counterI) {
for (counterJ = 0; counterJ < colB; ++counterJ) {
matrixOut[counterI][counterJ] = 0;
for (counterK = 0; counterK < rowB; ++counterK) {
matrixOut[counterI][counterJ] +=matrixA[counterI][counterK] * matrixB[counterK][counterJ];
}
}
}
printf("finished slice %d\n", myParam);
return 0;
}
Any idea why???
Thanx in advance.
PS: at the pthread_create I get a warning at (void*)counter btw
EDIT:
matrixA and matrixB are given through matrixA.txt and matrixB.txt. They are read and the values are taken from that.
One of the txt file would look like this:
2 2 // The dimensions of the matrice
12 14
13 15
EDIT3: The new one. Here I get segmentation fault 11:
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
void *multiplyThread (void *param);
int rowA, rowB, colA, colB;
int myNrThreads = 0;
double **matrixA, **matrixB, **matrixOut;
void fillAndCheckMatrice(double **matrix, FILE *myFile, int ID) {
char *line = NULL;
char *p;
int row, column;
ssize_t read;
int i = 0, j = 0;
size_t length = 0;
getline (&line, &length, myFile);
p = strtok(line, " ");
row = atoi(p);
p = strtok(NULL, " ");
column = atoi(p);
printf("%d, %d\n", row, column);
if (ID == 1) {
rowA = row;
colA = column;
} else if (ID == 2) {
rowB = row;
colB = column;
}
matrix = malloc(row * sizeof(double*));
for (j = 0; j < row; ++j) {
matrix[j] = malloc(column * sizeof(double));
}
i = 0;
while ((read = getline (&line, &length, myFile)) != -1) {
j = 0;
p = strtok(line, " ");
while (p != NULL) {
matrix[i][j] = atof(p);
++j;
p = strtok(NULL, " ");
}
++i;
}
free(line);
}
int main (int argc, char* argv[])
{
pthread_t *myThread;
int counter, j, r;
FILE *fileA = fopen("matrixA.txt", "r");
FILE *fileB = fopen ("matrixB.txt", "r");
if (argc!=2)
{
printf("Usage: %s number_of_threads\n",argv[0]);
exit(-1);
}
myNrThreads = (atoi)(argv[1]);
fillAndCheckMatrice(matrixA, fileA, 1);
fillAndCheckMatrice(matrixB, fileB, 2);
matrixOut = malloc(rowA * sizeof(double*));
for (counter = 0; counter < rowA; ++counter) {
matrixOut[counter] = malloc (colB * sizeof(double));
}
for (counter = 0; counter < rowA; ++counter) {
for (j = 0; j < colB; ++j) {
printf ("%.5f ", matrixOut[counter][j]);
}
printf("\n");
}
myThread = malloc(myNrThreads * sizeof(pthread_t));
for (counter = 1; counter < myNrThreads; ++counter) {
printf("%d", counter);
if (pthread_create (&myThread[counter], NULL, multiplyThread, (void*)(intptr_t)counter) != 0) {
printf ("No threads create!");
free (myThread);
exit(-1);
}
}
for (counter = 0; counter < rowA; ++counter) {
for (j = 0; j < colB; ++j) {
printf ("%.5f ", matrixA[counter][j]);
}
printf("\n");
}
multiplyThread(0);
for (counter = 1; counter < myNrThreads; ++counter) {
pthread_join(myThread[counter], NULL);
}
fclose(fileA);
fclose(fileB);
free(myThread);
free(matrixA);
free(matrixB);
free(matrixOut);
return 0;
}
/*
* The method gets on the first line the dimensions of the matrice.
* While filling every postion of our matrice, we control
* if the given dimensions are the real dimensions of the matrice.
* Everything is read from the .txt file, produced from our python
* generator.
*
*/
void *multiplyThread(void *param){
int myParam = (int)param;
int limitBegin = (myParam * rowA) / myNrThreads;
int limitEnd = ((myParam + 1) * rowA) / myNrThreads;
int counterI, counterJ, counterK;
for (counterI = limitBegin; counterI < rowA; ++counterI) {
for (counterJ = 0; counterJ < colB; ++counterJ) {
matrixOut[counterI][counterJ] = 0;
for (counterK = 0; counterK < rowB; ++counterK) {
matrixOut[counterI][counterJ] +=matrixA[counterI][counterK] * matrixB[counterK][counterJ];
}
}
}
printf("finished slice %d\n", myParam);
return 0;
}

There are quite a few problems in the question code. Perhaps the best 'answer' would be to carefully walk through the code and point out some of the issues.
First, consider the following:
int rowA, rowB, colA, colB;
Nothing really wrong with the above line, until (later in main):
fillAndCheckMatrice(matrixA, fileA, rowA, colA);
fillAndCheckMatrice(matrixB, fileB, rowB, colB);
The above lines pass the 'values' of 'rowA', 'colA' 'rowB' and 'colB'. Being that these variables have no established values, it is obvious that there is trouble in the code.
Most likely, the intention is to initialize these values inside the 'fillAndCheckMatrice()' function. However, in order to initialize these variables, the 'address' of the variables must be passed into 'fillAndCheckMatrice()', (not their 'values'). Perhaps something like this:
fillAndCheckMatrice(matrixA, fileA, &rowA, &colA);
fillAndCheckMatrice(matrixB, fileB, &rowB, &colB);
Then, of course, the 'fillAndCheckMatrice()' will have to be modified as well; from:
void fillAndCheckMatrice(double **matrix, FILE *myFile, int row, int column) {
To:
void fillAndCheckMatrice(double **matrix, FILE *myFile, int *row, int *column) {
And then, of course, every reference to 'row' and 'column' will now have to deal with a pointer to a variable, instead of the variable value. Hence these:
row = atoi(p);
column = atoi(p);
printf("%d, %d\n", row, column);
Will have to change to these:
*row = atoi(p);
*column = atoi(p);
printf("%d, %d\n", *row, *column);
...and so forth...
matrix = malloc((*row) * sizeof(double*));
for (j = 0; j < *row; ++j) {
I will proceed debugging the question source upon request.

Related

Going over a matrix while multi-threading

I need to create a program that gets a dynamic matrix and changes it to one dimension, for example 4x4 matrix will give 16 arrays length, where each index has a odd or even number, matching the index itself. The threads needs to go over the matrix at the same time and copy the odd and even numbers to the correct places in the array. The main thread needs to wait for the rest of them to finish before printing the array and every value with its respective thread. It should come out like this
We managed to fix the segmentation fault that kept happening, but now we need to set it so that each thread runs right after the other but instead each thread runs 4 times and then it switches to a different one. How can I change it so it'll run as asked?
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <pthread.h>
#include <math.h>
#define CORE 4
int N;
int odd = 1;
int even = 0;
typedef struct my_thread {
int** matrix;
int* resArray;
int threadId;
int strart_raw;
int strart_cal;
int end_raw;
int end_cal;
int counter;
} my_thread;
void* createArray(struct my_thread* thread);
void main() {
pthread_t th[CORE];
int s_r = 0, s_c, e_r, e_c;
int i, j, lines, columns, * intMatrix;
printf("Type the N for the N*N matrix:\t");
scanf("%d", &N);
int size = N * N;
int result_Array[N * N];
int retcode;
int interval = size / CORE;
int matrix_build_counter = 1;
intMatrix = (int*)malloc(N * N * sizeof(int));
for (i = 0; i < N; ++i)
{
for (j = 0; j < N; ++j)
{
intMatrix[i * N + j] = matrix_build_counter;
matrix_build_counter++;
}
}
printf("The matrix:\n");
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
printf("%d ", intMatrix[i * N + j]);
}
printf("\n");
}
struct my_thread thred_obj_array[CORE];
for (int i = 0; i < CORE; i++) {
thred_obj_array[i].matrix = &intMatrix;
thred_obj_array[i].resArray = result_Array;
thred_obj_array[i].threadId = i;
thred_obj_array[i].strart_raw = (int)((i * N) / CORE);
thred_obj_array[i].end_raw = (int)(((interval * (i + 1)) / N));
thred_obj_array[i].strart_cal = ((interval * i)) % N;
thred_obj_array[i].end_cal = ((interval) * (i + 1));
thred_obj_array[i].counter = (int)floor((interval)*i);
}
for (int i = 0; i < CORE; i++) {
retcode = pthread_create(&th[i], NULL, createArray, &thred_obj_array[i]);
if (retcode != 0) {
printf("Create thread failed with error %d\n", retcode);
}
}
printf("done");
for (int i = 0; i < CORE; i++) {
pthread_join(th[i], NULL);
}
printf("the result array is: ");
for (int i = 0; i < N * N; i++) {
printf("%d ", result_Array[i]);
}
}
void* createArray(struct my_thread* thread) {
int j;
for (int i = thread->strart_raw; i < N; i = i * sizeof(int) * N) {
for (j = thread->strart_cal; j < N; j++) {
printf("I am thread: %d And my value is: %d , (%d,%d)\n", thread->threadId, (*thread->matrix + i * N)[j], i, j);
if (((*thread->matrix + i * N)[j]) % 2 == 0) {
thread->resArray[even] = (*thread->matrix + i * N)[j];
even += 2;
printf("-----%d ---even---\n", even);
}
else {
thread->resArray[odd] = (*thread->matrix + i * N)[j];
odd += 2;
printf("---%d ---odd--\n", odd);
}
(thread->counter)++;
if (thread->counter == thread->end_cal) {
return;
}
}
thread->strart_cal = 0;
}
}

Converting large CSV file into 2D array in C

I have reacently switched to C due to its exceptional computing speeds. I am currently trying to import a very large CSV table (500.000 x 27) into an array, but am facing majour difficulties in trying to assign the values from the imported cell to the respective array cell.
I hope the following code helps in trying to understand my problem. I would be glad for any help!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int row = 520241, col = 27, j = 0, i = 0;
double *arr[row];
for(i = 0; i < row; i++)
arr[i] = (double*)malloc(col*sizeof(double));
FILE *f;
f = fopen("WethData.csv","r");
if( f == NULL) { //control
printf("Unable to open file \n");
exit(1);
}
char line[485]; //if too little memory is allocated weird numbers show up
char *sp; //string pointer
i = 0; //loop to store every row
double res;
while(fgets(line, 485, f) !=NULL) {
sp = strtok(line, ","); arr[i][0] = atof(sp); //<- Here the problem lies as far as I know
for(j = 1; j < col; j++)
sp = strtok(NULL, ","); arr[i][j] = atof(sp); //<-
i++;
if( i > row) {
puts("Row count exceeded"); //controll, if the loop repeats more than there are rows: "record count exceeded"
exit(1); //stops loop
}
};
fclose(f);
return 0;
}
There are a few issues ...
Putting arr on the stack can be problematic:
int row = 520241, col = 27;
double *arr[row];
Here, arr takes up 520241 * 8 bytes which is 2,901,208 bytes. Most archs have a default stack size of 4MB or 8MB. While your allocation is below this, the method doesn't scale to really large .csv files.
Also, pre-allocating for a fixed number of rows can be wasteful. Better to allow the array to grow dynamically in both dimensions.
You don't really have a two dimensional array as C defines them. You have a one dimensional array of pointers to double elements. This is how one has to define a 2D array in languages that don't have 2D arrays (e.g. python).
Note that you're using atof to decode numbers (on the return value of strtok). We can skip the strtok altogether if we use strtod to decode the numbers.
Creating a control struct for a dynamic 2D array can be helpful.
Anyway, here is some refactored code. It is annotated:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define sysfault(_fmt...) \
do { \
printf(_fmt); \
exit(1); \
} while (0)
typedef struct {
int rowmax;
int colmax;
double *data;
} arr_t;
// colcalc -- get number of columns in csv file
int
colcalc(const char *line)
{
int colmax = 1;
// count the number of commas
while (1) {
line = strchr(line,',');
if (line == NULL)
break;
++line;
++colmax;
}
return colmax;
}
// arrload -- read in array from .csv file
arr_t *
arrload(FILE *f)
{
char line[10000];
arr_t *arr;
arr = calloc(1,sizeof(*arr));
if (arr == NULL)
sysfault("calloc failure -- %s\n",strerror(errno));
int rowcap = 0;
double *rowptr;
while (fgets(line, sizeof(line), f) != NULL) {
// dynamically calculate number of columns by probing the first row
if (arr->colmax == 0)
arr->colmax = colcalc(line);
// expand the array size
if (arr->rowmax >= rowcap) {
rowcap += 100;
arr->data = realloc(arr->data,
sizeof(*arr->data) * rowcap * arr->colmax);
if (arr->data == NULL)
sysfault("realloc failure -- %s\n",strerror(errno));
}
// point to the current row we want to fill
rowptr = &arr->data[arr->rowmax * arr->colmax];
char *cp = line;
for (int colidx = 0; colidx < arr->colmax; ++colidx) {
if (*cp == 0)
sysfault("line too short -- rowmax=%d colidx=%d\n",
arr->rowmax,colidx);
// decode the number
rowptr[colidx] = strtod(cp,&cp);
// check the trailing character
switch (*cp) {
case ',': // middle of the line number
++cp;
break;
case '\n': // last number on line
++cp;
break;
case 0: // broken last line (still okay)
break;
default:
sysfault("syntax error -- '%s'\n",cp);
break;
}
}
++arr->rowmax;
}
// trim array to actual size used
rowcap = arr->rowmax;
arr->data = realloc(arr->data,sizeof(*arr->data) * rowcap * arr->colmax);
if (arr->data == NULL)
sysfault("realloc trim failure -- %s\n",strerror(errno));
return arr;
}
void
arrprt(const arr_t *arr)
{
const double *rowptr = arr->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx,
rowptr += arr->colmax) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g",rowptr[colidx]);
printf("\n");
}
}
int
main(void)
{
FILE *f;
f = fopen("WethData.csv", "r");
if (f == NULL)
sysfault("unable to open file -- %s\n",strerror(errno));
arr_t *arr = arrload(f);
fclose(f);
arrprt(arr);
return 0;
}
UPDATE:
After going through your code I still have some uncertainties. For one the use of the arrprt function?
That function just loops through the array and prints the elements. As an example of array element access. More on this below.
For another your use of the "->" opperator?
This is the arrow operator. It is basic C coding. There are other SO questions that detail this. But, I'd look at a good C book (e.g. K&R). Here are some simple examples. They all do the same thing (e.g. print the array element that has index 3):
double data[5];
printf("%g\n",data[3]);
double *dptr = data;
printf("%g\n",dptr[3]);
printf("%g\n",*(dptr + 3));
struct arr {
double data[5];
};
struct arr arr;
printf("%g\n",arr.data[3]);
struct arr *ap = &arr;
printf("%g\n",ap->data[3]);
And lastly how would I access a specific box in the array (e.g. row 300, col 5).
There are a few different ways to do this. I've improved my example code to show the different ways. You can define a few macros with the -D compiler option to get the different ways (e.g. -DUSEMACRO and/or -USEFNC).
You could also use cpp to get the macro output. I've added the USECPP as a convenience. So, to look at macro output (e.g.):
cpp -DUSECPP x.c > xstd.i
cpp -DUSECPP -DUSEMACRO x.c > xmac.i
cpp -DUSECPP -DUSEFNC x.c > xfnc.i
cpp -DUSECPP -DUSEMACRO -DUSEFNC x.c > xmacfnc.i
You can also add -DUSEPRT=n where n is 1-4
Anyway, here is the full code:
#ifndef USECPP
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#endif
// USEMACRO -- select access method
// 0 - index calculation in arrdata function
// 1 - index calculation in ARRDATA macro
//
// USEFNC -- select access method for arrprt2/arrprt3 functions
// 0 - use ARRDATA macro
// 1 - use arrdata
//
// USEPRT -- select arrprt* function to use
// 0-4
#ifndef USEPRT
#define USEPRT 1
#endif
#define sysfault(_fmt...) \
do { \
printf(_fmt); \
exit(1); \
} while (0)
typedef struct {
int rowmax;
int colmax;
double *data;
} arr_t;
// ARRDATA -- access individual array elements
#if USEMACRO
#define ARRDATA(_arr,_rowidx,_colidx) \
(_arr)->data[((_rowidx) * (_arr)->colmax) + (_colidx)]
#else
#define ARRDATA(_arr,_rowidx,_colidx) \
*arrdata(_arr,_rowidx,_colidx)
#endif
// arrdata -- point to given data address
static inline double *
arrdata(const arr_t *arr,int rowidx,int colidx)
{
#if USEMACRO
return &ARRDATA(arr,rowidx,colidx);
#else
return &arr->data[(rowidx * arr->colmax) + colidx];
#endif
}
// ARRDEF -- define 2D array (_advanced_ usage)
#define ARRDEF(_arr,_sym) \
double (*_sym)[(_arr)->colmax] = (__typeof__(_sym)) (_arr)->data
// colcalc -- get number of columns in csv file
#ifndef USECPP
int
colcalc(const char *line)
{
int colmax = 1;
// count the number of commas
while (1) {
line = strchr(line,',');
if (line == NULL)
break;
++line;
++colmax;
}
return colmax;
}
#endif
// arrload -- read in array from .csv file
#ifndef USECPP
arr_t *
arrload(FILE *f)
{
char line[10000];
arr_t *arr;
arr = calloc(1,sizeof(*arr));
if (arr == NULL)
sysfault("calloc failure -- %s\n",strerror(errno));
int rowcap = 0;
double *rowptr;
while (fgets(line, sizeof(line), f) != NULL) {
// dynamically calculate number of columns by probing the first row
if (arr->colmax == 0)
arr->colmax = colcalc(line);
// expand the array size
if (arr->rowmax >= rowcap) {
rowcap += 100;
arr->data = realloc(arr->data,
sizeof(*arr->data) * rowcap * arr->colmax);
if (arr->data == NULL)
sysfault("realloc failure -- %s\n",strerror(errno));
}
// point to the current row we which to fill
#if 0
rowptr = &arr->data[arr->rowmax * arr->colmax];
#else
rowptr = arrdata(arr,arr->rowmax,0);
#endif
char *cp = line;
for (int colidx = 0; colidx < arr->colmax; ++colidx) {
if (*cp == 0)
sysfault("line too short -- rowmax=%d colidx=%d\n",
arr->rowmax,colidx);
// decode the number
rowptr[colidx] = strtod(cp,&cp);
// check the trailing character
switch (*cp) {
case ',': // middle of the line number
++cp;
break;
case '\n': // last number on line
++cp;
break;
case 0: // broken last line (still okay)
break;
default:
sysfault("syntax error -- '%s'\n",cp);
break;
}
}
++arr->rowmax;
}
// trim array to actual size used
rowcap = arr->rowmax;
arr->data = realloc(arr->data,sizeof(*arr->data) * rowcap * arr->colmax);
if (arr->data == NULL)
sysfault("realloc trim failure -- %s\n",strerror(errno));
return arr;
}
#endif
// arrprt1 -- print array (original)
void
arrprt1(const arr_t *arr)
{
const double *rowptr = arr->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx,
rowptr += arr->colmax) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g",rowptr[colidx]);
printf("\n");
}
}
// arrprt2 -- print array (use arrdata function and pointers)
void
arrprt2(const arr_t *arr)
{
const double *rowptr;
const double *rowend;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
// point to start of the row
rowptr = arrdata(arr,rowidx,0);
// point to one past the end of the row (either of these work)
#if USEFNC
rowend = arrdata(arr,rowidx,arr->colmax);
#else
rowend = rowptr + arr->colmax;
#endif
for (; rowptr < rowend; ++rowptr)
printf(" %g",*rowptr);
printf("\n");
}
}
// arrprt3 -- print array (slow, use arrdata/ARRDATA each time)
void
arrprt3(const arr_t *arr)
{
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx) {
#if USEFNC
printf(" %g",*arrdata(arr,rowidx,colidx));
#else
printf(" %g",ARRDATA(arr,rowidx,colidx));
#endif
}
printf("\n");
}
}
// arrprt4 -- print array (slow, use ARRDEF)
void
arrprt4(const arr_t *arr)
{
ARRDEF(arr,data);
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g",data[rowidx][colidx]);
printf("\n");
}
}
#ifndef USECPP
int
main(void)
{
FILE *f;
f = fopen("WethData.csv", "r");
if (f == NULL)
sysfault("unable to open file -- %s\n",strerror(errno));
arr_t *arr = arrload(f);
fclose(f);
switch (USEPRT) {
case 1:
arrprt1(arr);
break;
case 2:
arrprt2(arr);
break;
case 3:
arrprt3(arr);
break;
case 4:
arrprt4(arr);
break;
}
return 0;
}
#endif
UPDATE #2:
Here are the outputs of the modified source, run through cpp from the cpp commands above.
Here is xstd.i:
typedef struct {
int rowmax;
int colmax;
double *data;
} arr_t;
static inline double *
arrdata(const arr_t *arr, int rowidx, int colidx)
{
return &arr->data[(rowidx * arr->colmax) + colidx];
}
void
arrprt1(const arr_t *arr)
{
const double *rowptr = arr->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx, rowptr += arr->colmax) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g", rowptr[colidx]);
printf("\n");
}
}
void
arrprt2(const arr_t *arr)
{
const double *rowptr;
const double *rowend;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
rowptr = arrdata(arr, rowidx, 0);
rowend = rowptr + arr->colmax;
for (; rowptr < rowend; ++rowptr)
printf(" %g", *rowptr);
printf("\n");
}
}
void
arrprt3(const arr_t *arr)
{
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx) {
printf(" %g", *arrdata(arr, rowidx, colidx));
}
printf("\n");
}
}
void
arrprt4(const arr_t *arr)
{
double (*data)[(arr)->colmax] = (__typeof__(data)) (arr)->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g", data[rowidx][colidx]);
printf("\n");
}
}
Here is xmac.i:
typedef struct {
int rowmax;
int colmax;
double *data;
} arr_t;
static inline double *
arrdata(const arr_t *arr, int rowidx, int colidx)
{
return &(arr)->data[((rowidx) * (arr)->colmax) + (colidx)];
}
void
arrprt1(const arr_t *arr)
{
const double *rowptr = arr->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx, rowptr += arr->colmax) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g", rowptr[colidx]);
printf("\n");
}
}
void
arrprt2(const arr_t *arr)
{
const double *rowptr;
const double *rowend;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
rowptr = arrdata(arr, rowidx, 0);
rowend = rowptr + arr->colmax;
for (; rowptr < rowend; ++rowptr)
printf(" %g", *rowptr);
printf("\n");
}
}
void
arrprt3(const arr_t *arr)
{
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx) {
printf(" %g", (arr)->data[((rowidx) * (arr)->colmax) + (colidx)]);
}
printf("\n");
}
}
void
arrprt4(const arr_t *arr)
{
double (*data)[(arr)->colmax] = (__typeof__(data)) (arr)->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g", data[rowidx][colidx]);
printf("\n");
}
}
Here is xfnc.i:
typedef struct {
int rowmax;
int colmax;
double *data;
} arr_t;
static inline double *
arrdata(const arr_t *arr, int rowidx, int colidx)
{
return &arr->data[(rowidx * arr->colmax) + colidx];
}
void
arrprt1(const arr_t *arr)
{
const double *rowptr = arr->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx, rowptr += arr->colmax) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g", rowptr[colidx]);
printf("\n");
}
}
void
arrprt2(const arr_t *arr)
{
const double *rowptr;
const double *rowend;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
rowptr = arrdata(arr, rowidx, 0);
rowend = arrdata(arr, rowidx, arr->colmax);
for (; rowptr < rowend; ++rowptr)
printf(" %g", *rowptr);
printf("\n");
}
}
void
arrprt3(const arr_t *arr)
{
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx) {
printf(" %g", *arrdata(arr, rowidx, colidx));
}
printf("\n");
}
}
void
arrprt4(const arr_t *arr)
{
double (*data)[(arr)->colmax] = (__typeof__(data)) (arr)->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g", data[rowidx][colidx]);
printf("\n");
}
}
Here is xmacfnc.i:
typedef struct {
int rowmax;
int colmax;
double *data;
} arr_t;
static inline double *
arrdata(const arr_t *arr, int rowidx, int colidx)
{
return &(arr)->data[((rowidx) * (arr)->colmax) + (colidx)];
}
void
arrprt1(const arr_t *arr)
{
const double *rowptr = arr->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx, rowptr += arr->colmax) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g", rowptr[colidx]);
printf("\n");
}
}
void
arrprt2(const arr_t *arr)
{
const double *rowptr;
const double *rowend;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
rowptr = arrdata(arr, rowidx, 0);
rowend = arrdata(arr, rowidx, arr->colmax);
for (; rowptr < rowend; ++rowptr)
printf(" %g", *rowptr);
printf("\n");
}
}
void
arrprt3(const arr_t *arr)
{
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx) {
printf(" %g", *arrdata(arr, rowidx, colidx));
}
printf("\n");
}
}
void
arrprt4(const arr_t *arr)
{
double (*data)[(arr)->colmax] = (__typeof__(data)) (arr)->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g", data[rowidx][colidx]);
printf("\n");
}
}

Heap Corruption on resize array by realloc() function in C

I have a problem with increasing C[] array from 6 to 10 I've faced with heap corruption problem by realloc(). I have a following code of Big M metod:
#include <stdio.h>
#include <stdlib.h>
int * mnInit(FILE * );
double * * ReadA(FILE * , int, int);
double * ReadVector(FILE * , int);
int * condtxt(FILE *, int );
void Artif_counter(int* , int *, int);
void reallocationA(double**, int* , int , int);
void increaseA(int*, double**, int, int, int);
void increaseC(double *, int);
int main(int argc, char * argv[]) {
FILE * file1 = fopen("C.txt", "r");
FILE * file4 = fopen("A.txt", "r");
FILE * file5 = fopen("Agetmn.txt", "r");
FILE * file6 = fopen("cond.txt", "r");
int * ptr_mn;
ptr_mn = mnInit(file5);
int n = * (ptr_mn);
int m = * (ptr_mn + 1);
double * * A;
A = ReadA(file4, n, m);
double * C;
C = ReadVector(file1, n);
int * cond;
cond = condtxt(file6, m);
for(int i = 0; i < m; i++){
}
//--------------------------------------------------
int BAcounter = 0;
Artif_counter(cond, &BAcounter, m);
printf("\n Basys and Artifical variable = %d", BAcounter);
reallocationA(A, &n, m, BAcounter);
increaseA(cond, A, n, m, BAcounter);
this function dont't working
increaseC(C, n);
When I trying to print arrays: the A[][] was printed right while C[] array was printed by unknown numbers and after the program Mmetod.exe was closed with problem: A heap has been corrupted (parameters: 0x00007FFCA0C1F6B0).
// count of basys and artif
//------------------------------------------------After Adding a new columns:
printf("\n A[][] ARRAY:\n");
for (int i = 0; i < m; i++) {
printf("%d ", i);
for (int j = 0; j < n; j++) {
printf(" %.3f ", A[i][j]);
}
printf("\n");
}
printf("\n\tVECTOR C[]:\n");
for (int i = 0; i < n; i++) {
printf("%lf ", C[i]);
}
fclose(file1);
fclose(file4);
fclose(file5);
fclose(file6);
free(C);
for (int i = 0; i < m; i++) {
free(A[i]);
}
free(A);
printf("\n\n");
system("pause");
return 0;
}
int * mnInit(FILE * file) {
int c;
int digit = 0;
int column = 0;
int * mnArray = malloc(2 * sizeof( * mnArray));
if (file == NULL) perror("Warning!");
else {
while (!feof(file)) {
c = fgetc(file);
if (c == ';') {
column++;
}
if (c == ' ') {
digit++;
}
}
}
* (mnArray) = (digit / column) + 1; * (mnArray + 1) = column;
return mnArray;
}
double * * ReadA(FILE * file, int n, int m) {
double * * A = malloc(m * sizeof( * A));
for (int i = 0; i < m; i++) {
A[i] = malloc(n * sizeof( * A[i]));
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
//fscanf(file ,"%lf ", &(*(*(A + i) + j)));
fscanf(file, "%lf ", & A[i][j]);
}
fscanf(file, "\n");
}
return A;
}
double * ReadVector(FILE * file, int m) { // ++++
double * Vector = malloc(m * sizeof( * Vector));
for (int i = 0; i < m; i++) {
fscanf(file, "%lf ", Vector + i);
}
return Vector;
}
int* condtxt(FILE * file, int m){
int * condA = malloc(m * sizeof(*condA));
for(int i = 0; i < m; i++){
fscanf(file, "%d", &condA[i]);
}
return condA;
}
void Artif_counter(int * cond, int *k, int m){
for(int i = 0; i < m; i++){
if(cond[i] == -1){
(*k)++;
}
if(cond[i] == 0){
(*k)++;
}
if(cond[i] == 1){
*k = (*k) + 2;
}
}
}
void reallocationA(double** A, int* n, int m, int k){
double * tmp = NULL;
for(int i = 0; i < m; i++){
tmp = realloc(A[i], ((*n) + k)*sizeof(*A[i]));
if(tmp){
A[i] = tmp;
tmp = NULL;
} else{
printf("Error! Memory isn't reallocated'");
tmp = NULL;
}
}
(*n) = (*n) + k;
}
void increaseA(int* cond, double** A, int n, int m, int k){
int presentcol = n-k;
for(int i = 0; i < m; i++){
if(cond[i] == -1){
for(int j = 0; j < m; j++){
if(j == i){
A[j][presentcol] = 1;
} else {
A[j][presentcol] = 0;
}
}
presentcol++;
}
if(cond[i] == 0){
for(int j = 0; j < m; j++){
if(j == i){
A[j][presentcol] = 1;
} else {
A[j][presentcol] = 0;
}
}
presentcol++;
}
if(cond[i] == 1){
for(int j = 0; j < m; j++){
if(j == i){
A[j][presentcol] = 1;
A[j][presentcol + 1] = -1;
} else {
A[j][presentcol] = 0;
A[j][presentcol + 1] = 0;
}
}
presentcol = presentcol + 2;
}
}
}
When I wanted to increase an array in a simple code by this function it've done and I don't understand why(
A GNU debugger rewiev: 0 warning: Critical error detected c0000374
void increaseC(double * C, int n){
double * tmp;
tmp = realloc(C, (n)*sizeof(*C)); // found out that realloc function caused an error
if(!tmp){
printf("Error");
} else{
C = tmp;
}
tmp = NULL;
}

Segmentation Fault:11 Error messages in C Terminal

While compiling in the terminal I keep getting the error Segmentation Fault: 11. The goal is to make dark circles on a picture of a boarder, ect with command. My reasoning that it isn't working if because of my File IO. I did it without the in & out FILE types and changed the two functions that are called in pgmUtility to not call in files and the program ran smoothly. So I'm assuming I need to have help focusing on the issues I have with my file IO.
Command used:
$ ./a.out -c 470 355 100 < balloons.ascii.pgm > TestImages/balloons_c100_4.pgm
It uses main.c program that relates to pgmUtility.c
This is Main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "pgmUtility.h"
#define ROWS 4
#define COLS 100
void usage(void)
{
printf("Usage\n");
printf(" -h Help Dialog\n");
printf(" -e edgeWidth < OldImageFile > NewImageFile\n");
printf(" -c centerRow centerCol radius < OldImageFile > NewImageFile\n");
printf(" -e edgeWidth -c radius centerRow centerCol < OldImageFile > NewImageFile\n");
exit (8);
}
int main(int argc, char * argv[]) {
FILE *fp;
FILE *out;
int i, j;
int flag1 = 0; //-e switch (edge draw)
int flag2 = 0; //-c switch (circle draw)
int numRows, numCols, centerRow, centerCol, radius, edgeWidth;
char originalImage[100], newImageFile[100];
char **header = (char**) malloc (sizeof(char*)*4);
int **pixels;
//command line argument parsing
//turn flag switches on or off
if(argc < 3)
usage();
if(argc > 7)
usage();
for(i = 1; i < argc; i++) {
if(strncmp(argv[i], "-e", 2) == 0) {
//set flag on
//get edge with values)
if(atoi(argv[i+1]) == 0) {
usage();
}
edgeWidth = atoi(argv[i+1]);
if(argv[i+2] != NULL) {
if(atoi(argv[i+2]) != 0) {
usage();
}
}
flag1 = 1;
}
if(strncmp(argv[i], "-c", 2) == 0) {
//set flag on
//get radius and center values
if(atoi(argv[i+1]) == 0) {
usage();
}
centerRow = atoi(argv[i+1]);
centerCol = atoi(argv[i+2]);
radius = atoi(argv[i+3]);
flag2 = 1;
strcpy(originalImage, argv[5]);
strcpy(newImageFile, argv[6]);
fp = fopen(originalImage, "r");
out = fopen(newImageFile, "w");
}
if(strncmp(argv[i], "-h", 2) == 0) {
usage();
}
}
//allocate memory for header array
header = (char **)malloc(ROWS * sizeof(char));
for(i = 0; i < ROWS; i++) {
for(j = 0; j < COLS; j++) {
header[i] = (char *)malloc(COLS * sizeof(char *));
}
}
//read pgm file
pixels = pgmRead(header, &numRows, &numCols, fp);
if(pixels == NULL)
usage();
switch(flag1) {
case 1 :
if(flag2 == 1) {
//execute circle draw and edge draw
pgmDrawCircle(pixels, numRows, numCols, centerRow, centerCol, radius, header);
pgmDrawEdge(pixels, numRows, numCols, edgeWidth, header);
}
else {
//execute only edge draw only
pgmDrawEdge(pixels, numRows, numCols, edgeWidth, header);
}
break;
case 0 :
if(flag2 == 1) {
//execute circle draw
pgmDrawCircle(pixels, numRows, numCols, centerRow, centerCol, radius, header);
}
break;
default :
usage();
break;
}
//write new pgm file
pgmWrite((const char **)header, (const int **)pixels, numRows, numCols, out);
//Garbage Collection
//Fix this
//free(pixels);
//free(header);
for(i = 0; i < numRows; i++) {
int *current= pixels[i];
free(current);
}
for(i = 0; i < ROWS; i++) {
char *current = header[i];
free(current);
}
return 0;
}
This is two functions from pgmUtility.c that I think may be the cause of the issue.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "pgmUtility.h"
#define ROWS 4
#define COLS 100
// Implement or define each function prototypes listed in pgmUtility.h file.
// NOTE: You can NOT change the input, output, and argument type of the functions in pgmUtility.h
// NOTE: You can NOT change the prototype (signature) of any functions listed in pgmUtility.h
int ** pgmRead( char **header, int *numRows, int *numCols, FILE *in ){
int r, c;
int **array;
for(r = 0; r < ROWS; r++) {
fgets(header[r], COLS, stdin);
if(header == NULL)
return NULL;
}
//sscanf parses the numRows and numCols
sscanf(header[ROWS - 2], "%d %d", numCols, numRows);
//read in pixel map
array = (int **)malloc(*numRows * sizeof(int *));
for(r = 0; r < *numRows; r++) {
array[r] = (int *)malloc(*numCols * sizeof(int));
}
for(r = 0; r < *numRows; r++) {
for(c = 0; c < *numCols; c++) {
fscanf(in, "%d", *(array + r) + c );
}
}
fclose(in);
return array;
}
int pgmWrite( const char **header, const int **pixels, int numRows, int numCols, FILE *out ){
//iterate straight through pixels
//setup with a loop to insert a new line every "numCols" and keep printing until "numRows + 1" is reached (as soon as numRows + 1 break loop)
int i, j;
for(i = 0; i < 4; i++){
//printf("%s", *header[i]);
fprintf(out, "%c", *header[i]);
}
//for(i = 0; i < 4; i++)
//fprintf(out, "*I=%d**%s**", i, header[i]);
for(j = 0; j < numRows; j++){
for(i = 0; i < numCols; i++)
fprintf(out, "%d ", pixels[i][j]);
fprintf(out, "\n");
}
fclose(out);
return 0;
}
You're not allocating the header arrays correctly. It should be:
header = malloc(ROWS * sizeof(char*));
for(i = 0; i < ROWS; i++) {
header[i] = malloc(COLS * sizeof(char));
}
You had the wrong types in the two sizeof calls.
You didn't need the inner j loop at all, you were repeatedly assigning to the same header[i].
And for C (but not C++) see: Do I cast the result of malloc?
Also, at the beginning of main() you have an extra allocation that you never use or free:
char **header = (char**) malloc (sizeof(char*)*4);
You should get rid of this.
It's not related to the error, but this is wrong:
if(header == NULL)
return NULL;
You should be testing header[r].
For clarity, I recommend rewriting:
fscanf(in, "%d", *(array + r) + c );
as:
fscanf(in, "%d", &array[r][c]);
It appears (even after correcting the malloc call as correctly suggested), you are allocating header[i] COLS number of times.
header = malloc(ROWS * sizeof(char*));
for(i = 0; i < ROWS; i++) {
for(j = 0; j < COLS; j++) {
header[i] = malloc(COLS * sizeof(char)); // this happens COLS times
}
}
That will leave COLS number of each header[i] allocated. As I read your code, you need only allocate a single char array for each header[i]. To do this, you need to move header[i] = malloc(COLS * sizeof(char)); outside the for(j = 0; j < COLS; j++) loop:
header = malloc(ROWS * sizeof(char*));
for(i = 0; i < ROWS; i++) {
header[i] = malloc(COLS * sizeof(char));
}
You should also validate that header and each header[i] were successfully allocated.

C program store file to jagged array and sort it

I am trying to create C program to read a text file and sort it by ascending order. The example of text file is
2
3; 2, 5, 7
6; 4, 7, 8, 9, 5, 2
with the first line indicated the number of rows, the number after the ";" indicated elements each rows and elements separated by ",".
So my idea is to create a dynamic jagged array with rows as the first number, then point each row to the different array with element. Sort the pointer arrays first then sort elements of each arrays. This is what I have tried so far
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int SortLists();
int main ()
{
int i,j = 0;
char filename[10]; //name of the file
char line[100];
int rows = 3; //I have to initialized this to test my code first
int cols;
int **jaggedArr; //jagged array
jaggerArr = malloc (rows*sizeof(int*)) ;
printf("Enter the file name with .txt : ");
scanf("%s", filename);
FILE *filePtr = fopen(filename, "r");
int num;
if (filePtr != NULL)
{
while (fgets(line, sizeof(line), filePtr) != NULL) //read each line of the text
{
cols = atoi(strtok(line, ";")); //use strtk to break elements
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
jaggedArr[i][j] = atoi(strtok(line, ",")); //parse into the jagged array
}
}
}
fclose(filePtr);
}
}
int SortLists(int list[], int size) //sort method
{
int i,j,temp;
for (i = 0; i < size; ++i)
{
for (j = i + 1; j < size; ++j)
{
if (list[i] > list[j])
{
temp = list[i];
list[i] = list[j];
list[j] = temp;
}
}
}
}
As a beginner in C, I am not familiar with the idea of pointer, which a lot different with C#.
Sorry for my bad English as its not my first language. Thank you so much for helping me.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define S_(x) #x
#define S(x) S_(x)
void SortLists(int list[], int size);
int main(void){
char filename[FILENAME_MAX+1];
char line[100];
int rows, cols;
printf("Enter the file name with .txt : ");
scanf("%" S(FILENAME_MAX) "[^\n]%*c", filename);
FILE *filePtr = fopen(filename, "r");
if(!filePtr)
return EXIT_FAILURE;
fscanf(filePtr, "%d ", &rows);
int **jaggedArr;
jaggedArr = malloc (rows * sizeof(int*));
int *sizeArr = malloc(rows * sizeof(int));
int r = 0, c;
while (fgets(line, sizeof(line), filePtr) != NULL){
sizeArr[r] = cols = atoi(strtok(line, ";"));
jaggedArr[r] = malloc(cols * sizeof(int));
for (c = 0; c < cols; ++c){
jaggedArr[r][c] = atoi(strtok(NULL, ","));
}
SortLists(jaggedArr[r++], cols);
}
fclose(filePtr);
//check print and deallocation
for(r = 0;r < rows; ++r){
for(c = 0; c < sizeArr[r]; ++c)
printf("%d ", jaggedArr[r][c]);
printf("\n");
free(jaggedArr[r]);
}
free(jaggedArr);
free(sizeArr);
return 0;
}
void SortLists(int list[], int size){
int i,j,temp;
for (i = 0; i < size-1; ++i){
for (j = i + 1; j < size; ++j){
if (list[i] > list[j]){
temp = list[i];
list[i] = list[j];
list[j] = temp;
}
}
}
}
for extra question.
#include <stdio.h>
void SortLists(int list[], int size);
void SortRows(int *jaggedArr[], int size, int *rowSize);
int main(void){
int row1[] = {4,7,8,9,5,2};
int row2[] = {2,5,7};
int *jaggedArr[] = { row1, row2};
int rows = 2;
int sizeArr[] = {6,3};
int i, r, c;
for(i=0;i<rows;++i)
SortLists(jaggedArr[i], sizeArr[i]);
for(r = 0;r < rows; ++r){
for(c = 0; c < sizeArr[r]; ++c)
printf("%d ", jaggedArr[r][c]);
printf("\n");
}
printf("\n");
SortRows(jaggedArr, rows, sizeArr);
for(r = 0;r < rows; ++r){
for(c = 0; c < sizeArr[r]; ++c)
printf("%d ", jaggedArr[r][c]);
printf("\n");
}
return 0;
}
void SortLists(int list[], int size){
int i,j,temp;
for (i = 0; i < size-1; ++i){
for (j = i + 1; j < size; ++j){
if (list[i] > list[j]){
temp = list[i];
list[i] = list[j];
list[j] = temp;
}
}
}
}
void SortRows(int *jaggedArr[], int size, int *rowSize){
int i,j,temp,*tempp;
for (i = 0; i < size-1; ++i){
for (j = i + 1; j < size; ++j){
if (rowSize[i] > rowSize[j]){
//swap in pairs
temp = rowSize[i];
rowSize[i] = rowSize[j];
rowSize[j] = temp;
tempp = jaggedArr[i];
jaggedArr[i] = jaggedArr[j];
jaggedArr[j] = tempp;
}
}
}
}
#include <stdio.h>
void SortLists(int list[], int size);
void SortRows(int *jaggedArr[], int size);
int main(void){
int row1[] = {6, 4,7,8,9,5,2};//The first element represents the number of elements.
int row2[] = {3, 2,5,7};
int *jaggedArr[] = { row1, row2};
int rows = 2;
//int sizeArr[] = {6,3};//Not required
int i, r, c;
for(i=0;i<rows;++i)
SortLists(jaggedArr[i]+1, jaggedArr[i][0]);
SortRows(jaggedArr, rows);
for(r = 0;r < rows; ++r){
for(c = 1; c <= jaggedArr[r][0]; ++c)
printf("%d ", jaggedArr[r][c]);
printf("\n");
}
return 0;
}
void SortLists(int list[], int size){
int i,j,temp;
for (i = 0; i < size-1; ++i){
for (j = i + 1; j < size; ++j){
if (list[i] > list[j]){
temp = list[i];
list[i] = list[j];
list[j] = temp;
}
}
}
}
void SortRows(int *jaggedArr[], int size){
int i,j,*tempp;
for (i = 0; i < size-1; ++i){
for (j = i + 1; j < size; ++j){
if (jaggedArr[i][0] > jaggedArr[j][0]){
tempp = jaggedArr[i];
jaggedArr[i] = jaggedArr[j];
jaggedArr[j] = tempp;
}
}
}
}

Resources