-3

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;
}
David_red
  • 13
  • 5
  • 2
    Don't you think it it is common sense for you to show us the function that actually does the file reading since that is what you describe as being problematic? Or are you really asking about printing the array values? Please clarify and please have a read of [how to create a minimal complete and verifiable example](https://stackoverflow.com/help/mcve) for a description of what is expected. – kaylum Apr 07 '16 at 22:45
  • `printf("%10.5f \n", a[i]);`. For starters, `a[i]` is a *pointer* to a `double`. It is not a `double`. – kaylum Apr 07 '16 at 22:49
  • `It somehow only reads the first line of my matrix` ... does this suggest that there is a problem with the code handling input ... so please post the code that handles input ... and show what format the source data is in. – anita2R Apr 07 '16 at 22:49
  • @kaylum sorry. Edited it and included the function. – David_red Apr 08 '16 at 02:19

2 Answers2

0

Add \r\n in your post loop if statement.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

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.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Thanks for your comment. I added asterisks to that first piece and I'm getting the errors "Expression must have arithmetic type" for if (i != j) sum = sum + (a[i][j] * x[j]); and in some other places of my function. – David_red Apr 08 '16 at 04:05
  • Can't say — your description is too vague and there are too many possibilities for what might be going wrong. I could guess, but I'd probably be wrong. Please read up on how to create an MCVE ([MCVE]). Update your question with the revised code (don't remove the original), and show how the matrix is allocated, and the function(s) called. – Jonathan Leffler Apr 08 '16 at 04:27
  • If you could take a quick look at the entirety if my code that would be very helpful. I've been struggling for hours on this and my professor doesn't seem to know the answer either. – David_red Apr 08 '16 at 04:31
  • I'll look at it, but pay attention. I previously said: **Update your question with the revised code (don't remove the original),** but you did remove the original — or the version I responded to, to be more precise — because the signature of `gauss_seidel()` changed. – Jonathan Leffler Apr 08 '16 at 04:40
  • Please read [What should `main()` return in C and C++](http://stackoverflow.com/questions/204476/). If you're not on Windows, using `void main()` is inexcusable. – Jonathan Leffler Apr 08 '16 at 04:42
  • Oh, sorry, I've been testing out different things based on the research and things I'm finding elsewhere. I'll keep that in tact and make sure I don't change anything without keeping the original up. I'm on Windows. – David_red Apr 08 '16 at 04:44
  • What's with the block of code `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]); for (i = 0; i < n; i++) { free(a[i]); } free(a); free(b); free(x); return 0; }` —— you print one line of data and then free everything and exit? It makes life difficult. Please provide a minimal test data file (for example, n = 3). I can't be bothered to work out what it should look like (and shouldn't have to). – Jonathan Leffler Apr 08 '16 at 04:48
  • How do I stop that from only printing one line? Thanks once again. – David_red Apr 08 '16 at 05:08
  • 'Tis curious that you pass `b` to `gauss_seidel()` but the function uses it not. – Jonathan Leffler Apr 08 '16 at 05:47
  • I noticed that later but apparently it still worked for what I was doing previously. The function supposedly should work for both so I didn't want to mess with it. I'm in the process of implementing what you posted. thanks again for your help. I'm getting an error in line 39, " a potentially unintialized local pointer variable 'a' used, working on that. – David_red Apr 08 '16 at 05:55