Thread: student database

  1. #1
    Registered User
    Join Date
    Sep 2012
    Posts
    68

    student database

    Hello everyone,
    So i was just going by my old college a few days back to meet some of my close professors,when i noticed one of them logging student data on an excel sheet.
    Being a inquisitive c learner i asked him to contact the it/compt dept and make them write a code to make logging easier.
    He got back to me today informing that they were too busy at the moment,so i offered to do it instead and need some of your expertise suggestions.

    I have already written a first draft and have come across a few difficulties.
    The program works fine but i still want to optimize and add a few features.I would be glad to hear your useful tips and suggestions.
    Here's the code:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <process.h>
    struct mydata
    {
        char name[100];
        int age,hight;
    };
    int main()
    {
        struct mydata bo;
        char *ptr;
        char buffer[10000] = "\0",ch[100000] = "\0",option,fname[100] = "\0",name[10000] = "\0",replace_data[10000] = "\0";
        char header[100] = "Name,Age,Hight\n";
        int num = 0;
        char flag=0;
        printf("MENU:\n1.Add entry\n2.Edit Entry\n3.Exit\n");
        option = getch();
        char submenu1 = 13;
    
        memset(bo.name,0,100);
        bo.age = 0;
        bo.hight = 0;
    
        FILE *fs;
        fflush(stdin);
        if(option == '1')
        {
            printf("Enter file name.");
            scanf("%s",&fname);
            fname[100] = strcat(fname,".csv");
            system("cls");
            while(submenu1 == 13)
            {
                fs = fopen(fname,"r");
                if(fs != NULL)
                {
                    flag=1;
                }
                fclose(fs);
                fs=fopen(fname,"a+");
                if(fs == NULL)
                {
                    printf("Error opening file.");
                    exit(0);
                }
                if(flag==0)
                {
                    fprintf(fs,"%s",header);
                }
                fflush(stdin);
                printf("Enter the name.\n");
                gets(bo.name);
                fflush(stdin);
                printf("Enter the age.\n");
                scanf("%d",&bo.age);
                fflush(stdin);
                printf("Enter the hight.\n");
                scanf("%d",&bo.hight);
                fprintf(fs,"%s,%d,%d\n",bo.name,bo.age,bo.hight);
                fclose(fs);
                printf("Add another entry.(Hit enter to keep on adding)\n");
                submenu1 = getch();
                fflush(stdin);
                if(submenu1 != 13)
                {
                    exit(0);
                }
            }
        }
        fflush(stdin);
        if(option == '2')
        {
            system("cls");
            printf("Enter file name.");
            scanf("%s",&fname);
            strcat(fname,".csv");
            FILE *fs,*fp;
            fs = fopen(fname,"r");
            if(fs == NULL)
            {
                printf("Could not open file:Read operation failed.\n");
                system("pause");
            }
            else
            {
                printf("Enter name of entry to edit.");
                scanf("%s",&name);
                fflush(stdin);
                printf("Enter data to edit(name,age,hight)");
                scanf("%s",&replace_data);
                FILE *fs,*fp;
                fs = fopen(fname,"r");
                if(fs == NULL)
                {
                    printf("Could not open file:Read operation failed.");
                }
                fread(ch,1000,1,fs);
                fclose(fs);
                ptr = strstr(ch,name);
                if(!ptr)
                {
                    printf("\n\nName not found.\nProgram Exiting.");
                    exit(1);
                }
                while(*(ptr+num) != '\n')
                {
                    num++;
                }
                strcpy(buffer,(ptr+num));
                strcpy(ptr,replace_data);
                strcat(ch,buffer);
                printf("\n%s\n",ch);
                fp = fopen(fname,"w");
                if(fp == NULL)
                {
                    printf("Could not open file:Write operation failed.");
                }
                fprintf(fp,"%s",ch);
                fclose(fp);
    
                /*printf("Do you want to view the excel sheet?")
                if(yes)
                {
                    open excell/notepad sheet.
                    spawn(somthing)...dont know how??
                }*/
    
            }
        }
        fflush(stdin);
        if(option == '3')
        {
            exit(0);
        }
        return 0;
    }
    Output(example):
    Name,Age,Hight
    John,19,170
    Nickel,21,160
    .
    .
    .
    //etc
    Last edited by ak47; 11-06-2012 at 10:00 AM.

  2. #2

  3. #3
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    I suggest using switch statement for menus
    Switch Case in C - Cprogramming.com

    Move the non-portable code to a separate function is a good idea in most cases.
    All, or nearly all, system calls are considered non-portable and security issues.
    Code:
    system("cls");
    Tim S.
    Last edited by stahta01; 11-06-2012 at 10:10 AM.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > #include <process.h>
    This is an obsolete header file.
    What are you using for a compiler? TurboC?

    > char buffer[10000] = "\0",ch[100000] = "\0",option,fname[100] = "\0",name[10000] = "\0",replace_data[10000] = "\0";
    Nah, it can't be TurboC, you have some massively large arrays.
    100K for a string - WTF!?

    > scanf("%s",&fname);
    It's just fname, not &fname

    > fname[100] = strcat(fname,".csv");
    1. This is an array overrun, there is no char at this point in the array.
    2. strcat doesn't return a char
    3. Did you get any warnings from the compiler when you compiled this?

    > gets(bo.name);
    While you're reading the FAQ about fflush(stdin), read the other FAQ about gets() as well.

    > if(submenu1 != 13)
    > exit(0);
    Brutal!
    What if I wanted to choose another top level option?

    Make AddEntry and EditEntry separate functions.
    Then your main won't grow to be several hundred lines long.
    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.

  5. #5
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    "Hight", should be "Height".

    Instead of one big function, break it up into several smaller one's:
    menu, readFile, search, edit, delete, etc.

    I was expecting to see fname and lname as members of the struct mydata, and then a big global (above main()) creation of that struct array. If those local arrays get beyond local stack size, the program will fail.

    The search would be very quick if the array was sorted, and then searched with a binary search function.

    "entry" in menu option 1, should be the same case as "Entry" in option 2

  6. #6
    Registered User
    Join Date
    Sep 2012
    Posts
    68
    Thanks for you help guys,ok so far i got to remove
    1.flush(stdin)
    2.Use switch statements
    3.Put my menus into separate functions.
    4.Not use gets(old habit apologies,will use fgets from now on)
    5.And ya "Hight", should indeed be "Height"
    > #include <process.h>
    This is an obsolete header file.
    What are you using for a compiler? TurboC?

    > char buffer[10000] = "\0",ch[100000] = "\0",option,fname[100] = "\0",name[10000] = "\0",replace_data[10000] = "\0";
    Nah, it can't be TurboC, you have some massively large arrays.
    100K for a string - WTF!?

    > scanf("%s",&fname);
    It's just fname, not &fname

    > fname[100] = strcat(fname,".csv");
    1. This is an array overrun, there is no char at this point in the array.
    2. strcat doesn't return a char
    3. Did you get any warnings from the compiler when you compiled this?
    >I thought of using spawn or something similar later,so i added the process.h
    >I din't know how much array size i would require so i gave a large number,its just temporary.
    >will change that right away.
    >My bad, i have pasted a slightly older copy of the program,its just
    Code:
    strcat(fname,".csv");
    at both the places.

    I will do all these changes and get back to you guys,thank you very much for all your help.

  7. #7
    Registered User
    Join Date
    Sep 2012
    Posts
    68
    ok so i put them in separate functions and used switch for my menu options.
    >I haven't yet removed the fflush(stdin) ,that's partly because i did not understand the FAQ about that.
    As far as my understanding the replacement code(in the FAQ) does the function of scanf,so should i remove scanf and opt for other means of getting input from user?Please give me an example in code.(and Please correct me if i am wrong anywhere :P)

    >about the gets,i tried using "fgets",but here's a new problem.Quoting from turbo c reference library:
    fgets retains a newline character at the end of the string and appends a null byte to mark the end of the string.
    so my output will be in this form:

    name,
    age,hight

    But i want it to be:

    name,age,hight
    ---
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    //#include <process.h>
    struct mydata
    {
        char name[100];
        int age,hight;
    };
    void myExit(void);
    void myEntry(void);
    void myEdit(void);
    int main()
    {
        char option;
        printf("MENU:\n1.Add entry\n2.Edit Entry\n3.Exit\n");
        option = getch();
    
        switch(option)
        {
        case '1':
        {
            myEntry();
        }
        break;
        case '2':
        {
            myEdit();
        }
        break;
        case '3':
        {
            myExit();
        }
        break;
        }
        return 0;
    }
    void myEntry(void)
    {
        struct mydata bo;
        char fname[100] = "\0";
        char submenu1 = 13;
        char header[100] = "Name,Age,Height\n";
        char flag = 0;
    
        memset(bo.name,0,100);
        bo.age = 0;
        bo.hight = 0;
    
        FILE *fs;
        fflush(stdin);
        printf("Enter file name.");
        scanf("%s",fname);
        strcat(fname,".csv");
        system("cls");
        while(submenu1 == 13)
        {
            fs = fopen(fname,"r");
            if(fs != NULL)
            {
                flag=1;
            }
            fclose(fs);
            fs=fopen(fname,"a+");
            if(fs == NULL)
            {
                printf("Error opening file.");
                exit(0);
            }
            if(flag==0)
            {
                fprintf(fs,"%s",header);
            }
            fflush(stdin);
            printf("Enter the name.\n");
            //fgets(bo.name,100,stdin); //prints \n at the end.
            gets(bo.name);
            fflush(stdin);
            printf("Enter the age.\n");
            scanf("%d",&bo.age);
            fflush(stdin);
            printf("Enter the height.\n");
            scanf("%d",&bo.hight);
            fprintf(fs,"%s,%d,%d\n",bo.name,bo.age,bo.hight);
            fclose(fs);
            printf("Add another entry.(Hit enter to keep on adding)\n");
            submenu1 = getch();
            fflush(stdin);
            if(submenu1 != 13)
            {
                break;
            }
        }
    }
    
    void myEdit(void)
    {
        char *ptr;
        char buffer[10000] = "\0",ch[10000] = "\0",fname[100] = "\0",name[10000] = "\0",replace_data[10000] = "\0";
        int num = 0;
        system("cls");
        printf("Enter file name.");
        scanf("%s",fname);
        strcat(fname,".csv");
        FILE *fs;
        fs = fopen(fname,"r");
        if(fs == NULL)
        {
            printf("Could not open file:Read operation failed.\n");
            system("pause");
        }
        else
        {
            printf("Enter name of entry to edit.");
            scanf("%s",name);
            fflush(stdin);
            printf("Enter data to edit(name,age,hight)");
            scanf("%s",replace_data);
            FILE *fs;
            fs = fopen(fname,"r");
            if(fs == NULL)
            {
                printf("Could not open file:Read operation failed.");
            }
            fread(ch,10000,1,fs);
            fclose(fs);
            ptr = strstr(ch,name);
            if(!ptr)
            {
                printf("\n\nName not found.\nProgram Exiting.");
                exit(1);
            }
            while(*(ptr+num) != '\n')
            {
                num++;
            }
            strcpy(buffer,(ptr+num));
            strcpy(ptr,replace_data);
            strcat(ch,buffer);
            printf("\n%s\n",ch);
            FILE *fp;
            fp = fopen(fname,"w");
            if(fp == NULL)
            {
                printf("Could not open file:Write operation failed.");
            }
            fprintf(fp,"%s",ch);
            fclose(fp);
            printf("\nEdit Succesful");
        }
    }
    void myExit(void)
    {
        exit(0);
    }

  8. #8
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Think of your kitchen faucet, and think of your toilet. You flush() only the toilet, not the kitchen faucet. That's how it is with fflush() - it works for output streams only, not input.

    The trick is, to remove the junk from the input buffer. Instead of
    scanf("%c",&myCharVariable);

    use
    scanf(" %c",&myCharVariable);

    The one little space before the %, makes all the difference, since it tells scanf() to skip over whitespace like newlines.

    Note that numbers and strings have no problems with the trailing newline, because the newline is seen as whitespace, and skipped. When working with chars however, the newline is seen AS a char, and mistaken as the input to be saved, if present in the input buffer.

    fgets() is a bit of a pain since it adds the newline, but it's worth it to use it. like so:
    Code:
    fgets(buffer, sizeof(buffer), fp);
    int len = strlen(buffer)
    if(buffer[len-1]=='\n')
       buffer[len-1]=='\0';
    And the newline fgets added, is now gone, and the buffer string has been shortened to it's proper length.

    You will need to create the int variable "len" at the start of the function, depending on your compiler.
    Last edited by Adak; 11-07-2012 at 10:39 AM.

  9. #9
    Registered User
    Join Date
    Sep 2012
    Posts
    68
    Thanks Adak,That did the trick.But i noticed another problem,i know its something silly but i cant figure out what it is!
    In the myEdit() function the
    Code:
    fread(ch,10000,1,fs);
    doesn't seem to be working as planned.(I printed out the fread() data and checked.)
    When i edit an entry for example:
    Name,Age,Hight
    john,23,150
    mike,50,130
    dolly,20,150

    Say i want to edit details of mike.
    When i finish editing i get this:
    Name,Age,Hight
    john,23,150
    mike,70,125 //edit successful
    dolly,20,150
    .//blank line
    .//blank line
    ,150

    2 extra blank lines and then some value
    Any idea what's wrong?

  10. #10
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    fread reads in the number of bytes you tell it to read in - it could be what was left over from a recipe or anything. Different compilers will pad a struct differently. You could use sizeof(structname), but then you have commas and spaces to deal with. I suggest using fread only with binary files. For text files, use fgets() and then take out your struct.members with sscanf() - or you can use fscanf() directly on the file, since it is formatted.

  11. #11
    Registered User
    Join Date
    Sep 2012
    Posts
    68
    Yep its working now.Thanks

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. implementing a student database using a binary tree
    By atchy6 in forum C Programming
    Replies: 1
    Last Post: 05-02-2012, 08:44 AM
  2. [ A student who needs help ]
    By Phazawhy in forum C Programming
    Replies: 2
    Last Post: 08-23-2007, 04:28 AM
  3. Database to Database Transfer?
    By draggy in forum C++ Programming
    Replies: 4
    Last Post: 01-17-2007, 10:50 AM
  4. A Student's Mark Database
    By playstationman1 in forum C++ Programming
    Replies: 1
    Last Post: 03-01-2006, 01:26 PM
  5. Replies: 1
    Last Post: 10-09-2001, 10:20 PM