Help please!

This is a discussion on Help please! within the C Programming forums, part of the General Programming Boards category; Can someone please tell me what is wrong with the code below, and point me in the right direction. I ...

  1. #1
    Registered User
    Join Date
    Aug 2005
    Posts
    51

    Help please!

    Can someone please tell me what is wrong with the code below, and point me in the right direction. I want the user to be able to add to each structure of the array, and then view them back, but it doesnt seem to be working properly.


    Code:
    #include<stdlib.h>
    #include<stdio.h>
    #include<conio.h>
    #include<windows.h>
    #include<string.h>
    #include<time.h>
    
    
    
    
    //structure to hold all info, final program will contain structures of main meal, snacks
    //and also deserts, using this structure
    
    struct database {
      char prod[60];
      float cal;
      float carb;
      float prot;
      float fat;  
    };
    
    //function prototypes
    
    int full_screen(void);//puts the dos console to full screen when called
    void main_menu(void);
    void about_opt(void);
    void help_opt(void);
    void fflushstdin( void );//clears scanf when called
    void clrscr(void); //clears the screen when called
    
    
    FILE *fp;
    
    struct database *point1;
    
    
    
    
    int main()
    {
        
        
     
     full_screen(); //Puts the dos console into full screen when program is executed
    
    
      struct database mainm[10]; 
      
      main_menu();
    
    
      
      char buf[BUFSIZ];
      char *p;                      
      int i;
      int x;
      FILE *fp;
    
    
      for ( i = 0; i < 10; i++)
      
    
      {
          printf("\nAnother? (Y/N) ");
        if(getch() == 'n') break;
        
    
          printf("\nEnter the product:");
          fgets(mainm[i].prod, 60, stdin);
          if ((p = strchr(mainm[i].prod, '\n')) != NULL)
          *p = '\0';
          system("cls");
          printf("\nNow Please Enter The Nutritional Information:");
          printf("\nEnter cal:");
          scanf("%f", &mainm[i].cal);
          fflushstdin();
          printf("\nEnter carb:");
          scanf("%f", &mainm[i].carb);
          fflushstdin();
          printf("\nEnter protein:");
          scanf("%f", &mainm[i].prot);
          fflushstdin();
          printf("\nEnter fat:");
          scanf("%f", &mainm[i].fat);
          system("cls");
          fflushstdin();
          
          }
          
          
    
    fp = fopen("output.dat", "ab");      
    fwrite(mainm, 1, sizeof(struct database) * 10, fp);
    fclose(fp);
    
    fp = fopen("output.dat", "rb");
    fread (mainm, 1, sizeof(struct database) * 10, fp);
    fclose(fp);
    
    int a;
    
    for ( a = 0; a <10; a ++)
    {
        clrscr();
        
    printf("\n * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
    printf("\n\nThe nutritional values for ");
    HANDLE h = GetStdHandle ( STD_OUTPUT_HANDLE );
    WORD wOldColorAttrs;
    CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
    GetConsoleScreenBufferInfo(h, &csbiInfo);
    wOldColorAttrs = csbiInfo.wAttributes; 
    
    SetConsoleTextAttribute ( h, FOREGROUND_RED | FOREGROUND_INTENSITY );
    printf("%s", mainm[a].prod);
    SetConsoleTextAttribute ( h, wOldColorAttrs);                                        
    printf(" item # %d are:",a);
    printf("\n\nCALORIES - ");
    SetConsoleTextAttribute ( h, FOREGROUND_RED | FOREGROUND_INTENSITY );
    printf("%f", mainm[a].cal);
    SetConsoleTextAttribute ( h, wOldColorAttrs);
    printf("\n\nCARBOHYDRATES - ");
    SetConsoleTextAttribute ( h, FOREGROUND_RED | FOREGROUND_INTENSITY );
    printf("%f", mainm[a].carb);
    SetConsoleTextAttribute ( h, wOldColorAttrs);
    printf("\n\nPROTEIN - ");
    SetConsoleTextAttribute ( h, FOREGROUND_RED | FOREGROUND_INTENSITY );
    printf("%f", mainm[a].prot);
    SetConsoleTextAttribute ( h, wOldColorAttrs);
    printf("\n\nFAT - ");
    SetConsoleTextAttribute ( h, FOREGROUND_RED | FOREGROUND_INTENSITY );
    printf("%f\n\n", mainm[a].prot);
    SetConsoleTextAttribute ( h, wOldColorAttrs);
    printf("\n* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
    printf("\n\nPress return for next product...");
    
    getch();
    
    }
    
    }

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Well for starters you're still doing this wrong:
    Code:
    fwrite(mainm, 1, sizeof(struct database) * 10, fp);
    I've already told you this once. Now let's pay attention this time:
    Code:
    fwrite( fromhere, sizeofoneobject, howmanyobjects, file );
    Furthermore, at a glance, you don't even have a function called:
    Code:
    void fflushstdin( void );//clears scanf when called
    defined any place in your code. You prototype it, but it's not actually in any of the code you have posted.

    And finally, just saying "doesn't seem to be working properly" doesn't really help us pinpoint the problem. It also doesn't really inspire me to find an old DOS compiler around just so I can compile your code. It doesn't really want to even make me comment out all of the non-standard stuff just to compile it either.


    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,528
    I guess I was a little more inspired than quzah to fix up your code so it would compile on my machine. Maybe I had a little too much time on my hands. When you have problems - the kind which we can only assume what they are - do as was implied, and post warning messages and so on to help us. The other suggestion would be to pare down your code, to get a small working example - then add your features such as text colour and screen effects and so on. Here is some revised code, with comments:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct database {
            char prod[60];
            float cal;
            float carb;
            float prot;
            float fat;
    };
    
    static float getnum(void);
    
    int main(void)
    {
    
            enum {
                    MAX = 10
            };
    
            struct database mainm[MAX];
    
            char *p;
            int ;
            FILE *fp;
    
            for (j = 0; j < MAX; j++) {
    
                    (void) system("cls");
                    printf("\nEnter the product: ");
                    (void) fflush(stdout);
                    (void) fgets(mainm[j].prod, 60, stdin);
                    if ((p = strchr(mainm[j].prod, '\n')) != NULL) {
                            *p = '\0';
                    }
                    (void) system("cls");
    
                    printf("\nNow Please Enter The Nutritional Information: ");
                    (void) fflush(stdout);
    
                    printf("\nEnter cal: ");
                    (void) fflush(stdout);
                    mainm[j].cal = getnum();
    
                    printf("\nEnter carb: ");
                    (void) fflush(stdout);
                    mainm[j].carb = getnum();
    
                    printf("\nEnter protein: ");
                    (void) fflush(stdout);
                    mainm[j].prot = getnum();
    
                    printf("\nEnter fat: ");
                    (void) fflush(stdout);
                    mainm[j].fat = getnum();
            }
    
            (void) system("cls");
    
            fp = fopen("output.dat", "ab");
            if (fp == NULL) {
                    perror("Unable to open file");
                    exit(EXIT_FAILURE);
            }
            fwrite(mainm, sizeof(struct database), MAX, fp);
            if (fclose(fp) != 0) {
                    perror("fclose");
                    exit(EXIT_FAILURE);
            }
    
            fp = fopen("output.dat", "rb");
            if (fp == NULL) {
                    perror("Unable to open file");
                    exit(EXIT_FAILURE);
            }
            fread(mainm, sizeof(struct database), MAX, fp);
            if (fclose(fp) != 0) {
                    perror("fclose");
                    exit(EXIT_FAILURE);
            }
    
            for (j = 0; j < MAX; j++) {
                    (void) system("cls");
                    printf
                        ("\n * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
                    printf
                        ("\n\nThe nutritional values for item #%d (%s) are: \n\n",
                         i + 1, mainm[j].prod);
                    printf("CALORIES - %.2f\n", mainm[j].cal);
                    printf("CARBOHYDRATES - %.2f\n", mainm[j].carb);
                    printf("PROTEIN - %.2f\n", mainm[j].prot);
                    printf("FAT - %.2f\n\n", mainm[j].prot);
                    printf
                        ("\n* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
                    printf("\n\nPress return for next product...\n");
    
                    (void) getchar();
    
            }
    
            return 0;
    }
    
    
    static float getnum(void)
    {
    
            enum {
                    BUFMAX = 12
            };
            char *p;
            char buf[BUFMAX] = { (char) 0 };
            float num;
    
            (void) fgets(buf, BUFMAX, stdin);
            if ((p = strchr(buf, '\n')) != NULL) {
                    *p = '\0';
            }
    
            if ((sscanf(buf, "%f", &num)) != 1) {
                    (void) puts("Error: call to sscanf() failed.");
                    exit(EXIT_FAILURE);
            } else {
                    return num;
            }
    }
    A lot of the changes were stylistic I suppose, but it helps make things more clear.

    1 - Try to use named constants instead of 'magic numbers' in your code. You had things like
    Code:
    for ( i = 0; i < 10; i++)
    While this is not evil or anything, if 10 is a meaningful number (and in this case it is) try making it into a #define or an enum such as I did:

    Code:
     enum {
                    MAX = 10
            };
    
    ....
    
    for ( i = 0; i < MAX; i++)
    That way, if you need to change the 'max' value, you need only change it in one spot, rather than several. By doing this, you don't have to search through your code looking for the relevant bits to change.

    If you have an operation that you need to do several times, consider turning it into a separate function, such as the one I wrote, getnum(). If you look at the getnum() function, you will notice that I checked the return value of sscanf() - scanf() also returns the number of successful data conversions, and if you must use scanf(), always check that return value!

    Speaking of return values, you did not check the returns from fopen() and fclose() - that is bad.

    There are other changes I made, but there were enough that I cannot remember them all. Have a look over the code, and if there is anything you don't understand, just ask.

    edit::

    Here is something kind of glitchy - I was using i for the one variable, but when I would do this:

    Code:
    (void) fgets(mainm[i].prod, 60, stdin);
    it was being interpreted as an opening italics tag - then the rest of the message was italicized. I assume this has been noticed before, or should I add it to the bugs page?
    ~/
    Last edited by kermit; 08-07-2005 at 07:32 PM.

  4. #4
    Registered User
    Join Date
    Aug 2005
    Posts
    51
    Thankyou kermit, I am grateful for your help, and the fact that you have actualy compiled and altered the code. When you're learning, books cant always help you in the way that another person can. I will now go and look at your revised code and start again.

  5. #5
    Registered User
    Join Date
    Aug 2005
    Posts
    51

    File wont append?

    Thanks also Kermit for fixing the %f so they print to screen in right format. The problem which I still have though is, when I add this small piece of code just above the at the top:

    Code:
    printf("\nAnother? (Y/N) "); 
                    if(getch() == 'n') break;
    and then compile and run. I can enter values to the array, and then terminate the loop by pressing n, which is OK. It will then print of what I entered and exit the program. But when I run the program again and enter more data, and then break the loop, it will only print of to me the input from the last time I executed the program, and anything after that is just a load of unreadable garbage. So it is not appending the next structure in the array like i want it to. The idea is that each time data is added it just saves it to the next empty structure. I want that break in there aswell so the user can quit when he/she wants to.

    It is probably something to do with the break statement at a guess.

Popular pages Recent additions subscribe to a feed

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21