Thread: file writing and reading

  1. #1
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715

    file writing and reading

    Hi guys I need help
    I'm writing a simple program than asks user to entere string and then write this to a file
    I'm using functions for both write and read:
    For writing to a file:
    Code:
    void Write(char string[])
    {
    
    if((fp=fopen("Test.bin","a+b"))==NULL) exit(1);
    fwrite(string,sizeof(char),strlen(string)+1,fp);
    fclose(fp);
    }
    fp is a global file pointer so it is working. Each time program is executed new string is added to a file.
    Problem raises when attempt to read.
    function for reading:
    Code:
    char * Read(void)
    {	
    	
    	if((fp=fopen("Test.bin","rb"))==NULL) exit(1);	
    	
    	
    	char*  novi=(char *)malloc(sizeof(char)*500);
    	char *str;
    	
    	
    	fread(novi,sizeof(char),500,fp);
    	
    	fclose(fp);
    	return novi;
    }
    Every time only first string is returned. I understand what is happening. I allocate 500
    elements of char assuming I don't know how much is enetered. Character '\0' is also written
    and when I use puts(string) //string=Read(); in main() only first string is displayed.
    How can I solve this problem. In geereal case how to read files taht contains strings variable size. Do I have to track length when writing and then to pass it in Read or...?
    And what if I write to a file other data types such as integer? or maybe it is better to use structures then? Questions, question oooooooooohhh
    Help me please!

  2. #2
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >In geereal case how to read files taht contains strings variable size.
    Don't use fread and fwrite for variable length memory blocks unless you have some way to find out what the size of the next block is. Since you are working with strings, just open the file as text and use fgets/fputs or something equally suitable. That way you can have a good definition of what a line is and the variable length problem is only a problem with the size of the array that you put the string in.
    My best code is written with the delete key.

  3. #3
    Been here, done that.
    Join Date
    May 2003
    Posts
    1,164
    Also, your read function will
    Code:
    open 
    read first line (open always starts at the first line)
    close
    return
    where do you read the 2nd string?

    If each of your functions completely encompases the file open thru close, there is no reason to make the file pointer a global. Declare it in each function.

    By creating a buffer in the read function using malloc, you have an excellent change of memory leaks if you aren't extremely careful.
    Definition: Politics -- Latin, from
    poly meaning many and
    tics meaning blood sucking parasites
    -- Tom Smothers

  4. #4
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    That's ok with text file but I want to solve this with binary files and this program is working but if someone have a better solution welcome:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <iostream.h>
    #include <string.h>
    
    FILE *fp;
    void Write(char []);
    void Read(void);
    void main(void){
    
    char string[BUFSIZ];
    
    cout<<"Unesite string:";
    cin.getline(string,BUFSIZ,'\n');;
    
    	Write(string);
    	
    
    	Read();
    
    
    }
    void Write(char string[])
    {
    
    	if((fp=fopen("podaci.bin","a+b"))==NULL) //do something
    	fwrite(string,sizeof(char),strlen(string)+1,fp);
    	fclose(fp);
    }
    void Read(void)
    {	
    	unsigned long kraj;
    	char tmp[500];
    	if((fp=fopen("podaci.bin","rb"))==NULL) //do something	
    	fseek(fp,0L,SEEK_END);
    	kraj=ftell(fp);
    	fseek(fp,0L,SEEK_SET);
    
    	char*  novi=(char *)malloc(sizeof(char)*kraj/sizeof(char));
    	
    	fread(novi,sizeof(char),kraj/sizeof(char),fp);	
    
    	for(int i=0,j=0;(unsigned)i<kraj/sizeof(char);i++,j++){
    		tmp[j]=novi[i];
    		if(novi[i]=='\0')
    		{
    			puts(tmp);
    			j=-1;
    		}
    	}
    	free(novi);
    	fclose(fp);
    }

  5. #5
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    cout<<"Unesite string:";
    cin.getline(string,BUFSIZ,'\n');;
    This is C++ code and as such should be asked there.

  6. #6
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    You right, of course I can use printf and gets(), but what about the main question here? Is there an efficient way than that I used. So simply ignore cout and imagine that there are printf and gets

  7. #7
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >but if someone have a better solution welcome
    Read can be made to be more efficient, but I'm sure you can figure that one out without too much trouble. Hint: Remove malloc and free for every line, but still allow for variable length strings.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <assert.h>
    
    void Write ( const char *string, FILE *fp );
    void Read ( FILE *fp );
    
    int main ( void )
    {
      FILE *fp;
    
      fp = fopen ( "input.txt", "w+b" );
      if ( fp == NULL ) {
        perror ( NULL );
        return EXIT_FAILURE;
      }
      Write ( "this is a test", fp );
      Write ( "another test", fp );
      Write ( "different length strings", fp );
      rewind ( fp );
      Read ( fp );
      fclose ( fp );
    
      return EXIT_SUCCESS;
    }
    
    void Write ( const char *string, FILE *fp )
    {
      size_t len;
    
      assert ( string != NULL );
      assert ( fp != NULL );
      len = strlen ( string ) + 1;
      fwrite ( &len, sizeof len, 1, fp );
      fwrite ( string, len, 1, fp );
    }
    
    void Read ( FILE *fp )
    {
      size_t len;
    
      assert ( fp != NULL );
      while ( fread ( &len, sizeof len, 1, fp ) == 1 ) {
        char *string = malloc ( len );
        if ( string == NULL ) {
          fprintf ( stderr, "Fatal error\n" );
          return;
        }
        fread ( string, len, 1, fp );
        puts ( string );
        free ( string );
      }
    }
    >So simply ignore cout and imagine that there are printf and gets
    We would still call you on it. gets is a Bad Thing most of the time. fgets should be used instead.
    My best code is written with the delete key.

  8. #8
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    Thanks man, but I have a little question. I don't know how to use assert. I heard that is for debug but not sure. What this function do in this code?

  9. #9
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    >I don't know how to use assert. I heard that is for debug but not sure.

    Here is an article or two.
    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. segmetation fault (reading and writing file in c)
    By tasosa in forum C Programming
    Replies: 5
    Last Post: 04-13-2009, 06:04 AM
  2. Replies: 3
    Last Post: 03-05-2009, 03:14 AM
  3. Reading out of and writing into the same file
    By Wiretron in forum C Programming
    Replies: 8
    Last Post: 12-30-2006, 02:04 PM
  4. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  5. what does this mean to you?
    By pkananen in forum C++ Programming
    Replies: 8
    Last Post: 02-04-2002, 03:58 PM