Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

C code problem

  1. Apr 21, 2005 #1
    Figured this forum might be able to help more than the homework help, if not, feel free to redirect.

    I'm writing a program that calculates Blood Alcohol Content from various input the user gives (nothing fancy, straight forward simple calculation, prompting user for data, that sort of thing).

    However it is doing something weird, and I cannot figure out for the life of me why it is doing this. The code is:

    The output is:

    What i can't figure out is why its printing that message (in bold) twice. I've checked the loop that prints that part in the code(also bolded) and have no idea what is wrong with it.
     
  2. jcsd
  3. Apr 21, 2005 #2
    Are you piping this info into the program?
    If so there might be a whitesapce or a incorect return char after you timeDrinking.

    In any case it looks like there is somethign waitin gon the buffer for you that is not m, M, F,f.

    Less likely answer is if you are typing it in by hand that the concole you are using uses a return char that is not regonized by scanf.

    Find out what is there on the buffer by:
    Code (Text):

     while((gender!='m')&&(gender!='M')&&(gender!='f')&&(gender!='f')) {
    printf("Enter your gender(m or f): ");
    scanf("%c", &gender);
    printf("Test output buffer char: %c %i \n",gender,gender);
    }
     
    That will at least tell you what is on the buffer.
     
  4. Apr 21, 2005 #3
    I should have clarified, when it prints that bolded line, it only prompts me once, its prints both statements as one.

    I initialised gender when i declared so that it was 'c', so the loop would run once for sure, and keep running until a proper input was given. But it double prints the prompt for some reason.
     
  5. Apr 21, 2005 #4
    Right, probably because something is on the buffer before it enters the loop.

    Then the program prints out your question. Scanf reads form the buffer and finds something, but it is not m,M,f,F so the loop runs again but this time the buffer is empty so it waits for your input.

    This is just a guess btw.
     
  6. Apr 21, 2005 #5
    Ok, i added that line like you suggested and the output becomes:

    For some reason its not initialising gender correctly, since its supposed to be initialised to 'c' which is not 10(it should be 99). In fact, its initialising gender as a newline character....hmmm....Any idea why?
     
  7. Apr 21, 2005 #6
    I was right something is on the buffer waiting for scanf.

    The 10 is not inside the gender variable, it is in the input buffer. The buffer holds the input from the keyboard and other sources, then you program reads from the buffer to get its input.

    You have two options, try and track down the source of the random char on the buffer, or if it is always something off the alphabet chart, just If statement out the printf statement when it is not in the correct range.
     
  8. Apr 21, 2005 #7
    Question is it 10 each time? Or does it change each time you run the program?
     
  9. Apr 21, 2005 #8

    Right, the 10 is not the gender variable, but the newline character right before it is. So what's happening is the previous scanf for weight, reads in the weight, but then went i hit enter the newline character gets passed to the next scanf, so i need to do something to prevent that....

    If i enter 1m for the time drinking, it reads the m into gender and jumps right out of the loop. So for some reason, whatever i enter immediately after the time drinking gets passed to scanf....
     
  10. Apr 21, 2005 #9
    10 is the ASCII code for a newline. And it is 10 each time.
     
  11. Apr 21, 2005 #10
    Sounds like you just need to burn the newline then.

    scanf(%c,&gender);

    while(...

    It also sounds like two spreate return chars are being used by the console and scanf only burns the first of the two. I think they are called newline and the return carriage. The console is putting them both in the buffer while scanf only expects there to be one.
     
  12. Apr 21, 2005 #11
    I fixed the problem.

    Rather than trying to stop it from running the loop twice unnecessarily, i just pulled the printf statement that prompted the user out of the loop, so that no matter how many times the loop is run the prompt only appear once. So when the newline char gets passed to scanf and the loop runs a second time it is invisible to the user.
     
  13. Apr 21, 2005 #12
    So it willl not reask the quesiton if the user enters in the wrong input?

    Enter your gender(m or f):h
    j
    k
    l
    m

    How much do you weigh (yes, your real weight):

    Something like that?

    It is also odd that it is not ignored in the first place scanf is supposed to ignore leading newlinesk, whitespaces, and carriage.

    What library are you useing?
    Are using the command console? I would assume with windows nt or higher?
     
  14. Apr 21, 2005 #13
    All you have to do is add a getchar() to your while loop (in your original program), like this:

    Code (Text):

    while((gender!='m')&&(gender!='M')&&(gender!='f')&&(gender!='f')) {
        getchar();
        printf("Enter your gender(m or f): ");
        scanf("%c", &gender);
    }
     
    Your problem is each time the user enters a response (ended by a newline) to a question, scanf leaves the newline character in the buffer. On the next call to scanf, if scanf is looking for a number it discards that newline & keeps looking (and takes the number that the user enters). But in the while loop, scanf is looking for a char, so it simply accepts that leftover newline as the response & stores that as the value of gender. Adding getchar() soaks up and discards the extra newlines.
     
  15. Apr 23, 2005 #14
    Exactly.

    Gcc-3.3.4, on Linux.

    I don't do any work for anything in windows. Not voluntarily anyway.
     
  16. Apr 23, 2005 #15
    This will correct the problem!

    #include<stdio.h>

    #define POUNDS_PER_KILO 2.2406
    #define OZ_ALCOHOL_PER_DRINK 0.54
    #define PERCENT_WATER_MALE 0.58
    #define PERCENT_WATER_FEMALE 0.49
    #define GRAMS_ALC_PER_OZ 23.36
    #define PERCENT_WATER_BLOOD 0.806
    #define METABOLISM_RATE 0.012

    int main(void)
    {

    float numDrinks, weight, bac, mlWater, gramsAlc, alcPerMlWater, alcPerMlBlood, timeDrinking;
    char gender = 'c';

    printf("Welcome to the Percent Blood Alcohol Calculator!\n\n");
    printf("Enter the number of drinks you've had so far: ");
    scanf("%f", &numDrinks);

    printf("How many hours ago did you start drinking: ");
    scanf("%f", &timeDrinking);

    printf("Enter your gender(m or f): ");
    while((gender!='m')&&(gender!='M')&&(gender!='f')&&(gender!='F')) {

    scanf("%c", &gender);
    }

    printf("How much do you weigh (yes, your real weight): ");
    scanf("%f", &weight);

    if (gender == 'M' || gender == 'm') {
    mlWater = weight/POUNDS_PER_KILO * PERCENT_WATER_MALE*1000;
    }else if(gender=='F' || gender == 'f') {
    mlWater = weight/POUNDS_PER_KILO * PERCENT_WATER_FEMALE*1000;
    }

    gramsAlc = numDrinks*OZ_ALCOHOL_PER_DRINK*GRAMS_ALC_PER_OZ;
    alcPerMlWater = gramsAlc / mlWater;
    alcPerMlBlood = alcPerMlWater * PERCENT_WATER_BLOOD;
    bac = alcPerMlBlood * 100;
    bac = bac - METABOLISM_RATE * timeDrinking;

    printf("Your BAC is: %f\n", bac);

    printf("\n**Discalimer: The information from this calculator is only an estimate**\n");
    printf(" In fact, you're probably not the least bit inebriated, go have five more.\n");

    return 0;
    }
     
  17. Apr 23, 2005 #16
    Thats what i already did.
     
  18. Apr 23, 2005 #17
    What did you change asher. You have "printf("Enter your gender(m or f): ");" out side of the loop, but franznietzsche already did that.
     
  19. Apr 23, 2005 #18
    Did you guys read post #13?
     
  20. Apr 24, 2005 #19
    One solution is to use a character string. Instead of
    ...
    scanf("%c", &gender);
    ....

    I would declare 'gender' to be a string, and then test

    char gender[10];

    ....

    do {
    printf("Enter your gender(m or f): ");
    scanf("%s", &gender);
    }
    while((gender[0]!='m')&&(gender[0]!='M')&&(gender[0]!='f')&&(gender[0]!='F'))

    I believe the more elegant alternative is to use getchar() and echo the output, like so:
    do {
    printf("Enter your gender(m or f): ");
    gender = getchar();
    printf(gender);
    }
    while((gender!='m')&&(gender!='M')&&(gender!='f')&&(gender!='F'))

    getchar() avoids having to deal with a newline, as it returns as soon as a key is pressed.
     
  21. Apr 24, 2005 #20

    Yes. And i liked that idea more than moving the prompt out of the loop, but i had submitted it already.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?



Similar Discussions: C code problem
  1. A C problem (Replies: 9)

Loading...