#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2013
    Posts
    2
    Rep Power
    0

    Help with our Program pleaseee :(


    Code:
    #include<stdio.h>
    #include<string.h>
    #include<conio.h>
    #include<stdlib.h>
    
    
    typedef struct
    {
            char FN[50],LN[50], MI;
    
    
    } fullname;
    
    
    typedef struct student
    {
          fullname name;
          int ID_no, year;
          char course[30];
          struct student *next;
    } studentinfo;
    
    
    
    
    typedef struct book
    {
            char title[30], genre[20];
            fullname author;
            int ISBN;
            struct book *next;
    }bookinfo;
    //void pass();
    
    
    void student();
    void addStudent(studentinfo *);
    void viewAllRecords(studentinfo *);
    void editRecord(studentinfo *);
    void deleteRecord(studentinfo *);
       /*
    
    
    void book();
    void addbook();
    void viewAllbook();
    void deletebook();
    void editbook();  */
    
    
    void menu();
    
    
    
    
    
    
    int main()
    {
    
    
    
    
       // pass();
        menu();
    
    
    
    
    }
    
    
    
    
    
    
    
    
    /*void pass()
    {
         char password[10];
         int i;
    
    
    
    
         printf("\n Enter Password: ");
    
    
    
    
         for(i=0; i<8;i++)
         {
                  password[i]=getch();
                  printf("*");
    
    
         }
        gets(password);
    
    
    
    
         if( password=="sexygirl")
         {
              printf("Correct Password!\n");
    
    
    
    
         }
         else
         {
             printf("Password did not match! \n");
             printf("Enter Password again!\n");
             pass();
    
    
         }
    
    
    }
    
    
    */
    
    
    void menu()
    {
     int a;
    
    
    
    
    
    
         printf("\nEnter the number of your choice: \n [1]student \n [2]book \n [3]search \n [4]Exit\n");
         scanf("%d",&a);
    
    
         while( a!=3)
         {
                switch(a)
                {
                case 1:clrscr();student();getch();break;
                case 2:clrscr();book();getch();break;
                //case 3:search();getch();break;
                default:exit(1);
    
    
                }
    
    
         }
    }
    
    
    void student()
    {   studentinfo *head;
        int s;
    
    
        printf("\nEnter the number of your choice: \n [1]add student \n [2]delete student \n [3]view all student\n [4]edit student\n [5]Main Menu\n");
        scanf("%d",&s);
    
    
          while( s!=6)
         {
                switch(s)
                {
                case 1:clrscr();addStudent(head);getch();break;
                case 2:clrscr();deleteRecord(head);getch();break;
                case 3:clrscr();viewAllRecords(head);getch();break;
                case 4:clrscr();editRecord(head);getch();break;
                case 5:clrscr();menu();getch();break;
    
    
                }
    
    
         }
    
    
    }
    
    
    
    
    void addStudent(studentinfo *head)
    {
        studentinfo *p,*temp;
        int i,count;
        FILE *fp;
    
    
    
    
        if((fp = fopen("data.dat", "ab"))==NULL)
        {
         printf("\nFile not found!");
         exit(1);
        }
    
    
    printf("Enter Number of Students to be added:\n");
    scanf("%d",&count);
    printf("\n===========================================================\n");
    
    
    head = (studentinfo *) malloc(sizeof(studentinfo));
    p=head;
    
    
     for(i=0;i<count;i++)
    {
    
    
    
    
      temp=(studentinfo*)malloc(sizeof(studentinfo));
      printf("\nEnter your first name: \n");
      fflush(stdin);
      gets(p->name.FN);
    
    
      printf("Enter your Middle Initial: \n ");
      scanf("%c",&p->name.MI);
    
    
      printf("Enter your last name: \n");
      fflush(stdin);
      gets(p->name.LN);
    
    
      printf("Enter ID Number: \n ");
      scanf("%d",&p->ID_no);
    
    
      printf("Enter year level: \n ");
      scanf("%d",&p->year);
    
    
      printf("Enter your course: \n");
       fflush(stdin);
      gets(p->course);
    
    
        printf("Successfully Added!\n");
        fwrite(p,sizeof(*p),1,fp);
     }
     p->next=NULL;
     fclose(fp);
    
    
    
    
     clrscr();
     student();
    
    
    }
    
    
    
    
    void viewAllRecords(studentinfo *head)
    {
         studentinfo *p;
         FILE *fp;
         int i;
          if((fp = fopen("data.dat", "rb"))==NULL)
        {
         printf("\nFile not found!");
         exit(1);
        }
        head = (studentinfo *) malloc(sizeof(studentinfo));
        p = head;
    
    
     while(p!=NULL)
        {
    
    
          fread(p,sizeof(*p),1,fp);
          printf("\nName: %s",p->name.FN);
          printf("\t%c.",p->name.MI);
          printf("\t%s",p->name.LN);
          printf("\nID NO: %d",p->ID_no);
          printf("\tCourse & Year: %s-%d\n",p->course,p->year);
          p = p->next;
    
    
    
    
          }
    
    
        fclose(fp);
          student();
    }
    
    
    void deleteRecord(studentinfo *head)
    {
         studentinfo *p,*temp;
        int num;
        FILE *fp;
    
    
    
    
        if((fp = fopen("data.dat", "ab"))==NULL)
        {
         printf("\nFile not found!");
         exit(1);
        }
    
    
        printf("Enter ID number of student to be deleted\n");
         scanf("%d", &num);
    
    
         head = (studentinfo *) malloc(sizeof(studentinfo));
         p=head;
    
    
         while(p->next->ID_no != num)
         p=p->next;
    
    
         if (p->next != NULL)
         {
                 temp=p->next;
                 p->next=temp->next;
            free(temp);
          }
         fclose(fp);
         student();
         }
    
    
    void editRecord(studentinfo *head)
    {
         studentinfo *p,*temp;
        int num,a;
        FILE *fp;
    
    
    
    
        if((fp = fopen("data.bnf", "ab+"))==NULL)
        {
         printf("\nFile not found!");
         exit(1);
        }
    
    
         head = (studentinfo *) malloc(sizeof(studentinfo));
         p=head;
         printf("Enter ID number of the student to be edited\n");
         scanf("%d", &num);
         while(p->next !=NULL && p->next->ID_no != num)
         p=p->next;
         temp=p->next;
    
    
    
    
            printf("Enter the number of the item to be edited: \n [1]Student's First Name \n [2]Student's Middle Name \n [3]Student's Last Name\n [4]ID Number \n [5]Year Level \n [6]Course \n [7]Exit\n");
         scanf("%d",&a);
    
    
         while( a!=7)
         {
                switch(a)
                {
                case 1:
                     free(temp->next->name.FN);
                     printf("Enter New First Name:\n");
                     gets(temp->next->name.FN);
                     fscanf(fp,"\n%s",temp->next->name.FN);
                     getch();
    
    
                     break;
                case 2:
                     printf("Enter New Middle Name:\n");
                     scanf("%c", &temp->next->name.MI);
                     fscanf(fp,"\n%c",temp->next->name.MI);
                     break;
                case 3:
                     free(temp->next->name.LN);
                     printf("Enter New Last Name:\n");
                     gets(temp->next->name.LN);
                     fscanf(fp,"\n%s",temp->next->name.LN);
                     break;
                case 4:
                     printf("Enter New ISBN:\n");
                     scanf("%d",&temp->next->ID_no);
                     fscanf(fp,"\n%d",temp->next->ID_no);
                     break;
                case 5:
                     printf("Enter New Last Name:\n");
                     scanf("%d",temp->next->year);
                     fscanf(fp,"\n%d",temp->next->year);
                     break;
                case 6:
                     free(temp->next->course);
                     printf("Enter New Course");
                     gets(temp->next->course);
                     fscanf(fp,"\n%s",temp->next->course);
                case 7:
                     exit(1);
                     break;
    
    
                }
    
    
    
    
         }
    
    
         clrscr();
         fclose(fp);
         student();
    }
    our problem is it only displays 1 record on viewAllRecords() function and delete and edit functions are not working please we need help badly
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    You know, it's not very smart of you to run a broken program. If a program throws warnings at you, then it's broken.

    Here's what I get when I compile your program (MinGW gcc under Win7):
    C:\otros\dcw>gcc -Wall trebz01.c conio.c
    trebz01.c: In function `main':
    trebz01.c:70: warning: control reaches end of non-void function
    trebz01.c: In function `menu':
    trebz01.c:146: warning: implicit declaration of function `book'
    trebz01.c: In function `viewAllRecords':
    trebz01.c:270: warning: unused variable `i'
    trebz01.c: In function `editRecord':
    trebz01.c:389: warning: format argument is not a pointer (arg 3)
    trebz01.c:400: warning: format argument is not a pointer (arg 3)
    trebz01.c:404: warning: format argument is not a pointer (arg 2)
    trebz01.c:405: warning: format argument is not a pointer (arg 3)
    C:\Users\FRY'SE~1\AppData\Local\Temp\ccaEdaaa.o(.text+0xd2):trebz01.c: undefined
    reference to `book'

    C:\otros\dcw>
    For that matter, it doesn't even compile, courtesy of the missing function, book(). Yes, you commented out the prototype, but you kept the function call; just follow the warning, "implicit declaration of function `book'".

    main returns an int. You even correctly declared that. But then you didn't do the return. If you lie to the compiler, then it will get even with you.

    The "unused variable" warning isn't usually important, unless you think that you actually did use that variable.

    You should take a close look at editRecord. Remember that *scanf needs addresses. You are not always providing an address. What the compiler would probably generate would take the value that you just gave it and try to use it as if that value were an address, because it would try to use an int as if it were a pointer. Guaranteed to cause a lot of grief. Attend to that!

    If you have been ignoring warnings, then you are an idiot. If you have been keeping warnings turned off, then you're a blithering idiot. Never ignore warnings! Always turn warnings on and up!

    And never run a program that doesn't compile cleanly (meaning no errors and no warnings). A program that doesn't compile cleanly is a broken program. The output and behavior of broken programs are worthless and a complete waste of time.
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2013
    Posts
    2
    Rep Power
    0
    im kinda confused how to retrieve the linked list from the data file. i really dont know how to do it. our addStudent() funcion works but the other functions doesnt. viewAllRecords() function only view one record instead of all. please help us :(
  6. #4
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    Non sequitur.

    Did you make the corrections? If so, then why didn't you post the corrected code so that we would have that to work with instead of your old broken code?

    You have to work with us for us to help you. You need to help us to help you. If you don't help us, then we cannot help you.
  8. #5
  9. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    BTW, this won't do what you think:
    Code:
      printf("Enter your Middle Initial: \n ");
      scanf("%c",&p->name.MI);
    You think you're telling scanf to read in the single printable character that the user inputs as the middle initial. In reality, you're telling scanf to read the next character in the input buffer regardless of what it is. In the case where this follows a previous scanf, then that character read in would be the newline ('\n') input into the buffer when you hit the Enter key. I'm not sure of what gets leaves behind in the input buffer, so I'm not sure what effect that will have -- since I know better than to do something that foolish, I haven't learned exactly what will happen.

    Instead, you need to tell scanf to read in the next printable character ignoring any and all whitespace that precedes that character. This is what that scanf call should look like:
    scanf(" %c",&p->name.MI);
    Please note the space that I added.

    I see you using this a lot:
    fflush(stdin);
    That is not defined in C. fflush is only defined for output streams, such as stdout and disk files, but not for input streams. You are depending on undefined behavior, which is an invitation for trouble. You are trusting your fate to whims of the compiler writers, which can change out from under you. Another forum member's tag-line likens using undefined behavior to dancing barefoot on broken glass. Don't do it. Stop using fflush on the stdin input file!

    You are also using gets a lot. Do not use gets! It is a gaping security hole that invites a buffer-overflow attack. On a more practical level, if you use gets then any user could type in more than it expects, thus overflowing the buffer and clobbering whatever follows the buffer. If you're lucky, then that will cause the program to crash. If you are very unlucky, then it will merely corrupt your program's data causing it to "inexplicably" produce the wrong results, which will lead to you coming here crying that your program doesn't work. That is what using gets will get you.

    If you don't believe me, then read the documentation on gets. If you don't have the documentation on your system, then Google on man page gets. The man page will also tell you to use fgets(stdin), since you are able to limit the length of the input so that it will not overflow your buffer.

    Have you corrected those other problems yet? Until you do and post your corrected code, we won't have anything to work with.
  10. #6
  11. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    Originally Posted by trebz95
    our problem is it only displays 1 record on viewAllRecords() function and delete and edit functions are not working please we need help badly
    Let's see if I get this right. main() calls menu(), which calls student(), which in turn calls viewAllRecords(), which in turn calls an entirely new instance of student() -- what???:
    Code:
    void viewAllRecords(studentinfo *head)
    {
         studentinfo *p;
         FILE *fp;
         int i;
          if((fp = fopen("data.dat", "rb"))==NULL)
        {
         printf("\nFile not found!");
         exit(1);
        }
        head = (studentinfo *) malloc(sizeof(studentinfo));
        p = head;
    
    
     while(p!=NULL)
        {
    
    
          fread(p,sizeof(*p),1,fp);
          printf("\nName: %s",p->name.FN);
          printf("\t%c.",p->name.MI);
          printf("\t%s",p->name.LN);
          printf("\nID NO: %d",p->ID_no);
          printf("\tCourse & Year: %s-%d\n",p->course,p->year);
          p = p->next;
    
    
    
    
          }
    
    
        fclose(fp);
          student();
    }
    As far as I can decipher, the student linked list only exists inside of student, since head is a local variable there. So when you call student again at the end of viewAllRecords, you create an entirely new and independent copy of head (SIMD, "single instruction, multiple data", model), thus creating an entirely new and independent second student linked list, one which is empty.

    Your program structure and flow of control doesn't make any sense. Why not simply return from viewAllRecords?

    Also, when you return from student(), head goes away as all local variables do and you drop that entire student linked list. That is a massive memory leak! If you are going to throw a linked list away, then dispose of it properly so that that memory can be returned to the heap for reuse. If instead you want that linked list to persist outside of student, then don't declare its head pointer locally.

    I think you need to sit down and work on the design of your program. Decide exactly what you want the program to do and where the data needs to be accessed and how long it needs to persist. The design phase comes before the coding phase. A lot of the time and effort is to go into the design phase, which makes the coding phase much shorter and easier. If you skimp on the design phase, then the coding phase will drag out because you need to rewrite it over and over again. If you do a proper job of designing the program, both the coding and the integration phases will go quickly and smoothly. If you skip the design phase, then coding and integration/debugging will be a nightmare. Your choice.

    PS
    Since C is a procedural language, you could use an old structured-programming graphic tool to view the overall structure of your program. With pencil and paper, sketch a tree in which the nodes are the functions and the edges (lines connecting nodes) are the function calls. At the top is main. One level down, draw the nodes that are the functions that main calls and connect them. Under those functions, draw the nodes of the functions that they call, and so on.

    Note that a function can have many child functions, functions that it will call. Most major structural functions should only have one parent function, the function that calls it, though some utility functions could be called from more than one place -- you can depict both. With that tree you can visualize the flow of control.

    Please note that each edge is bi-directional: flow of control goes down to the function being called and then it flows right back up that exact same edge when the function returns. What you are doing is that you are creating an entire new edge to get back to the parent function -- that is wrong!

    For your data structures, look at the nodes that need each data structure. Also answer the question of what you want to have happen when you travel up and down the tree. For example, student and the sub-tree beneath it need the student linked list. But what happens when you exit the student menu and then return to it again? Do you want the original student linked list to still be there (AKA "persistence")? Or do you want to start an entirely new list from scratch? If you want that list to remain persistent, then you need to declare it so that it can be. What you are doing now is to start over from scratch every time you call student() -- that includes you calling it in a botched attempt to "return" to it.

    You need to pay attention to the design phase so that you can have a clear vision of what your program will do.

    PPS
    To see what a structure chart looks like, here's the Wikipedia article: http://en.wikipedia.org/wiki/Structure_chart
    Last edited by dwise1_aol; October 9th, 2013 at 11:49 AM.
  12. #7
  13. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    Originally Posted by trebz95
    im kinda confused how to retrieve the linked list from the data file. i really dont know how to do it. our addStudent() funcion works but the other functions doesnt. viewAllRecords() function only view one record instead of all. please help us
    First, have you addressed the other very serious problems I've already pointed out? If so, then show us the new corrected code.

    What is the purpose of head in student()? That is the top level that it's declared at and you pass its value to each of the subordinate functions that student() calls. You never initialize it, so it contains a garbage address, meaning that it could be pointing anywhere at all, most likely outside the memory space that belongs to your program. If you were to actually use that garbage uninitialized pointer, then your program would most likely crash, but you don't use it. Instead, inside of each of those functions that student() calls, you assign a valid address to those functions local copies of head, via the malloc calls. Of course, you never change where the head pointer in the parent function, student(), points, just where the local copy of head points. If you were intending to have the original top-level head pointer point to a linked list that you are building, then that is not what you are actually doing. In reality, that top-level head pointer does nothing and it is a complete waste of time and processing power to pass it to those functions. If you want to change where that top-level head pointer is pointing, then you need to pass to those functions the address of that pointer. But as it is, I can only try to guess what your code is intended to do.

    You claim that addStudent() works, but it doesn't. Yes, it writes records of studentinfo out to a file, albeit in the wrong manner (even though it would work for this program, but not necessarily for another program using a different compiler or different compiler settings that declares the exact-same studentinfo struct; ie, it is not portable!). But it does not create a linked list. Read what you had written and read it for comprehension. You malloc one studentinfo record and assign it to both your local copy of head and to the local variable, p. You then use p, and hence that single malloc'd record, to store the values that you have the user enter and you wrote the entire record to disk. But you keep using that one single record over and over again. Worse, every time you go through that loop, you malloc another record and assign it to temp, but you never ever use it! Far worse yet, you keep dropping those extraneous record whenever you malloc yet another one and assign it to temp. That is a memory leak! Cardinal Rule: Never drop a pointer! Remember, that pointer is the only way you have to access that record; if you set that pointer to a different value without saving the old value, then you have dropped that pointer and have lost all access to the record it was pointing to.

    Here is how you build a linked list:
    1. Establish a head pointer and keep it safe! That head pointer is your only access to the linked list. At first, the head pointer will be NULL because the list is empty.

    2. Malloc a record and fill the data fields.

    3. Insert the record into the linked list. If it's an unsorted list, then you could add it after the last node in the list (ie, at the tail) or at the head. If you add it at the head, then set the new record's next field to point to where head is pointing -- that keeps you from dropping the list -- and set head to point to the new record. If you add it at the tail, then find the last record in the list and set its next field to point to the new record; if you add to the tail, you might want to maintain a tail pointer that always points to the last record, which will keep you from having to traverse the entire list each time you add a record. And if it's a sorted list, then you need to search the list for where you want to insert it; I'll leave that for later if it's needed and once you have workable code.

    4. If there are more records to add, then goto Step 2. Else you're done.

    addStudent() doesn't even come close to doing any of that. addStudent() does not work!


    In viewAllRecords(), what exactly are you trying to do? Especially with that statement, p = p->next;? Are you trying to rebuild the linked list from the data file? Again, that is not what you are actually doing. In order to rebuild the linked list from a data file, you need to follow the same procedure as I outlined above. You are not doing that. Instead, you malloc space for one record and repeatedly read into it and print out what was read. But what is in the next field? Whatever occupies that space in the disk file. Is it a valid memory address? No. For one thing, in addStudent() you never set the value of the next field -- of course, you also never actually created a linked list in the first place. So what value is in the next field? I don't know, but you can find out. Read that file, though you will need to use a hex dump (see my page, Generating a Hex Dump -- that is a link). From what you describe and your code, I suspect that the next field of the first record is all zeros, AKA NULL. And your code will drop out of that while loop as soon as it hits a NULL.

    But that's ignoring the huge mistake you are making. You cannot write a pointer to a disk file, then read it in later and expect it to be good. And especially not if you are reading a disk file created from a previous run. Here is what I wrote on that in the Basic Principles and Caveats section of my page, DWise1's Sockets Programming Pages: Formatting Packet Data; I'm adding the paragraph on structs as well, since you were making that mistake too as I pointed out above:
    • Pointers -- let's face it, a pointer points to a location in memory and the data that resides in that location. You cannot just send a pointer, because on the receiving system that memory location would contain something entirely different. No, instead of sending a pointer, you need to retrieve the data being pointed to and send the data itself. This should be a no-brainer, but I've seen people try to do it.

      BTW, the same idea applies to saving pointer data to a disk file: you cannot just write the pointer to disk, but rather you must write the data that it's pointing to. And in the case of saving a data structure, such as a linked list or a tree, you must format the data to disk in such a manner that you can reconstruct the data structure when you read it back in. Not a trivial task.
    • structs -- a lot of programmers get into the sloppy habit of writing entire structs to disk and then reading them back in. That will work if all programs writing and reading those files were written on the same platform with the same compiler, but not necessarily when you cross platforms. Compilers throw extra bytes between fields, extra padding, in an effort to line up the fields in such a way that accessing those fields will be more efficient. That means that the exact same struct declaration in source code can produce different-sized structs on different platforms and very likely will.

      For example, in a class exercise I wrote a C++ program on Linux that output an array of objects simply by using block-writes and read them back in with block-reads. I worked on the program at work during lunch on a Windows machine using MinGW gcc. But it kept crashing. The reason was that Linux's object size was slightly greater than on my Windows machine, so the end-of-file didn't line up the same. When I deleted the old data file then it ran just fine. Two different compilers on two different platforms created the very same objects, but of different size. A very good object lesson (no pun intended).

      And of course, if you write the entire struct to disk as one block and any of the fields in that struct is a pointer, then all bets are off. If you don't understand why, then refer above to my caveat about pointers.
    You have many more problems than you think. Please work on them.

IMN logo majestic logo threadwatch logo seochat tools logo