The objective is to sort a i x j matrix of words in a 1D matrix of words in alphabetical order(every row in the original matrix is already sorted). The matrix is read from a file and stored in a three star pointer ***index, it is dynamically allocated like this (in a separate function):
char ***index;
index= (char ***) malloc(*row * sizeof(char **));
...
for (int i = 0; i < *row; ++i){
index[i]= (char **) malloc(*col * sizeof(char **));
for (int j=0; j<*col; j++) {
fscanf(fp,"%s",tmp);
index[i][j]=strdup(tmp);
}
}
I then pass the index to my sorting function: char **sort_data(char ***index, int row,int col).
It is nothing special just a merge sort algorithm that:
checks the first elements of each row of ***index
moves the "smallest" word to **sortedIndex
substitutes the sorted word with a new one from the same row.
char **sort_data(char ***index, int row,int col){
int i,posInIndex,smallestCharPos,*tracker;
char **sortedindex,*buffer;
sortedindex=(char **) malloc((row*col)*sizeof(char*));
tracker= (int*) calloc(row, sizeof(int));
posInIndex=0;
while (posInIndex<row*col) {
smallestCharPos=-1;
for (i=0; i<row; i++) {
if ((smallestCharPos==-1)||(strcmp(index[i][tracker[i]], buffer)<0)) {
smallestCharPos=i;
buffer=index[i][tracker[i]];
}
}
sortedindex[posInIndex]=index[smallestCharPos][tracker[smallestCharPos]];
posInIndex++;
tracker[smallestCharPos]++;
}
free(tracker);
return (sortedindex);
}
After some iterations(depends on matrix size) of the for loop, I get a EXC_BAD_ACCESS (code=1, address=0x14000001f5) at the if statement which leads me to believe it's an issue with my memory allocation but i cannot spot the mistake.
An example of a matrix to sort would be (this particular matrix gives me trouble after 10 iterations of the for loop):
milano torino venezia
bari genova taranto
firenze napoli roma
bologna cagliari palermo
The problem is that you don't track when you are done with a row. Even if you have already used all words of a row, you just continue looking at the row as if there are more words to handle.
You need to add some code to skip the rows that are fully handled already.
Try changing this:
if ((smallestCharPos==-1)||(strcmp(index[i][tracker[i]], buffer)<0)) {
...
}
to
if (tracker[i] < col)
{
if ((smallestCharPos==-1)||(strcmp(index[i][tracker[i]], buffer)<0)) {
...
}
}
Related
So, I am trying to make a function that transpose some matrix and save it in another matrix.
In the main function I create a matrix called AB (is a 3D matrix) that is size AB[100][100][2] (in this test) and the terms of the type AB[i][j][0] represents the matrix A and AB[i][j][1] represents the matrix B.
The error is occurring in the big test (AB[100][100][2]) when I run the first loop in the function, that look like that:
void transpose(int size, int matrix[][MAX][2], int index, int index_save){
int auxiliar_matrix[MAX][MAX];
for (int i = 0; i < size; i++){
for (int j = 0; j < size; j++){
auxiliar_matrix[i][j] = matrix[j][i][index];
}
save(matrix, index_save, auxiliar_matrix, size) /*this just save the matrix, isnt wrong*/
}
The function just do not work for the big case and the error is in the first 3 lines. Any idea?
I'm trying to dynamically allocate a 2D INT array in C in order to return a transposed matrix, I've done several research on the topic, and it should work this way, however I keep struggling with the program.
I tried it many different ways now (offset, pointer arithmetic), I didn't find a fix for the problem.
I'm either getting trash values or the program crashes (no seg fault, error code crash).
I'm also loooking for a proper version to allocate the memory, I've seen several versions on stackoverflow, the one I would preferrably like to use, is allocating pointer space and the integer space afterwards (the one I'm trying to use in the example below).
// Convert a matrix to it's transposed version. Returns a two dimensional array (pointer)
int **getTransposedMatrix(int *matrix, int dimension_h, int dimension_w){
int **transposedMatrix = (int **) malloc(dimension_w * sizeof(int*));
for(int row=0; row<dimension_w; row++){
transposedMatrix[row] = (int*) malloc(dimension_w * sizeof(int));
}
for(int row=0; row<dimension_h; row++){
for(int column=0; column<dimension_w; column++){
transposedMatrix[column][row] = *(matrix + row * dimension_w + column);
printf("%d ", transposedMatrix + (row * dimension_w + column));
}
printf("\n");
}
return **transposedMatrix;
}
I appreciate any help :)
I would not bother with a "2D array" such as the one you are setting up, where you're allocating the rows separately. Below is my version which uses a single array and calculates offsets into it accordingly.
int *getTransposedMatrix(int *matrix, int dimension_w, int dimension_h)
{
int *transposed = malloc(dimension_w * dimension_h * sizeof(int));
for (int row = 0; row < dimension_h; row++) {
for (int col = 0; col < dimension_w; col++) {
transposed[col * dimension_h + row] = matrix[row * dimension_w + col];
}
}
return transposed;
}
ideone with some test examples
for(int i=0; i < n; ++i){
//Find the leading element in a+M*i
if(!find_leading_element((a+M*i),n-i,m,&rowLead,&columnLead)){
return;
}
//Get the dividable from a[rowLEad][columnLead]
divide = (double)1/a[rowLead][columnLead];
printf("The divide from current matrix is %d\n\n",divide);
//Swap the current row = i with rowLead in matrix a+M*i
swap_rows((a+M*i),n-i,m,i,rowLead);
}
I am working on a small school project for reducing matrices but having some troubles passing the 2D array with an offset.
I need the find_leading_element to get a 2D array and return via the pointers the row and column of the leading element in that matrix.
Therefore find_leading_element returns the row and col relative to the matrix it got, and it is okay I will handle it later on. Now the issue is with passing the 2D array with a row offset.
So with each iteration I will pass the matrix but with one row less. Since I can't change the declaration for find_leading_element, I need to pass the function with double a[][M], does it mean it is passed by value?
bool find_leading_element(double a[][M], int n, int m, int * row, int * column) {
printf("In Find Leader got the matrix\n");
print_matrix((double (*)[M])a,n,m);
for(int i=0; i < m; ++i){
for(int j=0; j < n; ++j){
if(*(&a[0][0]+j*M+i) != 0){
*row = j;
*column = i;
return true;
}
}
}
return false;
}
double a[N][M];
printf("Enter matrix:\n");
if (!read_matrix((double (*)[M]) a, n, m)) {
printf("Invalid matrix!\n");
return ERROR;
}
What is the best way to do it? The way I do it here it only receives on the second iteration one row.
Beware pointer arithmetics is not raw addresses arithmetics.
As a is a 2D array declared as double a[N][M]; it will decay to a pointer to a row. That means that the address of the i-th row is a+i and not a+M*i.
The latter is used when you simulate a 2D array with a 1D one: int aa[N*M];. Here aa will decay to an int pointer and the beginning of the i-th row would be at aa+M*i.
The call should be:
//Find the leading element in a+M*i
if(!find_leading_element((a+i),n-i,m,&rowLead,&columnLead)){
return;
}
I'm trying to populate a bidimensional array in the reverse way but I'm getting always the same error: core dump.
When I say reverse way I mean, usually we do something like
for(int i=0; i<MaxColumns; i++)
for(int b=0; i<MaxRows; b++)
array[i][b] = random value;
What I'm trying to do is for each row, I want to populate that single row on every column and then pass to the next row and do the same. At this time I'm declaring dynamically a new row for each column.
This is what I was trying:
int i = atoi(argv[1]);
int **array = (int**)malloc(i * sizeof(int*));
for (lines =0; lines <MAXLINES; lines ++) {
for (colunms =0; colunms <i; colunms ++) {
array[colunms] = (int*)malloc(1 * sizeof(int));
v=colunms+lines;
array[colunms][lines]=v;
}
}
And the error goes on:
array[colunms][lines]=v;
------ LAST UPDATE TO PROBLEM ----
Already updated and although I tried this code
for (lines =0; lines <MAXLINES; lines ++) {
array[colunms] = (int*)malloc(colunms * sizeof(int));
for (colunms =0; colunms <i; colunms ++) {
v=colunms+lines;
array[colunms][lines]=v;
}
}
I keep getting core dumped on:
array[colunms][lines]=v;
Thats simple enough. Instead of:
for(int i=0; i<MaxColumns; i++)
for(int b=0; i<MaxRows; b++)
array[i][b]=random value;
Use:
for(int b=0; i<MaxRows; b++)
for(int i=0; i<MaxColumns; i++)
array[i][b]=random value;
Your error though is in:
array[colunms] = (int*)malloc(1 * sizeof(int));
You are allocating space for 1 element of int where you should be allocating for colunms * sizeof(int). You should also do that outside the inner loop, like this:
int **array = (int**)malloc(MAXLINES * sizeof(int*));
for (lines =0; lines <MAXLINES; lines ++) {
array[lines] = (int*)malloc(i * sizeof(int));
for (colunms =0; colunms <i; colunms ++) {
v=colunms+lines;
array[lines][colunms] = v;
}
}
Also, even though this code should work, it can be a problem in the future to assume this as array[colunms][lines] where it should be array[lines][colunms].
Why? Because with array[lines][colunms] each array[line] represents a complete row with all its columns, which is a lot more practical for most cases.
In this form you will be able to declare functions to handle single records instead of handing it the entire "table".
I have searched many explanations, but I think I could not figure out how I can do this situation. I want to do something like that:
Using master processor, I am creating a dynamic 2D array. Then I want to;
1- send this array to other processors. And each processor prints this 2D array
2- send part of this array to others. And each processor prints their part to the screen.
For example; I have 2D array 11*11 and 4 processors. rank 0 is master. Others are slaves. For the first situation, I want to send all array to rank 1, rank 2, and rank 3. And for the second situation, I want to share rows to slaves. 11/3 = 3. Therefore rank 1 takes 3 rows, rank 2 takes 3 rows, and rank 3 takes 5 rows.
Here is my code:
int processorID;
int numberOfProcessors;
int main(int argc, char* argv[]){
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD ,&numberOfProcessors);
MPI_Comm_rank(MPI_COMM_WORLD ,&processorID);
double **array;
if(MASTER){
array = (double**) malloc(11*sizeof(double *));
for(i=0; i<11; i++){
array[i] = (double *) malloc(11*sizeof(double));
}
for(i=0; i<11; i++){
for(j=0; j<11; j++){
array[i][j] = i*j;
}
}
}
MPI_Bcast(array, 11*11, MPI_DOUBLE, 0, MPI_COMM_WORLD);
if(SLAVE){
for(i=0; i<11; i++){
for(j=0; j<11; j++){
printf("%f ", array[i][j]);
}
}
}
MPI_Finalize();
return 0;
}
according to these link ; MPI_Bcast a dynamic 2d array ; I need to create my array as;
if (MASTER){
array = (double**) malloc(121*sizeof(double))
for(i=0; i<11; i++){
for(j=0; j<11; j++){
array[i][j] = i*j; // this is not working.
}
}
}
but if I do this, I cannot initialize each member in the array. Inner for loops are not working. I could not find any way to solve it.
And for my second question, I followed this link sending blocks of 2D array in C using MPI . I think I need to change the inside of if(SLAVE). I should create 2D subArrays for each slave processor. And I need to use MPI_Scatterv. But I could not understand completely.
int main() {
...
...
MPI_Scatterv() // what must be here?
if(SLAVE){
if(processorID = numberOfProcessor-1){
subArray = (double**) malloc(5*sizeof(double *)); // beacuse number of row for last processor is 5
for(i=0; i<11; i++){
array[i] = (double *) malloc(11*sizeof(double));
}
}
else {
subArray = (double**) malloc(3*sizeof(double *));
for(i=0; i<11; i++){
array[i] = (double *) malloc(11*sizeof(double));
}
}
}
}
C does not really have multidimensional arrays. I would recommend storing your values in a regular 1D buffer, and then calculating correct indices from 1D values. Like so:
double* data = (double*)malloc(sizeof(double)*11*11);
// Now, to access data[i][j], simply do:
data[j + i*11] = ...; // this "maps" 2D indices into 1D
This will spare you all the trouble with the hierarchical malloc-ing, and it can easily be passed to the MPI APIs.
You can't use an array of pointers (what you are incorrectly calling a "2D array"), because each row pointer is not portable to another node's address space.
The code you quoted for creating a 2D array in a linear memory allocation is perfectly correct, all you need to do is index that memory in row major order, so that the loops become:
double* array = (double*) malloc(121*sizeof(double));
if (MASTER){
for(i=0; i<11; i++){
for(j=0; j<11; j++){
array[j+i*11] = i*j; // row major indexing here
}
}
}
/* Scatter code follows */
You can safely scatter this sort of array to multiple nodes.