I wanted to learn how to work with file I/O properly so i've found an assignment in my college papers and decided to write it. So here it is. //Write a C program which reads data about books and inputs them into a file named books.txt, like this: // //book_name#author_name#page_num#code#is_lent# // //book_name is an array of a maximum of 50 characters, author_name is an array of a maximum of 50 characters, //page_num is an integer, code is an integer, is_lent is an integer of interval [0, 1] where 1 //means that the book is lent, and 0 that it isn't. //Program creates a new file if it exists or opens an existing one and appends new //data on the end. Input ends when the book name is 'x'. //Print the contents of the file. #include <stdio.h> #include <stdlib.h> #include <string.h> /* Function prototypes */ void buff_clr( void ); void write_to_file( FILE *fp ); void read_from_file( FILE *fp ); void remove_newline( char *string ); int main() { FILE *fp; fp = fopen( "Books.txt" , "a+" ); if( fp == NULL ) { fprintf( stderr , "Error opening file" ); exit( 1 ); } write_to_file( fp ); read_from_file( fp ); fclose( fp ); return 0; } /* Removes newline from strings caused by fgets() */ void remove_newline(char *string) { char *ptr; if ( ( ptr = strchr( string , '\n' ) ) != NULL ) *ptr = '\0'; } /* Picks up left over characters from the buffer in case there are any */ void buff_clr(void) { char garbage; do { garbage = getchar(); }while( garbage != '\n' ); } /* Requests input and writes it to file */ void write_to_file( FILE *fp ) { struct book_s { char book_title[50]; char author_name[50]; unsigned int page_num; unsigned int code; unsigned int is_lent; }book; while(1) { /* Data input into struct */ printf( "Book title: " ); fgets( book.book_title , 50 , stdin ); remove_newline(book.book_title); if( strcmp( book.book_title , "x") == 0 ) { break; } printf( "Name of the author: "); fgets( book.author_name , 50 , stdin ); remove_newline(book.author_name); printf( "Number of pages: " ); scanf( "%d" , &book.page_num ); printf( "Book code: " ); scanf( "%d" , &book.code ); do { printf( "Is book lent(1 = yes , 0 = no):" ); scanf( "%d" , &book.is_lent ); }while(book.is_lent > 1); /* Data input into file */ fprintf( fp , "%s#%s#%d#%d#%d#\n", book.book_title , book.author_name , book.page_num , book.code , book.is_lent ); printf( "\n\n" ); buff_clr(); //Using this here because without it a '\n' sneaks into book title on next iteration for some reason } } /* Reads the file we've just written to */ void read_from_file( FILE *fp ) { struct book_s { char book_title[50]; char author_name[50]; char page_num[5]; char code[20]; char is_lent[1]; }book; char line[BUFSIZ]; //Rewind to start of file fseek(fp, 0, SEEK_SET); while( fgets( line , sizeof(line) , fp ) != NULL ) { strcpy( book.book_title , strtok( line , "#" ) ); strcpy( book.author_name , strtok( NULL , "#" ) ); strcpy( book.page_num , strtok( NULL , "#" ) ); strcpy( book.code , strtok( NULL , "#" ) ); strcpy( book.is_lent , strtok( NULL , "#" ) ); printf( "\nBook title: %s", book.book_title ); printf( "\nName of the author: %s", book.author_name ); printf( "\nPage num: %s", book.page_num ); printf( "\nBook code: %s", book.code ); printf( "\nIs book lent: %s", book.is_lent ); printf( "\n\n" ); } } Now this all works within the confines of the assigment. But what i am wondering is is my code too long? Could this have been written any shorter? Could this have been written any better? Did i miss anything? Are there any mistakes? A few things to note. I know i don't really need structs but i had an idea of using them to create arrays of data and then print them one by one but i decided to scrap that idea since the only thing i'd accomplish is more lines of code and more memory wasted, but i liked the look of the struct so i kept it. Oh and is there a way i could read all the data in their rightful forms without having to read them all as a string and then parse them and then convert them (i didn't convert integers here since i didn't really need to)? I know i can't use fscanf which would read strings until the whitespace character so it would try to gobble the whole line up since there aren't any. Also what if i had to read multiple lines of varying lengths and file types? for example if instead of `book_name#author_name#page_num#code#is_lent#` being all one line what if it was `book_name#page_num#` `author_name#code#is_lent#` What would be the ways of reading such input?