Thread: Turbo C Structures and Writing to file help

  1. #1
    Registered User
    Join Date
    Aug 2009
    Posts
    11

    Post Turbo C Structures and Writing to file help

    Hey everyone, I'm basically very new at this and I need to finish a program to finish my C programming course. My main problem is when writing to a file the information of a structure. It works fine, it writes to the file but it terminates the program as soon as the function ends, and it's not supposed to do that. I've been trying to debug for 2 hours now, and still nothing... Can anyone show me some examples of 'fread' and 'fwrite' in use? I don't want to paste my entire current program because it's quite long, but here's the function that I'm having trouble with:

    Code:
    void f_add_student(void)
    {
     int lv_id;
     student_rec s_students;
     char lv_continue;
     int lv_cancel;
     clrscr();
     if((file_student_rec=fopen(c_student_rec,"rb+"))==NULL)
      {
       f_dialog_border();
       gotoxy(13,24);
       printf("First student addition, a file will be created to store your");
       gotoxy(37,27);
       printf("information.");
       getch();
       s_students.id=1;
       clrscr();
       file_student_rec=fopen(c_student_rec,"a+");
      }
     else
      {
       do{
        lv_id=s_students.id;
        fread(&s_students,sizeof(s_students),1,file_student_rec);
       }while(!feof(file_student_rec));
       s_students.id=lv_id+1;
      }
     f_clear_variable(s_students.fname);
     f_clear_variable(s_students.lname);
     f_clear_variable(s_students.address);
     f_clear_variable(s_students.phone);
     s_students.age=0;
     s_students.gender=0x00;
     do{
      clrscr();
      gotoxy(36,14);
      printf("Add Student");
      gotoxy(15,17);
      printf("ID: %05i",s_students.id);
      gotoxy(15,19);
      printf("First Name:");
      gotoxy(15,21);
      printf("Last Name:");
      gotoxy(15,23);
      printf("Address:");
      gotoxy(15,25);
      printf("Age:");
      gotoxy(15,27);
      printf("Gender:");
      gotoxy(15,29);
      printf("Phone Number:");
      f_main_border();
      fflush(stdin);
      gotoxy(28,19);
      gets(s_students.fname);
      gotoxy(27,21);
      gets(s_students.lname);
      gotoxy(24,23);
      gets(s_students.address);
      gotoxy(20,25);
      scanf("%i",&s_students.age);
      fflush(stdin);
      gotoxy(23,27);
      scanf("%c",&s_students.gender);
      fflush(stdin);
      gotoxy(30,29);
      gets(s_students.phone);
      f_dialog_border();
      printf("Are you sure you want to add this student to student records[y/n]?");
      scanf("%c",&lv_continue);
      fflush(stdin);
      if(lv_continue=='n' || lv_continue=='N')
       lv_cancel=1;
      else
       lv_cancel=0;
     }while(lv_cancel==1);
     s_students.s_grades.History=0;
     s_students.s_grades.Geography=0;
     s_students.s_grades.Math=0;
     s_students.s_grades.English=0;
     s_students.s_grades.Humanities=0;
     s_students.s_grades.Science=0;
     s_students.s_grades.Art=0;
     s_students.s_grades.PE=0;
     fwrite(&s_students,sizeof(s_students),1,file_student_rec);
     fclose(file_student_rec);
    }
    Last edited by PHGDAL; 08-02-2009 at 01:42 PM. Reason: Forgot the code tags...

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    fflush(stdin) will result in undefined behavior:

    Quote Originally Posted by C Draft Standard 2005
    If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined.
    This is a common misuse of fflush(). Get rid of it.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User
    Join Date
    Aug 2009
    Posts
    11
    How do I clear the input stream without fflush(stdin)?

  4. #4
    Registered User GL.Sam's Avatar
    Join Date
    Aug 2009
    Posts
    88
    Omg, it looks horrible. First off, you definetely should get rid of unneeded gotoxy() instances. It is non-standard C, there are plenty possibilities of using escape sequences instead, but the main reason is darn uglyness.

    >How do I clear the input stream without fflush(stdin)?

    The general example goes like this:
    Code:
    while (getchar() != '\n')
      continue;
    Also,
    Code:
    fread(&s_students,sizeof(s_students),1,file_student_rec);
    fwrite(&s_students,sizeof(s_students),1,file_student_rec);
    should be
    Code:
    fread(&s_students,sizeof(student_rec),1,file_student_rec);
    fwrite(&s_students,sizeof(student_rec),1,file_student_rec);
    Last edited by GL.Sam; 08-02-2009 at 02:42 PM.

  5. #5
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by PHGDAL View Post
    How do I clear the input stream without fflush(stdin)?
    This is actually the 2nd time this has come up today. You may want to read this thread from yesturday for more info:

    fgetchar() doesnt work
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  6. #6
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    First piece of advice I have is get MSVS Express 2008 and dump Turbo C. MSVS can compile C or C++ or both and.

  7. #7
    Registered User
    Join Date
    Aug 2009
    Posts
    11
    Thanks everyone, I'll give it a try. Unfortunately I can't use any other program, my course demands that I use turbo C for this project otherwise I don't pass. For the gotoxy() bits it's to get the writing inside the borders I drew with a different function. I don't know any other way to do it...

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Ask your tutor why they insist on using a compiler which is older than the students, and is obsolete both as a compiler and the OS it was intended to run on.

    Who is paying for your course, and will your qualification be worth anything in the real world where NOBODY else uses that fossil?
    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.

  9. #9
    Registered User
    Join Date
    Aug 2009
    Posts
    11
    I thought the same thing too. But it's really only a simple 24-hour long course (3 hours a day, 2 days a week) just so I can get the basics of the language. I'll probably take a more useful course on C++ or C# later.

  10. #10
    DESTINY BEN10's Avatar
    Join Date
    Jul 2008
    Location
    in front of my computer
    Posts
    804
    Quote Originally Posted by Salem View Post
    Ask your tutor why they insist on using a compiler which is older than the students, and is obsolete both as a compiler and the OS it was intended to run on.

    Who is paying for your course, and will your qualification be worth anything in the real world where NOBODY else uses that fossil?
    There are a lot of universities who still teach C using TC, and you can't say anything to them like "Why are you using this fossil" coz it's going on for long and nobody cares what you say? So, IMO, the OP should run the code on TC and on any modern compiler for the sake of his/her understanding.
    HOPE YOU UNDERSTAND.......

    By associating with wise people you will become wise yourself
    It's fine to celebrate success but it is more important to heed the lessons of failure
    We've got to put a lot of money into changing behavior


    PC specifications- 512MB RAM, Windows XP sp3, 2.79 GHz pentium D.
    IDE- Microsoft Visual Studio 2008 Express Edition

  11. #11
    Registered User
    Join Date
    Aug 2009
    Posts
    11
    Ok, I changed all the fflush(stdin)'s to getchar()!='\n' and I also changed

    Code:
    fread(&s_students,sizeof(s_students),1,file_student_rec);
    fwrite(&s_students,sizeof(s_students),1,file_student_rec);
    to
    Code:
    fread(&s_students,sizeof(student_rec),1,file_student_rec);
    fwrite(&s_students,sizeof(student_rec),1,file_student_rec);
    but the problem is still there, the program exits after ending the function instead of returning to the last function. I attached the *.cpp file of the whole program just in case it helps. Thanks everyone in advance!

  12. #12
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Okay, I don't have windows installed so I cannot test this code, but I looked at it for a while and here's a preliminary observation: You use a flag, "lv_choice", quite a few times, in void() functions with a switch in a while loop to "end" the function:
    Code:
      }while(lv_choice==0);   //End of while loop.
    }
    You can return from a void function. In other words, rather than doing all that with the lv_choice flag, in the cases where you set the flag:
    Code:
        case 5:              //Logout.
        {
        f_logout();
        lv_choice=1;
        break;
        }
    You should just replace "break" with "return", change the loop to an infinite one:
    Code:
    while (1) {
           [...code...]
    }
    and remove all references to lv_choice. This will
    1. simplify the code
    2. reduce the usage of memory by eliminating a superfluous variable
    3. improve efficiency by removing a number of superfluous operations

    Those last two are sort of minor, on this scale, but they are indicative of how you should be thinking about programming; the first one is significant here IMO, because it amounts to a lot of clutter. In any case, these two perogatives (simplifying where ever possible, and streamlining the actual functionality of the process) go hand in hand.

    Also, using a tabstop of at least two characters would be nice.

    As for your problem, here is a strong possibility (again, I can't test this because of conio.h): it has to do with flushing the input buffer again. Did you read the thread I pointed you to to do with how '\n' gets left in the input buffer by scanf if you use %d %i or %c?

    Let's look at the flow of execution with that in mind. You believe f_add_student() is to blame. f_add_student gets called here, in f_student_options():
    Code:
      scanf("%i",&lv_choice);
      switch(lv_choice)
       {
        case 1:                        //Add Student.
         f_add_student();
         lv_choice=0;
         break;
    Notice, before you even begin, there is an '\n' left in the buffer. This will not get picked up by a %d or %i but it will get into a %c. That will get taken care of by your "while(getchar()!='\n')", altho these all have a strange form:
    Code:
      while(getchar()!='\n')
          s_students.gender;
    This loop does not need to perform an operation, altho "s_students.gender" is a meaningless no-op anyway. It should just be:
    Code:
    while(getchar()!='\n');
    This will repeat the call in the condition as long as the condition is met, which is all you want. However, I still think this is a better, less confusing way to deal with the '\n':
    Code:
    scanf("%i%*c",&s_students.age);
    which is explained in that thread I pointed you to earlier. You're free to think about that. It sort of short cuts verifying the input, but you are not performing any verification anyway (you presume the user did not accidently go "asdf\n") and that is fine for now.

    In any case, I think your problem is here:
    Code:
      printf("Are you sure you want to add this student to student records[y/n]?");
      scanf("%c",&lv_continue);
      if(lv_continue=='n' || lv_continue=='N')
       lv_cancel=1;
      else
       lv_cancel=0;
     }while(lv_cancel==1);
    You have that one last scanf("%c") call, with no flushing of the buffer, right before you return to f_student_options
    Code:
      f_add_student();
      lv_choice=0;
    where supposedly lv_choice is set to zero. Except you still have a '\n' in the buffer, so when the f_student_options() loop repeats (too fast to see), you may trigger this
    Code:
      printf("Input:");
      f_main_border();
      gotoxy(23,29);
      scanf("%i",&lv_choice);
    
      switch(lv_choice)
    In the wrong way. Kind of unlikely, but worth considering.

    Partial moral: Everytime you add a variable, you are adding a complication. Unnecessary complications contribute to -- unnecessary complications....


    But my final and most serious criticism is this: you should not have written this with all the conio stuff in initially. First, you should have gotten everything to work in the most simple way; when the essential structure of the program can be demonstrated to work, then you add all the fancy interface stuff. One major advantage to that would be you would then know if the error was actually part of the program flow, or taking place in one of the subroutines and procedures that add the cosmetics. On this scale, with a project like this, there is no excuse for not verifying EVERYTHING works the way you think it should every ten or so lines at most. I suspect you wrote a lot more than that all at once figuring the error checking capacity of the compiler could solve your typos and stuff at the end. And/or: that you were more pre-occupied with making the conio output correct than with the real "engine" of the code. If that is the case, never do it again!
    Last edited by MK27; 08-03-2009 at 02:28 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  13. #13
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    I will substitute the letter 'z' for p, since my keyboard has just now lost a few keys!

    I believe the zroblem is with fread (which is correct for binary mode), and feof(), which is designed for text mode.

    At the end of file, fread() will return a short count of items, (in your case, a zero), but feof() will return a non-zero (usually a -1), on end of file.

    So change your feof(), (rezlace it), with simzly while(fread, etc., and the file zroblem may disazzear. Like this:

    Code:
        //fread(&s_students,sizeof(student_rec),1,file_student_rec); <=original line
      }while(fread(&s_students,sizeof(student_rec),1,file_student_rec)); //new line of code
    //   }while(!feof(file_student_rec)); <=original line

    BTW, I use Turbo C/C++ 1.01, a great deal, and the criticism it's received here are both valid, and utter craz. It is horribly out of date, *but* it is simzle to set uz, and have the students szend a minimum of time learning the IDE, and a maximum of time learning C.

    Don't use it for CZZ, however. That language has changed a great deal since Turbo C/C++.

    The function gotoxy(), is very useful (although you've overdone it a bit), and Windows itself has taken it on with the function SetConsoleCursorZosition(). As you zrobably know, anyone using conio.h (like Turbo C), can code basic console diszlays, *way* easier comzared to using the Windows functions.

    fflush(stdin), will never stop a Turbo C program from running - it doesn't always work as it should, but in Turbo C, it doesn't cause a program to quit. Other compilers may be quite different, of course.

    Edit: BTW, your program assumes my console window has 45 lines (which it doesn't have), so it tears up my display something fierce. You have *plenty* of room on a 25 line display for a simple menu, etc.

    I'm not being judgmental here - I did the same thing with a game a couzle years back - and zromztly got feed back that nobody could zlay it because it requires 45 lines of console diszlay to see it all - and they didn't have it. < eek! >
    Last edited by Adak; 08-03-2009 at 02:32 AM.

  14. #14
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Well, hopefully Adak has the real answer there.

    Quote Originally Posted by Adak View Post
    fflush(stdin), will never stop a Turbo C program from running - it doesn't always work as it should, but in Turbo C, it doesn't cause a program to quit. Other compilers may be quite different, of course.
    The caveat about fflush(stdin) is that it is undefined by the C standard. Something like this will "never stop" my compiler, I've done a bunch of times just for the thrill :
    Code:
    int main () {
         char string[3]="hello world";
         printf("%s\n",string);
         return 0;
    }
    No errors, compiles fine, executes properly -- no problem! That does not make it right in the sense that allowing buffer overflows and using fflush(stdin) are BAD HABITS.

    And make sure you read my last post, there are other real things wrong with your code.
    Last edited by MK27; 08-03-2009 at 02:36 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  15. #15
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    That code runs under Turbo C 1.01, with the code I added.

    Turbo C was *made* to work OK with fflush(stdin), but not all comziler's were made that way. (sorry, bad keyboard, so ...ozqrstuv is the new alzabet, hey!). It was written by Borland, not the C standards committee!

    In no way is fflush(stdin), the same as over-running a buffer. I can't agree with that.

    It's OK to critique his zrogram, but let's not run it all into the ground, (along with his comziler, and his instructor, and his school), all at once.

    That's venting our frustrations, more than helzing him.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Updating in a sequential file?
    By Ronnyv1 in forum C Programming
    Replies: 1
    Last Post: 03-24-2009, 04:41 PM
  2. Replies: 2
    Last Post: 05-09-2008, 07:27 AM
  3. file writing and reading
    By Micko in forum C Programming
    Replies: 8
    Last Post: 01-13-2004, 11:18 AM
  4. Structures and file io
    By mungyun in forum Linux Programming
    Replies: 1
    Last Post: 05-18-2002, 02:48 PM
  5. Writing Data to a File
    By Unregistered in forum C Programming
    Replies: 2
    Last Post: 05-18-2002, 03:17 AM

Tags for this Thread