Thread: using FSCANF to read mixed text/double files

  1. #1
    Registered User
    Join Date
    Mar 2009
    Posts
    114

    using FSCANF to read mixed text/double files

    Hi there,

    I am trying to read a file that is only partly sequential; it contains strings between "arrays" of ints and arrays of doubles of different sizes.

    The file is reported below. Although I could read it by a combination of fgets() and strtok() calls, I am trying to change my old way to read it into a more efficient and shorter way by using fscanf throughout.

    The problem is that, from the way I wrote the algorithm, it apparently stops reading the file correctly once it reaches the intermediate strings END_ELEMENTS and COORDINATES (See below).

    I believe that I am doing somethign wrong in the sequence of calling fscanf, but I can't understand why.

    I hope someone can help with this. I am sure it is a common task to read mixed files.
    I use programming for my work but I am not actually a programmer, so that reading files is at times tricky

    Thank you in advance:

    1) File to be read
    Code:
    ELEMENTS  
               1          2         4         3         1  
               2          5         7         4         2  
               3          4         8         6         3  
               4          7         9         8         4  
    END_ELEMENTS  
    COORDINATES  
              1  0.000000 10.000000    
              2  0.000000 5.000000    
              3  5.000000 10.000000    
              4  5.000000 5.000000    
              5  0.000000 0.000000    
              6  10.000000 10.000000    
              7  5.000000 0.000000    
              8  10.000000 5.000000    
              9  10.000000 0.000000    
    END_COORDINATES
    2) My function that does that:
    Code:
    	//Testing the code:
    	
    	int nnodes = 9;
    	int nelem = 4;
    	
    	char header[32];
    	int	CONN[nelem][4];
    	double COORDS[nnodes][3];
    	
    	
    	//READ the FIRST LINE OF THE FILE:  ELEMENTS
    		fscanf(msh_file_ID, "%s\n", header);
    		printf("%s\t\n", header);
    		k = 1;
    		i = 0;
    
    		while( !feof(msh_file_ID)){
    			if(k <= nelem){
    			//Read CONN:
    				fscanf(msh_file_ID, "%d %d %d %d %d\n", &(CONN[k][0]), &(CONN[k][1]), &(CONN[k][2]), &(CONN[k][3]), &(CONN[k][4]) );
    				
    				printf(" %d %d %d %d %d\n ", CONN[k][0], CONN[k][1], CONN[k][2], CONN[k][3], CONN[k][4] );
    			}
    			//Read the intermediate strings: "END_ELEMENTS" and "COORDINATES"
    			else if(k > nelem && k <= nelem+2){
    				//String END_ELEMENTS
    				fscanf(msh_file_ID, "%s\n", header);
    					printf("%s\t\n", header);
    				//String COORDINATES
    				fscanf(msh_file_ID, "%s\n", header);
    					printf("%s\t\n", header);
    			}
    			//Read COORDS
    			else if(k > nelem+2 && k <= nelem+2+nnodes){
    				fscanf(msh_file_ID, "%f %f %f", &COORDS[i][0],&COORDS[i][1],&COORDS[i][2]);
    				printf(" %f %f %f\n", COORDS[i][0], COORDS[i][1],COORDS[i][2]);
    				i++;
    			}
    			else
    				return;
    		k++;
    		}//END while

  2. #2
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    do not use feof to control loop - read FAQ

    you have 2 fscanf in same iteration to read both END_ELEMENTS and COORDINATES and increment k once

    but want to read headers in 2 iterations
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  3. #3
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    This is my suggestion on your program:

    Code:
    /* Array2D.c: Shows how to malloc 2D arrays of type int and double, 
    by Adak, March 2009.
    Status: ok
    
    This is what the data file should have in it:
    
    
      ELEMENTS  
               1          2         4         3         1  
               2          5         7         4         2  
               3          4         8         6         3  
               4          7         9         8         4  
    END_ELEMENTS  
    COORDINATES  
              1  0.000000 10.000000  0   
              2  0.000000 5.000000   1  
              3  5.000000 10.000000  2   
              4  5.000000 5.000000   3  
              5  0.000000 0.000000   4  
              6  10.000000 10.000000 5   
              7  5.000000 0.000000   6   
              8  10.000000 5.000000  7   
              9  10.000000 0.000000  8   
    END_COORDINATES
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    int main(void)  {
    
       FILE * msh_file_ID;
       //Testing the code:
       int i, k, num;
       int nnodes = 9;
       int nelem = 4;
       double garbage = 0.00; //used to force linking to floating point header
    	
       char header[32];
       int	**CONN;         //2 *'s for a 2D array
       double **COORDS;
       garbage = sqrt(4);   //force the floating pt packing to load up
    
       CONN = malloc(nelem * sizeof(int*)); //get memory for 1D
       for (i = 0; i < nelem; i++)  {
          CONN[i] = malloc(4 * sizeof(int));   //get memory for 2D
       }
    
    
       COORDS = malloc(nnodes * sizeof(double*));
       for(i = 0; i < nnodes; i++)
         COORDS[i] = malloc(2 * sizeof(double));
    	
       msh_file_ID = fopen("Array2D.txt", "rt");
       
       //READ the FIRST LINE OF THE FILE:  ELEMENTS
       fscanf(msh_file_ID, "%s\n", header);
       printf("%s\t\n", header);
       
       i = 0;
       while( !feof(msh_file_ID)){
          for(k = 0; k < nelem; k++) {
    	//Read CONN:
    	fscanf(msh_file_ID, "%d %d %d %d %d\n",&(CONN[k][0]),&(CONN[k][1]),&(CONN[k][2]),&(CONN[k][3]));
    				
    	printf(" %d %d %d %d %d\n ", CONN[k][0], CONN[k][1], CONN[k][2], CONN[k][3]);
          }
          //Read the intermediate strings: "END_ELEMENTS" and "COORDINATES"
          //String END_ELEMENTS
          fscanf(msh_file_ID, "%s\n", header);
          printf("%s\t\n", header);
          //String COORDINATES
          fscanf(msh_file_ID, "%s\n", header);
          printf("%s\t\n", header);
             
          //Read COORDS
          for(i = 0; i < nnodes; i++) {
             fscanf(msh_file_ID, "%d", &num);
             fscanf(msh_file_ID, "%lf %lf", &COORDS[i][0], &COORDS[i][1]);
             printf(" %d. %lf %lf\n", num, COORDS[i][0], COORDS[i][1]);
          }
    		
          fscanf(msh_file_ID, "%s", header);
          printf("%s\n", header);
    
          //if(strcmp(header, "END_COORDINATES") == 0)  //just FYI
    		       //break;
       }//END while
    
       fclose(msh_file_ID);
       printf("\n\n\t\t\t     press enter when ready \n");
       garbage = getchar(); garbage++;
    
       
       for (i = 0; i < nelem; i++)  
          free(CONN[i]);
       free(CONN);
    
       for(i = 0; i < 9; i++)
          free(COORDS[i]);
       free(COORDS);
    
       return 0;
    }
    The if() else() type logic, I didn't like. It made it lean toward being unclear and harder to debug.

    I briefly tested the !feof() loop, and found it worked ok in your loop, so I didn't replace it.

    Cheers!

  4. #4
    Registered User
    Join Date
    Mar 2009
    Posts
    114
    Hello Adak,

    Thank you so much for replying and helping with your version of the code! It worked perfectly; I really appreciate it.

    Thank you again

    All the best
    cfd

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. fscanf: read word from file
    By Dedalus in forum C Programming
    Replies: 1
    Last Post: 06-24-2009, 02:56 AM
  2. read mix file: fscanf fgets
    By cfdprogrammer in forum C Programming
    Replies: 1
    Last Post: 03-20-2009, 11:38 AM
  3. read files
    By malebo in forum C++ Programming
    Replies: 3
    Last Post: 05-22-2008, 12:25 PM
  4. "sorting news" assignment
    By prljavibluzer in forum C Programming
    Replies: 7
    Last Post: 02-06-2008, 06:45 AM
  5. Replies: 12
    Last Post: 10-17-2005, 06:49 AM

Tags for this Thread