Thread: A bit of a specific problem with reading a file and line

  1. #1
    Registered User
    Join Date
    Jun 2005
    Posts
    108

    Unhappy A bit of a specific problem with reading a file and line

    Hi,

    I posted the other day about a problem that i had regarding reading a header from a file and only taking out the words i need.

    The header of this file is a group of words divided up by ";" characters and i have managed to read the line perfectly.
    Now, these words are headers for the information below. Like a table of values.

    What my problem is that i have to read the headers, remember the position of the ones i want (they could be in any sequence and theres 20 of them out of 40 headers in total).

    finally, i want to use the "index" of the position of where they were found to identify where their information lies in the next line. The next lines are just floats seperated by ";" characters and thus have no identifiable marking.

    This is a sample of the input file:

    "RX_WEEK";"RX_TOM";"POS_TYPE";"SBAS_USED";"POS_FLA G";"NSV_USED";"NSV_LOCK";"MSK_USED";"MSK_LOCK";"NS _HPL";"NS_VPL";"NS_LAT";"NS_LON";"NS_ALT";"NS_DEW" ;"NS_DNS";"NS_DUP";"NS_DHOR";"NS_VE";"NS_VN";"NS_V U";"GPS_SEC";"NS_CLKBIAS";"NS_CLKDRIFT";"NS_X";"NS _Y";"NS_Z";"DOP_P";"DOP_G";"DOP_H";"DOP_V";"DOP_T" ;"RAIM_MODE";"RAIM_HPL";"RAIM_VPL";"NS_RES";"LOOP_ COUNT"
    the problem is that (its very simple to solve, i guess) that the program refuses to cycle through all the components.

    below is my attempt:

    Code:
    			FILE* fp = fopen(posfilename, "a+");
    
            {
    
    			char *Elements[] = {"\"RX_WEEK\"", "\"RX_TOM\"", "\"SBAS_USED\"", "\"POS_FLAG\"", "\"NSV_USED\"", "\"NS_HPL\"", "\"NS_VPL\"", "\"NS_LAT\"", "\"NS_LON\"", "\"NS_ALT\"", "\"NS_DEW\"", "\"NS_DNS\"", "\"NS_DUP\"", "\"NS_DHOR\"", "\"GPS_SEC\"", "\"NS_RES\""};  //these are the values we are looking for
    			char *TokenIndex[100];
    			char * Token;
    
    		
    
    		int k = 0;
    		if (fgets( posinputbuff, BUFSIZ, fp ) != NULL )  // get the first line of the file (header)
    			{	
    
    			printf ("Read line is %s \n\n", posinputbuff);	// print to see we have the right line
    			
    		for (int b = 0; b < 40; b++)						// to cycle through the whole header and get tokens
    				{
    				strcpy(copystring, posinputbuff);			// copy string to prevent strtok errors
    				Token = strtok (copystring, ";");			// take first value from the input header
    
    				printf ("This Token is %s \n", Token);		//print this token
    
    				for (i = 0; i < 20; i++) 
    					{
    
    					printf ("Element %i is %s \n\n", i,  Elements[i]);	// Print the value of the first element we are looking for
    				
    					if (strcmp(Token, Elements[i]) == '0')				// compare the token and elemnt to see if they match
    						{
    						index = i;										// if true then the first token is equal to the first element
    						TokenIndex[k] = Elements[index];				
    						printf ("Element %i in the final buffer is %s \n", index,  TokenIndex[k]);
    						k++;
    						break;										
    						}
    						break;											
    					}
    					break;												// break if to get next token
    				}
    				
    			}
    		}
    All help would be greatly appreciated, thanks

  2. #2
    Registered User
    Join Date
    Jan 2006
    Location
    Berkeley, Ca
    Posts
    195
    Maybe I didn't read this close enough. I suppose what isn't helping is that I'm still drunk from this morning. But couldn't you do something like

    Code:
    while(fgets(buff,sizeof(buff),fp) != NULL) 
            if( strchr(buff, ';') )
    Then store the values of the header in a structure.

    If anyone feels the need to ask "Who in their right mind has a structure of 40 values", I must say that you should see the sourcecode on netscape 4.0

    Besides, and I quote my computer.

    STRTOK(3) Linux Programmer's Manual STRTOK(3)



    NAME
    strtok, strtok_r - extract tokens from strings

    SYNOPSIS
    #include <string.h>

    char *strtok(char *s, const char *delim);

    char *strtok_r(char *s, const char *delim, char **ptrptr);

    DESCRIPTION
    A ?token' is a nonempty string of characters not occurring in the string delim, followed by \0 or by a character
    occurring in delim.

    The strtok() function can be used to parse the string s into tokens. The first call to strtok() should have s as
    its first argument. Subsequent calls should have the first argument set to NULL. Each call returns a pointer to
    the next token, or NULL when no more tokens are found.

    If a token ends with a delimiter, this delimiting character is overwritten with a \0 and a pointer to the next
    character is saved for the next call to strtok(). The delimiter string delim may be different for each call.

    The strtok_r() function is a reentrant version of the strtok() function, which instead of using its own static
    buffer, requires a pointer to a user allocated char*. This pointer, the ptrptr parameter, must be the same while
    parsing the same string.

    BUGS
    Never use these functions. If you do, note that:

    These functions modify their first argument.

    These functions cannot be used on constant strings.

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Discover the magic of line feeds in source code.

    300+ chars on a source line don't do anybody any good.

    I could do it myself, but I've had enough of reformatting other peoples post today
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Jan 2006
    Location
    Berkeley, Ca
    Posts
    195
    I have this nagging feeling the real source of the problem stems from the line of code

    Code:
    char *Elements[] = {"\"RX_WEEK\"", "\"RX_TOM\"", "\"SBAS_USED\"", "\"POS_FLAG\"", "\"NSV_USED\"", "\"NS_HPL\"", "\"NS_VPL\"", "\"NS_LAT\"", "\"NS_LON\"", "\"NS_ALT\"", "\"NS_DEW\"", "\"NS_DNS\"", "\"NS_DUP\"", "\"NS_DHOR\"", "\"GPS_SEC\"", "\"NS_RES\""};
    Salem, help me with my brain fart. But don't you use go something like

    Code:
    Elements+i; /* &Elements[i]*/
    and not
    Code:
    Elements[i];
    When accessing elements of a pointer to an array of pointer to chars
    Last edited by cdalten; 04-28-2006 at 07:36 AM.

  5. #5
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    This is a loop that will only execute the first iteration.
    Code:
    for ( i = 0; i < 20; i++ )
    {
       /* ... */
       break;
    }
    And if there are 16 elements, why loop through 20?

    There is a difference between '0' and 0.
    Code:
    if ( strcmp(Token, Elements[i]) == '0' )
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  6. #6
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    If you had taken my original suggestion, added a simple function to search for the desired strings, and made some very simple mods to it, it might look like this.
    Code:
    #include <stdio.h>
    #include <string.h>
    
    size_t find_element(const char *text)
    {
       static const char *Element[] =
       {
          "\"RX_WEEK\"", 
          "\"RX_TOM\"", 
          "\"SBAS_USED\"", 
          "\"POS_FLAG\"", 
          "\"NSV_USED\"", 
          "\"NS_HPL\"", 
          "\"NS_VPL\"", 
          "\"NS_LAT\"", 
          "\"NS_LON\"", 
          "\"NS_ALT\"", 
          "\"NS_DEW\"", 
          "\"NS_DNS\"", 
          "\"NS_DUP\"", 
          "\"NS_DHOR\"", 
          "\"GPS_SEC\"", 
          "\"NS_RES\""
       };
       size_t i;
       for ( i = 0; i < sizeof Element / sizeof *Element; ++i )
       {
          if ( strcmp(text, Element[i]) == 0 )
          {
             return i;
          }
       }
       return -1;
    }
    
    int main(void)
    {
       static const char filename[] = "file.txt"; /* the name of a file to open */
       FILE *file = fopen(filename, "r"); /* try to open the file */
       if ( file != NULL )
       {
          char line[BUFSIZ]; /* space to read a line into */
          /*
           * Create an array of strings: here each line may be broken up into up
           * to 20 strings of up to 32 characters. Try changing it to 10 to hit
           * the "no more room" message.
           */
          char data[40][32];
          while ( fgets(line, sizeof line, file) != NULL ) /* read each line */
          {
             size_t i = 0, size;
             char *token = line;
             fputs(line, stdout);
             for ( ;; )
             {
                size_t len = strcspn(token, ";\n"); /* search for delimiters */
                /*
                 * Use sprint to copy the text into a char array.
                 */
                sprintf(data[i], "%.*s", (int)len, token);
    
                token += len; /* advance pointer by the length of the found text */
                if ( *token == '\0' )
                {
                   break; /* advanced to the terminating null character */
                }
                ++token; /* skip the delimiter */
    
                /* advance the index into the string array */
                if ( ++i >= sizeof data / sizeof *data )
                {
                   puts("no more room");
                   break;
                }
             }
             /*
              * Display the results.
              */
             for ( size = i, i = 0; i < size; ++i )
             {
                size_t index = find_element(data[i]);
                if ( index != (size_t)-1 )
                {
                   printf("data[%d] = \"%s\"\n", (int)i, data[i]);
                }
             }
             puts("---");
          }
          fclose(file);
       }
       else
       {
          perror(filename); /* why didn't the file open? */
       }
       return 0;
    }
    
    /* my output
    <the line snipped for this post>
    data[0] = ""RX_WEEK""
    data[1] = ""RX_TOM""
    data[3] = ""SBAS_USED""
    data[4] = ""POS_FLAG""
    data[5] = ""NSV_USED""
    data[9] = ""NS_HPL""
    data[10] = ""NS_VPL""
    data[11] = ""NS_LAT""
    data[12] = ""NS_LON""
    data[13] = ""NS_ALT""
    data[14] = ""NS_DEW""
    data[15] = ""NS_DNS""
    data[16] = ""NS_DUP""
    data[17] = ""NS_DHOR""
    data[21] = ""GPS_SEC""
    data[35] = ""NS_RES""
    ---
    */
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  7. #7
    Registered User
    Join Date
    Jun 2005
    Posts
    108
    thanks dave and cdalten

    I made some changes so it doesnt have to cycle 20 times or even 17.

    It will keep doing it till it finds a set value in the elements array.

    i called it "EOF"
    and it seems to work fine.

    I need to make some changes at the end to stop it from crashing but it seems to be doing the right thing.

    thanks alot

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Reading a file line by line
    By Raskalnikov in forum C Programming
    Replies: 8
    Last Post: 03-18-2009, 11:44 PM
  2. Game Pointer Trouble?
    By Drahcir in forum C Programming
    Replies: 8
    Last Post: 02-04-2006, 02:53 AM
  3. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  4. simulate Grep command in Unix using C
    By laxmi in forum C Programming
    Replies: 6
    Last Post: 05-10-2002, 04:10 PM
  5. Greenhand want help!
    By leereg in forum C Programming
    Replies: 6
    Last Post: 01-29-2002, 06:04 AM