Thread: Reading text file and structuring it..

  1. #16
    Registered User
    Join Date
    Jun 2004
    Posts
    722
    Killroy edit that post and leave only the necessary code. That's HUGE!!!! Noone will even look at it

  2. #17
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    You're over complicating your read process. Why don't you use the method I've suggested?
    Code:
    char buf[BUFSIZ];
    char *ptr;
    
    while( fgets( buf, BUFSIZ, inputfile ) != NULL ) /* read a line from file */
    {
        if( (ptr = strstr( buf, "xx." ) != NULL ) /* if the line contains 'xx.' */
        {
            ptr += 3; /* skip past 'xx.' */
            /* now do something with this line. use 'ptr' to sscanf from or whatever,
             * as we have already skipped past the 'xx.' portion.
             */
        }
    }
    Also, are you checking to make sure malloc hasn't failed?
    Furthermore, you never need to typecast the return value of malloc or realloc in C.
    Finally, you should be checking the return value of your sscanf call to makes sure it's actually scanning the right amount of items in.

    Try working from there.

    Quzah.
    Hope is the first step on the road to disappointment.

  3. #18
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,662
    Well it seems to me that all your cases do exactly the same thing, except for one line

    Behold the power of common code and indentation
    Code:
    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <ctype.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <math.h>
    
    #define MAX_LINE        (128+1)     /* Maximum length of a source line plus one */
    #define CM_NAME_LENGTH  20
    
    /* an enumeration is better that a whole bunch of #defines */
    enum {
        CM_CF = 1,
        CM_CF_CA,
        CM_WF_Shield,
        CM_Comma,
        CM_Lee_Cld
    };
    
    typedef struct {
        char Name[CM_NAME_LENGTH];
        int Value;
    } NameDefinition_t;
    
    typedef struct {
        int Index;
        int X;                      /* Longitude */
        int Y;                      /* Latitude */
        char Direction;             /* Direction, East or West */
        int CommentLines;           /* Number of infolines */
        char **Comments;
    } NameDescription_t;
    
    NameDefinition_t CM_lijst[] = {
        {"CF", CM_CF},
        {"CF in CA", CM_CF_CA},
        {"WF Shield", CM_WF_Shield},
        {"Comma", CM_Comma},
        {"Lee Cloud", CM_Lee_Cld},
        {"", 0}
    };
    
    /* Open Structure to write XML file*/
    
    typedef struct WRITER {
        float lat;
        float lon;
        char CM[50];
        char info[2000];
        char dir;
        int cl;
    } WRITE;
    
    WRITE *StrXML;
    NameDescription_t *NameDescriptions = NULL;
    
    /* ************* Function ************************* */
    
    /* searches the name definitions and returns the associated value */
    int FindNameValue(char *Name)
    {
        int i;
        for (i = 0; *CM_lijst[i].Name; i++)
            if (strcmp(Name, CM_lijst[i].Name) == 0)
                return (CM_lijst[i].Value);
        return (0);
    }
    
    /* ************ Start of main ********************* */
    int main()
    {
        NameDescription_t *Name;
        char InputBuffer[MAX_LINE];
        char StartJunk[5], NameString[CM_NAME_LENGTH];
        int X1, X2, X3;
        int Y1, Y2, Y3;
        int idx, n, k;
        char C1, C2, C3;
        FILE *STRPfile;
    
        idx = 0;
        n = 0;
        k = 0;
    
        /* Allocate memory to later write XML file*/
        StrXML = malloc(256 * 256 * sizeof *StrXML );
    
        if ((STRPfile = fopen("test.txt", "r")) == NULL) {
            fprintf(stderr, "Error opening info-file :%s\n", "test.txt");
            exit(1);
        }
    
        for (idx = 0; idx <= 2; idx++) {
            fgets(InputBuffer, MAX_LINE, STRPfile);
        }
    
        while (fgets(InputBuffer, MAX_LINE, STRPfile)) {
            /* your %s to read the command would not cope with spaces */
            /* %[^:] is like %s, but it takes everything which isn't a : */
            sscanf(InputBuffer,
                   "%4s %[^:]: %2d%2d%c (%2d%2d%c - %2d%2d%c)",
                   StartJunk, NameString, &X1, &Y1, &C1, &X2, &Y2, &C2, &X3,
                   &Y3, &C3);
            printf( "Name='%s'\n", NameString );
    
            Name = malloc(sizeof *Name);
            memset(Name, 0, sizeof *Name );
            Name->Index = FindNameValue(NameString);
            Name->X = X1;
            Name->Y = Y1;
            Name->Direction = C1;
    
            /* descriptions end with a blank line in the file */
            while (fgets(InputBuffer, MAX_LINE, STRPfile) && InputBuffer[0] != '\n' ) {
                void *temp;
                Name->CommentLines++;
                temp = realloc( Name->Comments, Name->CommentLines * sizeof * Name->Comments );
                if ( temp != NULL ) {
                    /* successful realloc - OK to assign (possibly new) pointer */
                    Name->Comments = temp;
                    /* strdup is not a standard function */
                    Name->Comments[Name->CommentLines-1] = malloc( strlen(InputBuffer)+1);
                    if ( Name->Comments[Name->CommentLines-1] != NULL ) {
                        strcpy( Name->Comments[Name->CommentLines-1], InputBuffer );
                    }
                } else {
                    /* oops, no more memory, can't store this comment */
                    Name->CommentLines--;
                }
            }
    
            /* now save Name somewhere before it gets lost */
            printf( "Index=%d, X=%d, Y=%d, Dir=%c, NumComments=%d\n",
                Name->Index, Name->X, Name->Y, Name->Direction, Name->CommentLines );
        }
    
        fclose(STRPfile);
        return 0;
    }
    This prints the following
    Code:
    Name='CF'
    Index=1, X=57, Y=40, Dir=W, NumComments=2
    Name='CF in CA'
    Index=2, X=63, Y=12, Dir=W, NumComments=1
    Name='WF Shield'
    Index=3, X=54, Y=7, Dir=W, NumComments=1
    Name='Lee Cloud'
    Index=5, X=41, Y=1, Dir=W, NumComments=0
    Name='Lee Cloud'
    Index=5, X=48, Y=11, Dir=E, NumComments=0
    Name='Comma'
    Index=4, X=46, Y=8, Dir=E, NumComments=0
    I compiled it with
    gcc -W -Wall -ansi -pedantic -O2 hello.c
    If you're not compiling with a strong set of compiler options to diagnose all sorts of problems, I suggest you start.

  4. #19
    Registered User
    Join Date
    Nov 2004
    Posts
    17
    @ Salem..
    Thank you for taking a look at it. Your code was inspiring and helpes me to solve this problem and write the program.

    @ Quzah
    Maybe you were right and I was overcomplicating, but hey.. I am a newby in programming, and even more in C. So, i'll learn.. eventually.. Think that you will like my new code, it does (almost) what I want..

    @ To all.. thanx for everyone looking at this code!!


    Code:
    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <ctype.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <math.h>
    
    #define MAX_LINE        (128+1)     /* Maximum length of a source line plus one */
    #define CM_NAME_LENGTH  20
    #define MAX_INFO_LEN 2000
    
    
    /* ************ Start of main ********************* */
    int main()
    {
        char InputBuffer[MAX_LINE];
        char StartJunk[5], NameString[CM_NAME_LENGTH];
        int X1, X2, X3;
        int Y1, Y2, Y3;
        int idx, n, k, i, z;
        char C1, C2, C3, *INFO;
        FILE *STRPfile, *XML;
    
        idx = 0;
        n = 0;
        k = 0;
        i = 0;
        z = 0;
    
    /* ------------------------- XML STUFF --------------------------------*/
    
    
    /* Write Satrep file  in XML, plain stuff.. headers etc. need to be changed for file in which to write */
    
    /* After that, you can write there with this: fprintf(AllInfosFile,"%s[%c,...]",variable); For example reasons I HAVE opened file astroXML.txt. Change is possible on later level  */
    
    	 XML=fopen("manu_xml.txt","w");
    
    	 fprintf(XML,"<\?xml version=\"1.0\"\?>\n");
    
    	 fprintf(XML,"<satrep source=\"ASII\" issuer=\"ZAMG\" valid-time=\"");
    	 /*fprintf(XML,Sr_date," YYYY,MM,DD");*/
    	 fprintf(XML,"20041109"); /* THIS STILL HAS TO BE CHANGED!!!! */
    	 fprintf(XML,"T");
    	 /*fprintf(XML,Sr_date," hh,mm");*/
    	 fprintf(XML,"1332"); /* THIS STILL HAS TO BE CHANGED!!!! */
    	 fprintf(XML,"\" issue-time=\"");
    	 /*fprintf(XML,Sr_date," YYYY,MM,DD");*/
    	 fprintf(XML,"20041109"); /* THIS STILL HAS TO BE CHANGED!!!! */
    	 fprintf(XML,"T");
    	 /*fprintf(XML,Sr_date," hh,mm");*/
    	 fprintf(XML,"1332"); /* THIS STILL HAS TO BE CHANGED!!!! */
    	 fprintf(XML,"\">\n");
    
    /* above the header for xml file. Important that time and date are presented */
    /* in the ISO-format. Next to that some info on by whom the SATREP was issued*/
    /* The latter we can leave.. Its only for internal use by ZAMG, to outside world */
    
    /* ------------------------- Open Satrep file --------------------------------*/
    
        if ((STRPfile = fopen("SATREP.000", "r")) == NULL) {
            fprintf(stderr, "Error opening info-file :%s\n", "SATREP.000");
            exit(1);
        }
    
        for (idx = 0; idx <= 21; idx++) {
            fgets(InputBuffer, MAX_LINE, STRPfile);
        }
    
        while (fgets(InputBuffer, MAX_LINE, STRPfile)) {
        sscanf(InputBuffer,"%4s %[^:]: %2d%2d%c (%2d%2d%c - %2d%2d%c)", StartJunk, NameString, &X1, &Y1, &C1, &X2, &Y2, &C2, &X3, &Y3, &C3);
            printf( "Name='%s'\n", NameString );
    	fprintf(XML,"<cm type=\"");
    	fprintf(XML,"%s", NameString);
    	fprintf(XML,"\" lon=\"");
    	fprintf(XML,"%d",X1);
    	fprintf(XML,"\" lat=\"");
    	fprintf(XML,"%d",Y1);
    	fprintf(XML,"\" preslon=\"");
    	fprintf(XML,"%d",X1);
    	fprintf(XML,"\" preslat=\"");
    	fprintf(XML,"%d",Y1);
    	fprintf(XML,"\">\n");
    
            /* descriptions end with a blank line in the file */
    
    	INFO = (char *)malloc(MAX_INFO_LEN*sizeof(char));
    	sprintf(INFO,"\0");
    
    	while (!feof(STRPfile)  && InputBuffer[0] != '\n') {
    	fgets(InputBuffer, MAX_LINE, STRPfile);
    	strcpy(INFO,InputBuffer);		
    	/*printf( "Info='%s'\n", INFO );*/
    	fprintf(XML,"%s",INFO);
    	}
    	fprintf(XML,"</cm>\n");
        }
    	fprintf(XML,"</satrep>\n"); /* End of file, last XML stament */
        	fclose(STRPfile);
    	fclose(XML);
        return 0;
    }

  5. #20
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Code:
    while (!feof(STRPfile)  && InputBuffer[0] != '\n') {
    	fgets(InputBuffer, MAX_LINE, STRPfile);
    	strcpy(INFO,InputBuffer);		
    	/*printf( "Info='%s'\n", INFO );*/
    	fprintf(XML,"%s",INFO);
    	}
    You should change this. If your fgets fails here, you'll be trying to use data that doesn't exist. Remove the feof portion and replace it with the call to fgets, as both Salem and I have suggested on multiple occasions. (There's a reason we've both been saying to do it that way.)

    While you're at it, you may want to read FAQ entry on why using feof to control a loop is flawed.

    Quzah.
    Hope is the first step on the road to disappointment.

  6. #21
    Registered User
    Join Date
    Nov 2004
    Posts
    17
    K.. Thnx for the tip. Might wanna pass that URL over to my boss.. His programs are full of it

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Structuring a file for I/O
    By John.H in forum C Programming
    Replies: 2
    Last Post: 01-29-2003, 10:28 AM