Thread: Skipping to a new line in an input file.

  1. #1
    Registered User
    Join Date
    May 2005
    Location
    Toronto, Canada
    Posts
    257

    Skipping to a new line in an input file.

    I'm not sure how this may be done.
    I've tried checking the FAQ, Getting a number or a string from the user, etc, can't quet figure it out.

    I know the exact format of the input file, and I want to read in the first 6 columns only. ie:
    Code:
    month  1    3  4  5    6     77   8   99 
    day       2   5  5  66   7    7     7   0
    I have a structture for the 1st 6 columns:
    Code:
    struct EDFSection
    {
    	char Param[20];
    	char Label[3], SFactor[4], SigBits[2];
    	int Bit30, Bit31;
    };
    I only want to fill the structure and then move on to the next row.
    desired output:
    Code:
    month  1    3  4  5    6     
    day       2   5  5  66   7
    It's a text input file.

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    1. Read in entire lines of data from the file into a buffer using the fgets function.
    2. Use the sscanf function to just parse the first six fields from the line you just read in.
    3. Repeat as necessary.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Registered User
    Join Date
    May 2005
    Location
    Toronto, Canada
    Posts
    257
    That was a good idea, why can't I think of things like this.
    However, I haven't been able to make it work perfectly.
    This is what I have:
    Code:
    for (j=0; j<nExpected; j++)
    	{
    		for (i=0; i<8; i++)
    		{
    			GetWord(inp, Temp[i]);
                SkipWS(inp);
    		}
    
    		strcpy(Sec.Param, Temp[0]);
    		Sec.Label = atoi(Temp[1]);
    		Sec.SFactor = atoi(Temp[2]);
    		Sec.SigBits = atoi(Temp[3]);
    		Sec.Bit31 = atoi(Temp[4]);
    		Sec.Bit30 = atoi(Temp[5]);
    		
    	}
    But given input:
    Code:
    late 1 2 3 4 5 6 7 
    busy 1 2 3 4 5 6 7 
    good 1 2 3 4 5  
    ugly 1 2 3 4 5
    It doesn't know not to stop reading at \n. I know I don't check for it, but I have to skip the whitespace after each entry to read the next. That's what SkipWS function is. GetWord scans a character at a time until isspace() is true.
    **Temp is a 2D array, array of strings.
    I can't figure out a better way to set up the logic here.

  4. #4
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Code:
    #include <stdio.h>
    
    struct EDFSection
    {
       char Param[20];
       int Label, SFactor, SigBits, Bit30, Bit31;
    };
    
    int main()
    {
       static const char filename[] = "file.txt";
       FILE *file = fopen(filename, "r");
       if ( file != NULL )
       {
          char line[80];
          while ( fgets(line, sizeof line, file) != NULL )
          {
             struct EDFSection Sec;
             if ( sscanf(line, "%s %d %d %d %d %d", Sec.Param, &Sec.Label,
                         &Sec.SFactor, &Sec.SigBits, &Sec.Bit30, &Sec.Bit31) == 6 )
             {
                printf("Sec.Param   = %s\n", Sec.Param);
                printf("Sec.Label   = %d\n", Sec.Label);
                printf("Sec.SFactor = %d\n", Sec.SFactor);
                printf("Sec.SigBits = %d\n", Sec.SigBits);
                printf("Sec.Bit30   = %d\n", Sec.Bit30);
                printf("Sec.Bit31   = %d\n", Sec.Bit31);
                putchar('\n');
             }
          }
          fclose(file);
       }
       return 0;
    }
    
    /* my output
    section.Param   = month
    section.Label   = 1
    section.SFactor = 3
    section.SigBits = 4
    section.Bit30   = 5
    section.Bit31   = 6
    
    section.Param   = day
    section.Label   = 2
    section.SFactor = 5
    section.SigBits = 5
    section.Bit30   = 66
    section.Bit31   = 7
    */
    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.*

  5. #5
    Registered User
    Join Date
    May 2005
    Location
    Toronto, Canada
    Posts
    257
    while ( fgets(line, sizeof line, file) != NULL )
    {
    struct EDFSection Sec;
    if ( sscanf(line, "%s %d %d %d %d %d", Sec.Param, &Sec.Label,
    &Sec.SFactor, &Sec.SigBits, &Sec.Bit30, &Sec.Bit31) == 6 )
    OK.
    would fgets return false or NULL if there aren't 80 chars available? I don't quet see that.
    and I would like the loop to stop at te end of the section marked by 'ENDL' and not copy the lines beginning with END.
    I tried
    Code:
    while ( fgets(line, sizeof line, inp) != NULL )
    	{
    		if (strncmp(line, "ENDL", 4))
    			break;
    
    		if (!strncmp(line, "END", 3))
    		{
    			if ( sscanf(line, "%s %d %d %d %d %d", Sec.Param, &Sec.Label,
                         &Sec.SFactor, &Sec.SigBits, &Sec.Bit30, &Sec.Bit31) == 6)
    			{
    				printf("Sec.Param   = %s\n", Sec.Param);
                    printf("Sec.Label   = %d\n", Sec.Label);
    but it doesn't like it.
    it exits the loop right away.

  6. #6
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Code:
          while ( fgets(line, sizeof line, file) != NULL )
          {
             struct EDFSection Sec;
             if ( strncmp(line, "ENDL", 4) == 0 )
             {
                break;
             }
             if ( strncmp(line, "END", 3) != 0 &&
                  sscanf(line, "%s %d %d %d %d %d", Sec.Param, &Sec.Label,
                         &Sec.SFactor, &Sec.SigBits, &Sec.Bit30, &Sec.Bit31) == 6 )
             {
                /* printing */
             }
          }
          fclose(file);
    http://www.rt.com/man/fgets.3.html
    Last edited by Dave_Sinkula; 06-14-2005 at 10:04 AM. Reason: Added link.
    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
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    but it doesn't like it.
    it exits the loop right away.
    Well of course it does, silly!
    Code:
    if (strncmp(line, "ENDL", 4))
    			break;
    Notice anything missing here?!


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

  8. #8
    Registered User
    Join Date
    May 2005
    Location
    Toronto, Canada
    Posts
    257

    Wink

    I thought
    Code:
    strncmp(line, "ENDL", 4)
    returns a 1 when the strings are the same. Never mind then.

    Instead of printing out the structure every time I scan it, I want to store then in an array of structures. So I'd pass the pointer to the array to a function that will read in all the individual structures. I don't really get how it is explained here:
    Code:
    struct Node *make_node ( void )
    {
      struct Node new_node = malloc ( sizeof *new_node );
    
      /* Error check and set a default state */
    
      return new_node;
    }
    That's from Prelude's FAQ again.

    I did it like it makes sense to me:
    Code:
    int 
    main (void)
    {
    	int i, j, nExpected, nActual=0;
    	char Word[25]; 
    	FILE* inp;
    	struct EDFLine *Sec;
    ..........................
    Sec = calloc(nExpected, sizeof (struct EDFLine));
    
    	ReadSection(inp, Sec, nExpected, &nActual);
    }
    
    int ReadSection(FILE * inp, struct EDFLine Sec[], int nExpected, int*nActual)
    {
    	char line[80];
    	int  i=0;
    
    	while ( fgets(line, sizeof line, inp) != NULL )
    	{
    		if ( strncmp(line, "ENDL", 4) == 0 )
    		{
                break;
             }
    
    		if (strncmp(line, "END", 3) != 0)
    		{
    			if ( sscanf(line, "%s %d %d %d %d %d", Sec[i].Param, &Sec[i].Label,
                         &Sec[i].SFactor, &Sec[i].SigBits, &Sec[i].Bit30, &Sec[i].Bit31) == 6)
    			{
    				nActual ++;
    				i++;
    			}
    		}
    		
    	}
    
    	if (*nActual == nExpected)
    		return 1;
    	else 
    		return 0;
    }
    Right now it exits the loop right away, again.

    Oh, and you guys told me numerously before not to typecast the calloc and never worked for me before. It kept giving me an incompatibility error, but now it worked.....
    Last edited by earth_angel; 06-14-2005 at 11:27 AM.

  9. #9
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Oh, and you guys told me numerously before not to typecast the calloc and never worked for me before. It kept giving me an incompatibility error,
    That's because you were compiling as C++ instead of C.


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

  10. #10
    Registered User
    Join Date
    May 2005
    Location
    Toronto, Canada
    Posts
    257
    That's because you were compiling as C++ instead of C.
    I tried even as C. But I guess there were other problems.

  11. #11
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by earth_angel
    Instead of printing out the structure every time I scan it, I want to store then in an array of structures.
    How about something along this line?
    Code:
    size_t EDFread(const char *filename, struct EDFSection Sec[], size_t size)
    {
       size_t i = 0;
       FILE *file = fopen(filename, "r");
       if ( file != NULL )
       {
          char line[80];
          while ( fgets(line, sizeof line, file) != NULL )
          {
             static const char stop[] = "ENDL", ignore[] = "END";
             if ( strncmp(line, stop, sizeof stop - 1) == 0 )
             {
                break;
             }
             if ( strncmp(line, ignore, sizeof ignore - 1) != 0 &&
                  sscanf(line, "%s %d %d %d %d %d", Sec[i].Param,
                         &Sec[i].Label, &Sec[i].SFactor, &Sec[i].SigBits,
                         &Sec[i].Bit30, &Sec[i].Bit31) == 6 )
             {
                if ( ++i >= size )
                {
                   break;
                }
             }
          }
          fclose(file);
       }
       return i;
    }
    
    int main()
    {
       struct EDFSection section[10];
       size_t size = EDFread("file.txt", section, sizeof section / sizeof *section);
       /* ... */
       return 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.*

  12. #12
    Registered User
    Join Date
    May 2005
    Location
    Toronto, Canada
    Posts
    257
    struct EDFSection section[10];
    That works, but the size of the array is not always 10. I have to dynamically allocate memory. So I end up passing to the function a pointer to an array of structures dynamically allocated. That's where the problems begin. I'm not sure how to arrange that.

    What is size_t?
    Last edited by earth_angel; 06-14-2005 at 12:52 PM.

  13. #13
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by earth_angel
    That works, but the size of the array is not always 10. I have to dynamically allocate memory. So I end up passing to the function a pointer to an array of structures dynamically allocated. That's where the problems begin. I'm not sure how to arrange that.
    Code:
    int main()
    {
       size_t size = 10;
       struct EDFSection *section = malloc(size * sizeof *section);
       if ( section )
       {
          size_t count = EDFread("file.txt", section, size);
          /* ... */
          free(section);
       }
       return 0;
    }
    Quote Originally Posted by earth_angel
    What is size_t?
    An unsigned integral type suited for array indexing.
    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.*

  14. #14
    Registered User
    Join Date
    May 2005
    Location
    Toronto, Canada
    Posts
    257
    Code:
    int ReadSection(FILE * inp, struct EDFLine Sec[], int nExpected)
    {
    .............................
    
    if ( sscanf(line, "%s %d %d %d %d %d", Sec[i].Param, &Sec[i].Label,
                         &Sec[i].SFactor, &Sec[i].SigBits, &Sec[i].Bit30, &Sec[i].Bit31) == 6)
    			{
    				if ( ++i >= nExpected )
    				{
    					break;
    				}
    
    			}
    		}
    		print_Struct(Sec[i]);
    		printf("\n\n");
    
    ............................
    in the main then:
    Code:
    int 
    main (void)
    {
    	int i, j, nExpected, nActual=0;
    	char Word[25]; 
    	FILE* inp;
    	struct EDFLine *Sec;
    
    ................
    
    nExpected = atoi(Word);   // Number of parameters expected
    
    	SkipWS(inp);
    
    	Sec = malloc(nExpected * sizeof *Sec);
    
    	if (Sec)
    	{
    		nActual = ReadSection(inp, Sec, nExpected);
    		free(Sec);
    	}
    
    ..............
    It's a bit different from yours Dave. It goes through the loop, but when I try to print the contects of Sec[i], I get gibrish.
    Is the pointer refference wrong?

  15. #15
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Print the structure after a line is successfully read and before you increment the index.
    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.*

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need Help Fixing My C Program. Deals with File I/O
    By Matus in forum C Programming
    Replies: 7
    Last Post: 04-29-2008, 07:51 PM
  2. help again with scrolling without wrapping
    By Dukefrukem in forum C Programming
    Replies: 8
    Last Post: 09-21-2007, 12:48 PM
  3. Unknown Memory Leak in Init() Function
    By CodeHacker in forum Windows Programming
    Replies: 3
    Last Post: 07-09-2004, 09:54 AM
  4. Contest Results - May 27, 2002
    By ygfperson in forum A Brief History of Cprogramming.com
    Replies: 18
    Last Post: 06-18-2002, 01:27 PM