Denys Korovets
Denys Korovets

Reputation: 75

Why does my fscanf not read?

I have to write a program that finds a path of maximum value in a triangular maze of integer numbers.

I have a problem with the fscanf function. It doesn't read for some reason. I would highly appreciate any help or advise as this project is due ASAP.

Here is an example of a maze:

30

47 1

35 65 21

0 74 94 58

71 29 34 28 60

97 6 29 19 26 68

37 1 48 98 57 89 64

60 38 33 23 49 57 19 50

4 83 52 47 84 60 16 56 90

19 59 6 10 97 47 96 93 59 50

And this is what I've got so far:

/#include <stdio.h>
/#include <stdlib.h>
/#define MAX 100

void read    (int maze [][MAX]);
int findPath (int maze[][MAX], int map[][MAX], int size);
void print   (int map [][MAX]);

int main()
{
    int maze [][MAX] = {};
    int map  [][MAX] = {};

    int sum = 0;
    int size = MAX;

    read     (maze);
    findPath (maze, map,size);
    print    (map);

    return;
}

void read (int maze[][MAX])
{
    FILE * mazeFile;
    int num, r, c, count;

    if ((mazeFile = fopen ("t4.txt", "r")) == NULL)
    {
        printf ("Error opening a file\n");
    }
    else
    {
        while (mazeFile != EOF)
        {        
            fscanf (mazeFile, "%d", &maze[r][c]);

            for (r = 0; r < 100 ; r++)
            {
                count = r + 1;
                for (c = 0; c <= count; c++)
                {
                    printf ("(%d, %d) = %d\n",r, c, maze[r][c]);
                }
            }
            fclose (mazeFile);
            return;
        }
    }
}

int findPath (int maze[][MAX], int map[][MAX], int size)
{
    int sum [MAX][MAX] = {0};
    int row, col, maxNum;

    for(row=(size-1); row >= 1; --row)
    {
        for (col-row;col>=1;--col)
        {
            maxNum = (sum[row+1][col] > sum [row+1][col+1] ? col : col + 1);
            sum[row][col]= maze[row][col] + sum [row+1][maxNum];

            map[row][col] = maxNum;
        }
    }  
    return sum [0][0];
}

void print (int map [][MAX])
{
    printf ("(%d, %d) = ", map[0][0], map[0][1]);
    return;
}

Upvotes: 2

Views: 528

Answers (1)

Ahmed Masud
Ahmed Masud

Reputation: 22372

Well :-) There are a lot of issues but the one that you ask about is reading the file so I will just address that for now:

Some Corrections

  • First do NOT use read, write, as they are standard library functions you will run into lots of issues;
  • Do not use void as a return type for functions, use int and return 0 on success and negative numbers for failure (it's conventional) and helps you write code that catches errors
  • Do use comments to describe your function
  • Tabs are good, at least 4 spaces ( I am a kernel programmer so I like 8-space tabs) they help when you are sleepy at 2:30AM and trying to figure out answers
  • ALL statements inside a function should be tabbed in and NOT line up with the { }
  • A good convention is to use opening { on newline only for function body and for the rest like if, for, while etc the { should be on the same line as the statement and closing } should line up with the first letter of the statement.
  • DO NOT put too many white spaces between each statement. It makes code less readable.

Example of good approach

Here is an example of how to code reading the file properly.

Step 1:

create a simple function that just reads the contents and dumps it back out so that you know your READING is fine.

#include <stdio.h>

/** 
 * @function: read_maze
 * @desc: Reads a maze file and dumps it to stdout, 
 * @return: Returns 0 on success, -1 on failure
 *
 */

int read_maze(const char *filename) 
{
     FILE *fp;
     int entry;

     fp = fopen(filename, "r");
     if ( !fp ) {
          perror(filename); /* prints system error related to
                             * the problem reading mazefile 
                             */
          return -1;
     }

     while(!feof(fp)) {
          if (fscanf(fp, "%d", &entry) == 1) { 
              printf ("%d\n", entry);
          }
     }

     return 0;
}

int main()
{
     if(read_maze("t4.txt")) {
          return -1;
     }

     return 0;
}

Step 2:

Create a triangular maze array that makes sense:

Okay so now that we know that we can read a file properly let's try and put it into a structure that makes sense.

We know that we have a bunch of rows (100), 1st row has 1 column, 2nd row has 2, 3rd row 3, and so on...

In other words each row has the same number of columns as its cardinality (index+1);

So is it something like the following?

int row0[1];
int row1[2];
int row2[3];
   .
   .
   .
int row99[100]; 

That's kinda ugly and not really programmatic; it would be nice to do this automatically; Well we know that the fixed number is the number of rows and the dynamic allocation is associated to the index. So let's make an array of pointers to integers; and then each member of this array can be a dynamically allocated memory block just as big as the cardinality of the member. (Mouthful hehe)

#define MAXROWS 100

int *row[MAXROWS]; 

NOTE: that conceptually MAXROWS actually corresponds to the hardcoded 0-99 we stuck in front the word row and NOT the declaration piece of array size in brackets. So for int row55[56]; this is about declaring the 55; the 56 declaration will come from a malloc later;

Now we know that a pointer to a data type is exactly that, a pointer that POINT to memory blocks for our data (essentially acting as an array) in other words let's allocate the appropriate columns for each row:

 /* starting from beginning */

 #define MAXROWS 100

 int *rows[MAXROWS];

 int init_triangular_array() 
 {
     int k;
     memset(rows, 0, sizeof(int *)*MAXROWS); /* make the rows array all zeros */
     for (k = 0; k < MAXROWS; k++) {
         rows[k] = (int *)calloc(k+1, sizeof(int)); /* cardinality */
         if( rows[k] == NULL ) {
              fprintf(stderr, "Unable to allocate memory, quoting\n");
              exit(-1); /* just kill the program */
         }
     }
 }

Now that we have a function to initialize the array ... let's also create a function to free the array when we are done with it; as that's just good coding practice.

 void free_triangular_array()
 {
     int k;
     for (k = 0; k  < MAXROWS; k++ ) {
         if ( rows[k] ) 
              free(rows[k]);
     }
 }

And now lets write a function to fill it up from our file:

 int fill_triangular_array(const char *filename)
 {

       FILE *fp = fopen(...);
       int row = 0, col = 0;

       while(!feof(fp)) {
             for (col = 0; col <= row_number; col++ ) {
                   // read an entry as above 
                   rows[row][col] = entry; 
             }
       }
 }

You get to fill in the missing bits.

and once you've done that now to use it all

 int main() 
 {

         init_triangular_array();
         fill_triangular_array();
         /* do something with the array */
         free_triangular_array();

 }

Upvotes: 3

Related Questions