reading a file line by line and char *

This is a discussion on reading a file line by line and char * within the C Programming forums, part of the General Programming Boards category; Hi i have a chicken and egg problem. I want to read a file line by line into a char ...

  1. #1
    Registered User
    Join Date
    Apr 2005
    Posts
    28

    reading a file line by line and char *

    Hi i have a chicken and egg problem. I want to read a file line by line into a char *, let's say str. In order to malloc str I need to know the length of the line which I cannot have unless I read it... The only way I can see is reading character by character till \n character encountered and realloc str in every character. But it seems to me that this quite inefficient and I was thinking of using fgets instead.

    Any clues on that?

    Cheers.
    Last edited by odysseus.lost; 05-28-2005 at 05:35 AM.

  2. #2
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,531
    Use fgets() to read a line into a buffer
    Use strlen() to work out the length
    Use malloc() to allocate enough space for that line
    Use strcpy() to copy from the buffer to the allocated space
    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.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  3. #3
    FOX
    Join Date
    May 2005
    Posts
    188
    But what if the buffer fgets uses is smaller than the line? Won't that cause the remaining characters on the line to stay in the input queue, and thus screw up the next line?

  4. #4
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,531
    Depends how you want to deal with long lines.
    It's easy enough to test if there is a \n in the buffer returned by fgets(). If there isn't a newline, then you make some kind of note to append to the current buffer (following reallocation) rather than allocating a new buffer.
    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.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  5. #5
    Registered User
    Join Date
    Apr 2005
    Posts
    28
    Quote Originally Posted by Salem
    Depends how you want to deal with long lines.
    It's easy enough to test if there is a \n in the buffer returned by fgets(). If there isn't a newline, then you make some kind of note to append to the current buffer (following reallocation) rather than allocating a new buffer.
    so basically you mean:
    Use fgets() to read a line into a buffer
    Use strlen() to work out the length
    Use malloc() to allocate enough space for that line
    Use strcpy() to copy from the buffer to the allocated space
    If (or better while) buffer does not end with \n fgets() the rest of the line
    Use strlen() to work out the length
    Use realloc(previous size + size of buffer) to allocate enough space for the line
    Use strcat to concatenate the rest of the line

    Cheers

  6. #6
    Registered User
    Join Date
    Jun 2004
    Posts
    201
    If you use a posix compatible compiler, you can also use stat() to get the filesize, allocate the buffer and read it in with fread at once.


    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/stat.h>
    
    static void readfile(FILE *fp, size_t size);
    
    int main(int argc, char **argv)
    {
    	struct stat st;
    
    	FILE *fp = fopen(__FILE__, "rb");
    
    	if (fp != NULL && fstat(fileno(fp), &st) == 0)
    	{
    		readfile(fp, st.st_size);
    	}
    
    	if (fp != NULL)
    		fclose(fp);
    
    	return 0;
    }
    
    void readfile(FILE *fp, size_t size)
    {
    	char *ptr = malloc(size+1);
    
    	if (ptr != NULL)
    	{
    		ptr[size] = '\0';
    		if (fread(ptr, size, 1, fp) == 1)
    		{
    			puts(ptr);
    		}
    
    		free(ptr);
    	}
    }

  7. #7
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,046
    Here's another way to determine the file length (ANSII I think):

    Instead of stat(), you can use this code:

    Code:
    FILE *fp;
    long filesize;
    
    /* open fp */
    fp = fopen("filename.ext", "rb");
    
    fseek(fp, 0, SEEK_END);
    filesize = ftell(fp);
    rewind(fp);  /* set the file pointer back to the beginning */
    This code sets the file pointer to the end of the file with the call to fseek(). ftell() tells the position of the file pointer (it's a long). And finally, rewind(fp) rewinds the file pointer so you can do other things to it later.

    I hope this helps.

    dwk

  8. #8
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,006
    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.*

  9. #9
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,046
    That's why I opened the file for binary.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C++ ini file reader problems
    By guitarist809 in forum C++ Programming
    Replies: 7
    Last Post: 09-04-2008, 06:02 AM
  2. Code review
    By Elysia in forum C++ Programming
    Replies: 71
    Last Post: 05-13-2008, 09:42 PM
  3. Game Pointer Trouble?
    By Drahcir in forum C Programming
    Replies: 8
    Last Post: 02-04-2006, 01:53 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
  5. simulate Grep command in Unix using C
    By laxmi in forum C Programming
    Replies: 6
    Last Post: 05-10-2002, 04:10 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21