I am trying to define a function to return a square matrix (NxN) in C language:
#define true 1
#define false 0
typedef char bool;
typedef bool** Matrix;
Matrix matrix_alloc(int size)
{
Matrix matrix = (bool **) malloc(sizeof(bool) * size);
int i;
for (i = 0; i < size; i++) {
matrix[i] = (bool *) calloc(size, sizeof(bool));
}
return matrix;
}
void matrix_print(Matrix matrix, int size)
{
int i, j;
for (i = 0; i < size; i++) {
for (j = 0; j < size; j++) {
printf("%i ", matrix[i][j]);
}
printf("\n");
}
}
However, it seems calloc() isn't initializing the "cells" with zero as expected. I was told calloc was safe for initialization, so I believe there is hole in my logics. Here is the output when running the two functions (e.g. to create a 9x9 matrix):
48 77 104 0 72 77 104 0 96
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
Wrong size in allocation: matrix is a pointer to bool *, not to bool.
Avoid mistakes, size to the de-referenced pointer, not the type.
The cast is not needed in C, and should be omitted.
// too small
// Matrix matrix = (bool **) malloc(sizeof(bool) * size);
Matrix matrix = malloc(sizeof *matrix * size);
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv, char **envp) {
int rows=3, cols=2, i, j;
char *myName = (char *) calloc(rows*cols, sizeof(char));
char chTemp = 'a';
//Kh
//al
//id
*(myName)='K'; *(myName+1)='h'; *(myName+2)='a'; *(myName+3)='l'; *(myName+4)='i'; *(myName+5)='d';
for(i=0; i<rows; i++){
for(j=0; j<cols; j++){
chTemp = *(myName+i*cols+j);
printf("%c", chTemp);
}
printf("\n");
}
return (EXIT_SUCCESS);
}
Related
I'm trying to save a 2-D array of integers to a binary file. The problem is that only the first row of the 2-D array is saved. Below I have attached the outputs from which you will better understand the problem. Thanks in advance for the help.
#include <stdio.h>
#include <stdlib.h>
#define N_MAX 100
// Declaration of functions
int readMatrix(FILE *fp, int matrix[N_MAX][N_MAX]);
void printMatrix(int matrix[N_MAX][N_MAX], int size);
void switchMax(int matrix[N_MAX][N_MAX], int size);
int avg(int matrix[N_MAX][N_MAX], int size);
int sumDown(int matrix[N_MAX][N_MAX], int size);
int sumUp(int matrix[N_MAX][N_MAX], int size);
void sortMainDiagonal(int matrix[N_MAX][N_MAX], int size);
int main()
{
int size, matrix[N_MAX][N_MAX], test[N_MAX][N_MAX];
FILE *fp;
fp = fopen("input.txt", "r");
if (fp != NULL)
{
size = readMatrix(fp, matrix);
fclose(fp);
switchMax(matrix, size);
avg(matrix, size);
sortMainDiagonal(matrix, size);
printf("\nOriginal matrix: \n");
printMatrix(matrix, size);
// SAVE ON BINARY FILE
fp = fopen("output.bin", "w");
if (fp != NULL)
{
fwrite(matrix, sizeof(int), size*size, fp);
fclose(fp);
} else {
printf("Error #e2");
}
// READ FROM BINARY FILE
fp = fopen("output.bin", "r");
if (fp != NULL)
{
fread(test, sizeof(int), size*size, fp);
fclose(fp);
printf("\nMatrix from file: \n");
printMatrix(test, size);
} else {
printf("Error #e3");
}
} else {
printf("Errore #e1");
}
}
// Definition of functions
int readMatrix(FILE *fp, int matrix[N_MAX][N_MAX])
{
int size = 0;
fscanf(fp, "%d", &size);
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
fscanf(fp, "%d", &matrix[i][j]);
return size;
}
void printMatrix(int matrix[N_MAX][N_MAX], int size)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}
void switchMax(int matrix[N_MAX][N_MAX], int size)
{
int max = 0, row = 0;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
if (matrix[j][i] > max)
{
max = matrix[j][i];
row = j;
}
}
matrix[row][i] = matrix[i][i];
matrix[i][i] = max;
max = 0;
}
}
int avg(int matrix[N_MAX][N_MAX], int size)
{
int avg;
avg = (sumDown(matrix, size) + sumUp(matrix, size)) / 2;
matrix[size-1][size-1] = avg;
return avg;
}
int sumDown(int matrix[N_MAX][N_MAX], int size)
{
int sum = 0;
for (int i = 1; i < size; i++)
for (int j = 0; j < i; j++)
sum += matrix[i][j];
return sum;
}
int sumUp(int matrix[N_MAX][N_MAX], int size)
{
int sum = 0;
for (int i = 0; i < size-1; i++)
for (int j = i+1; j < size; j++)
sum += matrix[i][j];
return sum;
}
void sortMainDiagonal(int matrix[N_MAX][N_MAX], int size)
{
int temp;
for (int i = 0; i < size-1; i++)
{
for (int j = 0; j < (size-1-i); j++)
{
if (matrix[j][j] > matrix[j+1][j+1])
{
temp = matrix[j][j];
matrix[j][j] = matrix[j+1][j+1];
matrix[j+1][j+1] = temp;
}
}
}
}
Screenshot of outputs from 'printMatrix' function:
click
File 'input.txt':
4
5 6 1 8
1 20 3 4
9 0 11 12
13 4 15 1
You don't show the value for N_MAX, but your image (which should be text in the question!) shows a 4x4 matrix. In future, please create an MCVE (Minimal, Complete, Verifiable Example).
However, let's suppose N_MAX is 16 or more (but that dim is 4). Then your code to write the matrix is writing a lot of zeroes. And skipping the other data.
Your matrix looks like:
13 6 1 8 0 0 0 0 0 0 0 0 0 0 0 0
1 15 3 4 0 0 0 0 0 0 0 0 0 0 0 0
9 0 20 1 0 0 0 0 0 0 0 0 0 0 0 0
5 4 11 26 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
And the fwrite() writes the first 16 integer values reading across. As you demonstrated, 12 of those are zeros.
To write a sub-array, you'll have to write the dim entries of each of the matrix's first dim rows separately.
for (size_t i = 0; i < dim; i++)
{
if (fwrite(matrix[i], sizeof(int), dim, fp) != dim)
err_syserr("short write on row %zu of matrix\n", i);
}
And similarly with the fread() code.
The function `err_syserr()` formats and prints the given error message and the system error message associated with `errno` before exiting with a non-zero (failure) status. A comprehensive suite of error reporting functions is available in my [SOQ](https://github.com/jleffler/soq) (Stack Overflow Questions) repository on GitHub as files `stderr.c` and `stderr.h` in the [src/libsoq](https://github.com/jleffler/soq/tree/master/src/libsoq) sub-directory.*\
So, for example I have 2 Arrays, one is
0 -1 1 0 1
0 -1 0 0 0
0 1 1 -1 0
0 0 0 -1 0
0 -1 0 1 0
the second is full of 0's.
After I meet the condition a[i][j] == -1 && a[i][k] == 1, where k=j+1, I need to copy the whole row and put it into the second array, so the result should be:
0 -1 1 0 1
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 -1 0 1 0
I've already alloced the memory for both arrays, and here's the part of the code that I've tried but it doesnt work, it copies the whole array
void copy_row(int **a, int **b, int m){
for(int i=0; i<m; i++){
b[i]=a[i];
}
}
int main(){
...
for(int i=0 ; i<n ; i++){
for(int j=0 ; j<m ; j++){
for(int k=j+1; k<m ; k++){
if (a[i][j]==-1 && a[i][k]==1){
copy_row(a,b,n);
}
}
}
}
If you want to copy a row, you would need to pass the index of the current row to copy_row, plus the number of columns.
The call from main could be
// Notice that we pass index i and not n
copy_row(m, a, b, i);
The copy_row could be:
void copy_row(int numOfColumns, int a[][numOfColumns], int b[][numOfColumns], int rowIndex) {
for (int ii = 0, ii < numOfColumns, ++ii) {
b[rowIndex][ii] = a[rowIndex][ii];
}
}
You could add a break after the call to copy_row in the if statement. Once a row is copied, there is no need to keep checking the rest of the columns for -1.
E.g., you might reduce the checks made by using
for(int j = 0 ; j < m ; ++j) {
if (a[i][j] == -1) {
for(int k = j + 1; k < m ; ++k) {
if (a[i][k] == 1) {
copy_row(m, a, b, i);
break;
}
}
break;
}
}
I've been trying to write a program that displays the sparse matrix and also finds the transpose of the matrix, but while transposing only the elements of the first row of the original matrix are getting transposed and all the other elements from other rows are getting ignored. I need some help.
Here's the code I've written
#include <stdio.h>
#include <stdlib.h>
struct Element{
int i;
int j;
int x;
};
struct Sparse{
int m;
int n;
int num;
struct Element *ele;
};
void create(struct Sparse *s){
printf("Enter the dimensions ");
scanf("%d%d",&s->m, &s->n );
printf("Number of non-zero elements");
scanf("%d",&s->num);
s-> ele= (struct Element*) malloc(s->num * sizeof(struct Element));
printf("Enter all non-zero elements\n");
for (int i = 0; i< s->num; i++)
{
scanf("%d%d%d",&s->ele[i].i,&s->ele[i].j,&s->ele[i].x);
}
}
void display(struct Sparse s){
int i,j,k=0;
for (i = 0; i < s.m; i++)
{
for (j = 0; j < s.n; j++)
{
if(i==s.ele[k].i && j== s.ele[k].j)
printf("%d ",s.ele[k++].x);
else
printf("0 ");
}
printf(" \n");
}
}
void createTranspose(struct Sparse *t, struct Sparse s){
t->m = s.n;
t->n = s.m;
t->num = s.num;
t-> ele= (struct Element*) malloc(t->num * sizeof(struct Element));
printf("Enter all non-zero elements\n");
for (int i = 0; i< t->num; i++)
{
t->ele[i].i= s.ele[i].j;
t->ele[i].j= s.ele[i].i;
t->ele[i].x= s.ele[i].x;
}
}
int main(){
struct Sparse s, t;
create(&s);
display(s);
createTranspose(&t,s);
printf("Transpose of the matrix is \n");
display(t);
return 0;
}
Output
Enter the dimensions 6 6
Number of non-zero elements6
Enter all non-zero elements
0 0 1
0 2 2
0 4 3
2 3 4
4 1 5
5 5 6
1 0 2 0 3 0
0 0 0 0 0 0
0 0 0 4 0 0
0 0 0 0 0 0
0 5 0 0 0 0
0 0 0 0 0 6
Enter all non-zero elements
Transpose of the matrix is
1 0 0 0 0 0
0 0 0 0 0 0
2 0 0 0 0 0
0 0 0 0 0 0
3 0 0 0 0 0
0 0 0 0 0 0
Some help to get a proper output would be highly appreciated.
Your display function assumes that the sparse elements are in row-major order, but after simple transpose they're now in column-major order.
Either you need to re-sort the sparse elements that they retain the row-major ordering, or you need an inner loop in your display routine:
for (k = 0; k < s.num; k++) {
if (i == s.ele[k].i && j == s.ele[k].j) {
printf("%d ", s.ele[k].x);
break;
}
}
// not found among the sparse elements
if (k == s.num) {
printf("0 ");
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
I am implementing a sparse linear equation solver such as Lx = b. For this, I initialize a reference x vector named x_ref and generate an RHS vector b accordingly. However, both pointers seem empty somehow.
VALUE_TYPE is a macro and set to double
VALUE_TYPE *x_ref = (VALUE_TYPE *)malloc(sizeof(VALUE_TYPE) * n);
VALUE_TYPE *b = (VALUE_TYPE *)malloc(sizeof(VALUE_TYPE) * n);
for ( int i = 0; i < n; i++)
x_ref[i] = rand() % 10 + 1;
for (int i = 0; i < n; i++)
{
for (int j = cscColPtrTR[i]; j < cscColPtrTR[i+1]; j++)
{
int rowid = cscRowIdxTR[j]; //printf("rowid = %i\n", rowid);
b[rowid] += cscValTR[j] * x_ref[i];
}
}
After I print them as;
for(int i = 0; i < n; i++)
{
printf("%d\t\t%d\n", x_ref[i], b[i]);
}
The results are:
4226166 1977719296
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
I cannot understand what is wrong with it.
Rather use objects in the sizeof instead of types VALUE_TYPE *x_ref = (VALUE_TYPE *)malloc(sizeof(*x_ref) * n);
Use the correct printf formats. %d is used to output integers, not doubles.
#define VALUE_TYPE double
int main(void)
{
size_t n = 20;
VALUE_TYPE *x_ref = malloc(sizeof(*x_ref) * n);
VALUE_TYPE *b = malloc(sizeof(*b) * n);
for ( int i = 0; i < n; i++)
x_ref[i] = rand() % 10 + 1;
for ( int i = 0; i < n; i++)
printf("%d - %f\n", i, x_ref[i]);
}
https://godbolt.org/z/RKjZi8
First of all, you don't need to cast those mallocs, since it returns a void pointer, so the cast is implicit. I'm not sure why you are getting those zeros, but there are some remarks:
You need to seed the pseudo-random number generator:
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
// Use current time as seed for random generator
srand(time(0));
for(int i = 0; i<4; i++)
printf(" %d ", rand());
return 0;
}
Initialize your b vector with a memset, because they are (as far as I can tell) accumulating values, so they should start from 0. As it is now, your vector may contain only gibberish.
I could not run your code because of the undefined references, but consider correcting those points :)
My problem is part of a larger communication algorithm I'm trying to implement. The point is to generate packets from messages, to send over the network. You fetch a batch of messages (decimal values), and form the packets from the bits from each message that are in the same column. The following figure illustrates this.
Packet formation from messages
My problem is the 'transpose' operation. How I'm trying to approach this is by transposing the bits of this 1D decimal value array of messages. Maximum decimal value of each message is 255, so 8 bits in length each.
I want to convert all decimal values to bits in a 2D array, where each column is a bit from the decimal value in that row. Finally I want to convert this 2D bit array to a 1D array with decimal values again.
Example:
Input is a decimal 1D array
decimal[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
Convert this 1D array to a 2D array representing the bits
bits[16][8] = { 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 0 1 0
0 0 0 0 0 0 1 1
....
0 0 0 0 1 1 1 1 };
Transpose this bit array
bits2[8][16] = {
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 };
Convert it back to a decimal value 1D array
result[8] = { 0, 0, 0, 0, 255, 3855, 13107, 21845}
The code I have so far:
#define n 8 // COLUMNS
#define m 16 // ROWS
int data[m];
int result[n];
int i,j;
int counter = 0;
memset(data, 0, sizeof(data));
memset(result, 0, sizeof(result));
for ( i = 0; i < m; ++i) {
data[i] = counter;
++counter;
}
int a[m][n], b[n][m], x;
// Convert decimal array to 2D bit array
for(i=0; i<m; i++)
{
x = data[i];
for(j=0; j<n; j++)
{
a[i][j] = (x & 0x8000) >> 8;
x <<= 1;
}
}
// Transpose bit array
for(i=0; i<m; i++)
{
for(j=0; j<n; j++)
{
b[j][i] = a[i][j];
}
}
// Convert back to decimal
for(i=0; i<n; i++)
{
for(j=0; j<m; j++)
{
if (b[i][j] == 1) result[i] = result[i] * 2 + 1;
else if (b[i][j] == 0) result[i] *= 2;
}
}
I hope my explanation is clear! If not, I'll gladly explain some more. I've searched endlessly for ways to do this but I'm still not getting up with a solid solution.
PS: Apologies for the bad code formatting of the arrays, didn't find a proper way to visualize it without linking an image.
This should provide the desired output.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define n 8 // COLUMNS
#define m 16 // ROWS
int main(void)
{
int data[m];
int result[n];
int i, j;
int counter = 0;
memset(data, 0, sizeof(data));
memset(result, 0, sizeof(result));
for (i = 0; i < m; ++i) // print initial data
{
data[i] = counter;
printf("%d ", data[i]);
++counter;
}
putchar('\n');
char a[m][n], b[n][m];
int x;
// Convert decimal array to 2D bit array
for (i = 0; i < m; i++)
{
x = data[i];
for (j = n - 1; j >= 0; j--)
{
a[i][j] = x & 1;
x >>= 1;
}
}
// Transpose bit array
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
b[j][i] = a[i][j];
}
}
// Convert back to decimal
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
if (b[i][j] == 1)
result[i] = result[i] * 2 + 1;
else if (b[i][j] == 0)
result[i] *= 2;
}
}
for (i = 0; i < n; ++i) // print result
{
printf("%d ", result[i]);
}
putchar('\n');
return 0;
}
What you were doing wrong was the conversion to the 2d bit array , it was all filled with 0's.
You were doing (x&0x8000) >> 8;
0x8000 = 1000 0000 0000 0000 (grouped in nibbles to see clearly)
so (x&0x8000) will always be 0 considering that x will in your case take values <=255 .
I also changed the int arrays which were using way too much space than needed to char arrays.