I am trying to find the sum of the diagonals for the following array seen below, but whenever I call the function diagsfunc and run the program it does not give the answer,
I made an if statement to make sure the array is a square matrix, and if it is, it proceeds to call the function diagsfunc where I find the sum of the diagonal elements however whenever I run it does not print the sum.
Below is the function, main and the array. all the other functions work fine except for the diagonal one. and in case you are wondering the file contains the following numbers, where the first 2 numbers are just the rows and columns and the last 2 numbers are specific rows and columns of the array used for functions:
The file contains:
4 4
5.5 7.8 7.8 3.3
2.2 1.1 4.4 7.7
9.9 7.6 4.4 6.6
9.0 4.0 5.0 2.0
2
3
The code:
/*Diagonal function*/
double
diagsfunc (double ** arr, int diagr, int diagc)
{
int f, g;
double sum3 = 0;
for (f=0;f<diagr;++f)
{
for (g=0;f<diagc;++g)
{
if (f == g)
{
sum3 = sum3 + arr[f][g];
}
}
}
return(sum3);
}
int
main (void)
{
int cols, rows, i, j, nrows, ncols;
double **a;
double diag;
FILE * fpointer;
fpointer = fopen("projectfile.txt", "r");
fscanf(fpointer, "%d %d", &rows, &cols);
a = (double **) calloc (rows, sizeof(double *));
for (i=0; i<rows; ++i)
a[i] = (double *) calloc (cols, sizeof(double));
for (i = 0; i < rows; ++i)
for ( j = 0; j < cols; ++j)
fscanf(fpointer, "%lf", &a[i][j]);
for (i = 0; i < rows; ++i){
for ( j = 0; j < cols; ++j){
printf("%10.3lf ", a[i][j]);
}
puts("");
}
fscanf(fpointer, "%d %d", &nrows, &ncols);
if (rows == cols){
diag = diagsfunc(a, rows, cols);
printf("The sum of the diagonal elements is: %.3lf\n", diag);
} else {
printf("The array must be square to compute the sum of diagonals\n");
}
fclose(fpointer);
return(0);
}
There are few silly mistakes you did, lot more, but I am listing just required one
wrong variable used in the loop for (g=0;f<diagc;++g).
It should be
for (g = 0;g < diagc; ++g)
to find sum of diagonal, you no need 2 loops as pointed by Pablo you can do using one loop itself as
for(int i = 0; i < diagr; ++i) { /* if its a square matrix */
sum3 + = arr[i][i]
}
Complete Code
double diagsfunc (double ** arr, int diagr) {
int f, g;
double sum3 = 0;
for(int i = 0; i < diagr; ++i) {
sum3 += arr[i][i];
}
return sum3;
}
int main (void){
int cols, rows, i, j, nrows, ncols;
double **a;
double diag;
FILE * fpointer = fopen("projectfile.txt", "r");
if(fpointer == NULL ) {
/* put some message */
return 0;
}
fscanf(fpointer, "%d %d", &rows, &cols);
a = (double **) calloc (rows, sizeof(double *));
for (i=0; i<rows; ++i)
a[i] = (double *) calloc (cols, sizeof(double));
for (i = 0; i < rows; ++i)
for ( j = 0; j < cols; ++j)
fscanf(fpointer, "%lf", &a[i][j]);
for (i = 0; i < rows; ++i){
for ( j = 0; j < cols; ++j){
printf("%10.3lf ", a[i][j]);
}
puts("");
}
//rewind(fpointer); /* this you forget */
//fscanf(fpointer, "%d %d", &nrows, &ncols); /* why this statement ? */
if (rows == cols){
diag = diagsfunc(a, rows); /* no need to pass col value as its square matrix, both will be equal */
printf("The sum of the diagonal elements is: %.3lf\n", diag);
} else {
printf("The array must be square to compute the sum of diagonals\n");
}
fclose(fpointer);
return(0);
}
Also check all functions return value & learn how to debug your code.
Related
I am trying to raise a matrix to a power, using pointers but there is a mistake in my code I can't find.
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
>
int **alloc(int r, int c) {
int **d;
d = (int **)malloc(r * sizeof(int *));
for (int i = 0; i < r; i++) {
d[i] = (int *)malloc(c * sizeof(int));
}
return d;
void input(int **A, int r, int c) {
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
printf("[%d][%d]=", i, j);
scanf_s("%d", &A[i][j]);
}
}
}
void output(int **A, int r, int c) {
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
printf("%d ", A[i][j]);
}
printf("\n");
}
}
void power(int **A,int**D, int r, int c,int p) {
int i, j,k;
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
D[i][j] = A[i][j];
}
}
while (p) {
// this is the matrix multiplication, where I attempt to multiply my matrix A with itself, and store the result in D, which initially started as A's copy, and p is the power I'm raising it to.
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
for (k = 0; k < c; k++)
D[i][j] = D[i][j] + A[i][k] * D[k][j];
}
}
p--;
}
}
void main() {
int r, c;
int **A, **D;
printf("rows A: ");
scanf_s("%d", &r);
printf("columns A: ");
scanf_s("%d", &c);
A = alloc(r, c);
printf("\nValues of A:\n");
input(A, r, c);
printf("\nMatrIX A is:\n");
output(A, r, c);
D = alloc(r, c);
printf("input the value you want to raise your matrix to: ");
int p;
scanf_s("%d", &p);
power(A, D, r, c, p);
printf("\nMatrix raised to said power is:\n");
output(D, r, c);
_getch();
}
When I input the rows and columns as 2 each, and input all values in the matrix as 1 and raise it to the power of 3, my answer should be
4 4
4 4
instead of
72 72
232 232
What is wrong in my code? If I were to print the D matrix before the multiplication, it would print it correctly, as:
1 1
1 1
Your two-step allocation looks okay, except that you don't free the memory after you're done. Your problem is in how you multiply the matrix:
Raising a matrix to a power involves multiplying it to itself. You can only do that if the matrix is square. You can replace all occurrences of rows r and columns c with a single dimension n.
When you do the actual multiplication:
D[i][j] = D[i][j] + A[i][k] * D[k][j];
you assign to D and read from it at the same time. Subsequent calculations (of the same multiplication) will see a changed value of D[i][j]. You will need a temporary "scratch" matrix.
Your code multiplies once too many. Also, Raising a matrix to the power of zero should yield the identity matrix.
Here's how your power function could look like:
void power(int **A, int **D, int n, int p)
{
int i, j,k;
// assign identity matrix to result D
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
D[i][j] = (i == j);
}
}
// create a scratch matrix
int **tmp = alloc(n);
while (p-- > 0) {
// multiply [tmp] = [A] * [D]
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
tmp[i][j] = 0;
for (k = 0; k < n; k++)
tmp[i][j] += A[i][k] * D[k][j];
}
}
// copy [D] = [tmp]
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
D[i][j] = tmp[i][j];
}
}
}
// TODO: clean up the scratch matrix
}
#include <stdlib.h>
#include <stdio.h>
double **transpose(double **arr, int r, int c);
double **transpose(double **arr, int r, int c){
//will hold the transposed matrix
double **arrT;
arrT = (double **)malloc(c * sizeof(double *));
for(int i = 0; i < c; i++){
arrT[i] = (double *)malloc(r * sizeof(double));
}
//transpose the matrix
for(int i = 0; i < c; i++){
for(int j = 0; j < r; j++){
arrT[j][i] = arr[i][j];
}
}
return arrT;
}
int main(int argc, char *argv[]){
//if there is no argument
if(argc < 2){
printf("There is no argument\n");
return -1;
}
//training data
char *fname = argv[1];
//test data
char *fname2 = argv[2];
//pointer for training data
FILE *fptr;
//pointer for test data
FILE *fptr2;
//number of columns
int column;
//number of rows
int row;
//opens training data file and reads it
fptr = fopen(fname, "r");
//will scan the first line of training data
//to store column of attributes and we add
//1 more column for price
fscanf(fptr, "%d\n", &column);
//adds column for prices
column++;
printf("Number of columns: %d\n", column);
//will scan the second line of training data
//to store number of rows
fscanf(fptr, "%d\n", &row);
printf("Number of rows: %d\n", row);
//allocate array X that will hold attributes
double **X;
X = (double **)malloc(row * sizeof(double *));
//allocate array that will hold everything attributes
//and prices
double **arr;
arr = (double **)malloc(row * sizeof(double *));
//allocate array that will hold prices
double *Y;
Y = (double *)malloc(row * sizeof(double *));
for(int i = 0; i < row; i++){
X[i] = (double *)malloc(column * sizeof(double));
arr[i] = (double *)malloc(column * sizeof(double));
}
//will store the whole training data into arr
printf("This is training data: \n");
for(int i = 0; i < row; i++){
for(int j = 0; j < column; j++){
fscanf(fptr, "%lf,", &arr[i][j]);
printf("%lf\t", arr[i][j]);
}
printf("\n");
}
//copies training data for the attribute array
for(int i = 0; i < row; i++){
for(int j = 0; j < column; j++){
X[i][j] = arr[i][j];
}
}
//will set attributes first column
//to all 1's
for(int i = 0; i < row; i++){
X[i][0] = 1;
}
printf("This is attributes:\n");
for(int i = 0; i < row; i++){
for(int j = 0; j < column; j++){
printf("%lf\t", X[i][j]);
}
printf("\n");
}
//will set the first column or training
//data to the prices array
printf("This is prices: \n");
for(int i = 0; i < row; i++){
Y[i] = arr[i][0];
printf("%lf\n", Y[i]);
}
//matrix will hold transposed
double **trans;
transpose(X, row, column);
/*
printf("This is transposed of attributes\n");
for(int i = 0; i < row; i++){
for(int j = 0; j < column; j++){
printf("%lf\t", trans[i][j]);
}
printf("\n");
}
*/
return 0;
}
double **transpose(double **arr, int r, int c){
//will hold the transposed matrix
double **arrT;
arrT = (double **)malloc(c * sizeof(double *));
for(int i = 0; i < c; i++){
arrT[i] = (double *)malloc(r * sizeof(double));
}
//transpose the matrix
for(int i = 0; i < c; i++){
for(int j = 0; j < r; j++){
arrT[j][i] = arr[i][j];
}
}
return arrT;
}
Hi so i havent completed the code yet but the code should still run fine as it is. The problem is though I try to the method to transpose the matrix and when it does it says segmentation fault core dumped. If you can tell me whats wrong that would be greatly appreciated. I am trying to pass a 2d array.
The txt file it should read should be input.txt:
where 4 is the first line, and 10 is the second line.
4
10
221900,3,1,1180,1955
538000,3,2.25,2570,1951
180000,2,1,770,1933
604000,4,3,1960,1965
510000,3,2,1680,1987
1230000,4,4.5,5420,2001
257500,3,2.25,1715,1995
291850,3,1.5,1060,1963
229500,3,1,1780,1960
323000,3,2.5,1890,2003
My code doesn't seem to be able to read the input file correctly. It somehow only reads the first line of my matrix and then it inputs the second line under "right hand side" instead of making another line for the matrix under "coefficient matrix". Additionally, it prints the third line under "Initial Guesses" rather than the third line of the matrix.
I'm assuming the error is somewhere in the code that I have posted below but let me know if you believe the code below is correct and somewhere else in my code is where this problem is originating from.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define MAX_DIM 100
#define MAX_ITER 500
#define TOLERANCE 1.e-6
void gauss_seidel(double **a, double *b, double *x, int n);
void print_screen_A_b_x(double **a, double *b, double *x, int n);
void main()
{
int i, j, *ptr, n;
int violation_counter, answer;
int violation_rows[MAX_DIM];
double sum;
double **a;
double *b, *x;
FILE *input_Ptr; //pointer to input file
//Open the input file
input_Ptr = fopen ( "my_input.txt", "r" );
if (input_Ptr == NULL) {
puts("\nInput file was not opened succesfully.\n");
exit(-1);
}
//read size of the problem
fscanf(input_Ptr, "%d", &n);
//dynamic memory allocation
a = (double **) malloc (n * sizeof(double *));
for (i = 0; i < n; i++) {
a[i] = (double *) malloc (n * sizeof(double));
}
b = (double *) malloc (n * sizeof(double));
x = (double *) malloc (n * sizeof(double));
/* read in data */
//n = MAX_DIM + 1;
//while (n > MAX_DIM) {
//fscanf(input_Ptr, "%d", &n);
//}
printf("\n");
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
fscanf(input_Ptr, "%lf", &a[i][j]);
}
for (i = 0; i < n; i++) {
fscanf(input_Ptr, "%lf", &b[i]);
}
for (i = 0; i < n; i++) {
fscanf(input_Ptr, "%lf", &x[i]);
}
printf("\n");
}
fclose(input_Ptr);
print_screen_A_b_x(a, b, x, n);
puts("Solution vector:");
for (i = 0; i < n; i++) {
printf("x[%d] = %10.5f \n", i, x[i]);
//free memory
for (i = 0; i < n; i++) {
free(a[i]);
}
free(a);
free(b);
free(x);
return 0;
}
/* test the convergence criterion */
violation_counter = 0;
for (i = 0; i < n; i++) {
sum = 0.0;
for (j = 0; j < n; j++)
if (i != j)
sum = sum + fabs(a[i][j]);
if (fabs(a[i][i]) < sum) {
violation_rows[violation_counter] = i;
violation_counter = violation_counter + 1;
}
if (a[i][i] == 0.0) {
printf("Found diagonal element equal to zero;
rearrange equations; exiting ...\n");
exit(0);
}
}
if (violation_counter > 0) {
printf("The Gauss-Seidel convergence criterion is violated in %d rows out of %d\n", violation_counter, n);
printf("Specifically, it was violated in rows:\n");
for (i = 0; i < violation_counter; i++)
printf("%d ", violation_rows[i]);
printf("\n");
printf("Enter 1 if you want to continue; any other number to abort : ");
scanf("%d", &answer);
if (answer != 1)
exit(1);
printf("Check results carefully\n\n");
}
/* initialize the solution vector -- initial guesses */
for (i = 0; i < n; i++) {
printf("Enter an initial guess for x[%d] of the solution vector : ", i);
scanf("%lf", &x[i]);
}
/* solve the system */
gauss_seidel(a, b, x, n);
/* output solution */
for (i = 0; i < n; i++)
printf("x[%d]=%f\n", i, x[i]);
printf("\n");
}
/* function to solve a system using Gauss-Seidel */
void gauss_seidel(double **a, double *b, double *x, int n)
{
double maxerror = 1.0e-7;
double iteration_error;
double e, sum, temp;
int i, j;
while (maxerror > 1.e-6) {
iteration_error = 0.0;
for (i = 0; i < n; i++) {
sum = 0.0;
for (j = 0; j < n; j++) {
if (i != j)
sum = sum + (a[i][j] * x[j]);
}
}
temp = (a[i][n] - sum) / a[i][i];
e = fabs((temp - x[i]) / x[i]);
x[i] = temp;
if (e > iteration_error)
iteration_error = e;
}
maxerror = iteration_error;
}
void print_screen_A_b_x(double **a, double *b, double *x, int n)
{
int i, j;
printf("\n Coefficient matrix:\n");
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
printf("%10.2f", a[i][j]);
}
printf("\n");
}
printf("\n Right hand side vector:\n");
for (i = 0; i < n; i++) {
printf("%10.2f \n", b[i]);
}
printf("\n Initial guess:\n");
for (i = 0; i < n; i++) {
printf("%10.5f \n", x[i]);
}
return;
}
Add \r\n in your post loop if statement.
You show us:
void gauss_seidel(double a[][MAX_DIM], double b[], double x[], int n)
and:
void print_screen_A_b_x(double **a, double *b, double *x, int n)
You cannot pass the same object as the first argument to both functions; they are (radically) different types, even though you use double subscripts with both. Since you've not shown how the matrix is actually defined, there isn't anything more we can do to help you.
Your compiler should be shrieking at you about one (or both) calls. Heed your compiler. It knows more about C than you do at the moment. It won't object unless there's a serious problem. If by some mischance your compiler was not complaining, then you need to either turn on compilation warnings (and work with C11, or perhaps C99, as the version of the standard — definitely not C90) or get a better compiler.
Analysis of one update
One version of the updated code in the question has input code like this:
// read size of the problem
fscanf(input_Ptr, "%d", &n);
// dynamic memory allocation
a = (double **)malloc(n * sizeof(double *));
for (i = 0; i < n; i++)
{
a[i] = (double *)malloc(n * sizeof(double));
}
b = (double *)malloc(n * sizeof(double));
x = (double *)malloc(n * sizeof(double));
printf("\n");
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
fscanf(input_Ptr, "%lf", &a[i][j]);
}
for (i = 0; i < n; i++)
{
fscanf(input_Ptr, "%lf", &b[i]);
}
for (i = 0; i < n; i++)
{
fscanf(input_Ptr, "%lf", &x[i]);
}
printf("\n");
}
The good news is that except for the absence of error checking, the memory allocation looks OK.
The bad news is that under most plausible inferences of what the data looks like, the main input loops are completely wrong. Assuming the value in n is N, the first iteration of the input loop reads N values into a[0] (which is fine), and then reads N values into b (which is fine as far as it goes), and then reads N values into x (which is also fine as far as it goes). The value of i is now n; when it is incremented by the outer loop, i is bigger than n, so the outer loop terminates, but you've only read one row of the main matrix.
Most likely, you should be using:
// read size of the problem
if (fscanf(input_Ptr, "%d", &n) != 1)
…report error and skedaddle…
// Check n for plausibility
if (n < 1 || n > 1000)
…report implausibility and skedaddle…
// dynamic memory allocation
…as before, except you should error check all the allocations…
printf("\n");
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
if (fscanf(input_Ptr, "%lf", &a[i][j]) != 1)
…report error and skedaddle…
}
}
for (i = 0; i < n; i++)
{
if (fscanf(input_Ptr, "%lf", &b[i]) != 1)
…report error and skedaddle…
}
for (i = 0; i < n; i++)
{
if (fscanf(input_Ptr, "%lf", &x[i]) != 1)
…report error and skedaddle…
}
The fact that you don't check for errors means you don't know when things go wrong. You can't afford not to know when things go wrong, so you can't afford not to check for errors.
skedaddle |skɪˈdad(ə)l|
verb [ no obj. ] informal —
depart quickly or hurriedly; run away.
Here is simple code just reading two matrix one is 3*3 dimensional and other is 3*1 dimensional. while printing first matrix A[3][3] the last element of matrix is printing zero in void printarray(double **A, int n ) function.
Below my code:
#include <stdio.h>
#include<malloc.h>
void printarray(double **A, int n );
void main(){
double **A;
int n = 3;
int row,col;
double *b;
A = (double **) malloc(n * sizeof(double**));
for (row = 1; row<= n; row++) {
A[row] = (double *) malloc(n * sizeof(double));
}
// Initialize each element.
for (row = 1; row<= n; row++) {
for (col = 1; col<= n; col++) {
printf("A[%d][%d]= %u \t",row,col,&A[row][col]);
scanf("%lf",&A[row][col]); // or whatever value you want
}
}
//print A
printf("\n...........array in main.................\n");
for (row = 1; row<= n; row++) {
for (col = 1; col<= n; col++) {
printf("A[%d][%d]=%u \t %lf",row,col,&A[row][col],A[row][col]);
printf("\n");
}
}
b = (double *) malloc(n * sizeof(double));
printf("\n enter the elemet of b \n"); // Initialize each element.
for (row = 1; row<= n; row++){
printf("address=%u \t",&b[row]);
printf("b[%d]=",row);
scanf("%lf",&b[row]);
printf("\n");
}
printarray((double **)A, n );
}// Print it
void printarray(double **A, int n ){
int i;
int j;
printf("\n.....print a.............\n");
for( j = 1; j <= n; j++ ){
for( i = 1; i <= n; i ++){
printf("A[%d][%d]= %u \t",j,i,&A[j][i]);
printf( "%lf ", A[j][i] );
}
printf( "\n" );
}
}
One the problem comes from the indexing of your array. Array indexing start at 0.
This means that in order to loop through your array, you need your for loop to start at 0 up to n-1:
for (int row=0; row<n;++row) {/*...*/}
If I run my program, and When I typed the dimensions of matrix, after I typed the first value of matrix , the console write out: Segmentation fault
For example:
4
3
Segmentation fault
Process returned 139(0x8B)
void inMatrix(int n, double **matrix)
{
int j, i;
for (i = 0; i < n; i++)
{
for (j= 0; j < n; j++)
{
scanf("%lf", &matrix[i][j]);
}
}
}
void inVector(double *vektor, int n)
{
int k;
for (k = 0; k < n; k++)
{
scanf("%lf", &vektor[k]);
}
}
int main()
{
int n;
// read dimension of matrix and value
scanf("%d", &n);
//matrix
double** matrix = (double **) calloc(n, sizeof ( double*));
//vector
double* vector = (double *) calloc(n, sizeof ( double));
// read values of matrix
inMatrix(n, matrix);
// read values of vector
inVector(vector, n);
outVector(vector, n);
printf("\n");
return 0;
}
You didn't allocate memory for the elements of the matrix, only for the pointers to the individual lines.
You need something like:
for (i = 0; i < n; i++)
matrix[i] = malloc(n * sizeof(double));
Of course, you must free stuff in the same manner when you're done with it.
for (i = 0; i < n; i++)
free(matrix[i]);
free(matrix);