Calculating Blood Alcohol Content (BAC)

  • Thread starter Thread starter franznietzsche
  • Start date Start date
  • Tags Tags
    Alcohol Blood
Click For Summary

Discussion Overview

The discussion revolves around a programming issue related to calculating Blood Alcohol Content (BAC) in a C program. Participants explore the unexpected behavior of the program, specifically the double printing of a disclaimer message, and investigate potential causes related to input handling and buffer management.

Discussion Character

  • Technical explanation
  • Debate/contested

Main Points Raised

  • One participant describes the issue of the program printing a disclaimer message twice and shares the relevant code snippet.
  • Another participant suggests that there may be an issue with whitespace or an incorrect return character in the input buffer affecting the program's behavior.
  • A participant notes that the gender variable is initialized to 'c', but it appears to be reading a newline character instead, leading to unexpected behavior.
  • Several participants discuss the possibility that the newline character from previous input is being passed to the next scanf call, causing the loop to execute more than once.
  • One participant proposes using a getchar() function to clear the newline character from the buffer before the next input is read.
  • Another participant suggests moving the prompt for gender outside of the loop to prevent it from being printed multiple times.

Areas of Agreement / Disagreement

Participants generally agree that the issue stems from how input is handled in the program, particularly regarding newline characters in the buffer. However, there is no consensus on the best solution, as multiple approaches are suggested.

Contextual Notes

Participants mention that scanf is expected to ignore leading newlines and whitespace, but the behavior observed suggests that this may not be occurring as anticipated. The discussion does not resolve the underlying cause of the input handling issue.

Who May Find This Useful

Programmers working with C who are interested in input handling, buffer management, and debugging similar issues in console applications may find this discussion relevant.

franznietzsche
Messages
1,503
Reaction score
6
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:

#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);

while((gender!='m')&&(gender!='M')&&(gender!='f')&&(gender!='f')) {
printf("Enter your gender(m or 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;
}

The output is:

Welcome to the Percent Blood Alcohol Calculator!



Enter the number of drinks you've had so far: 5

How many hours ago did you start drinking: 1

Enter your gender(m or f): Enter your gender(m or f): m

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

Your BAC is: 0.118923



**Discalimer: The information from this calculator is only an estimate**

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.
 
Computer science news on Phys.org
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:
 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.
 
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.
 
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.
 
Ok, i added that line like you suggested and the output becomes:

Welcome to the Percent Blood Alcohol Calculator!

Enter the number of drinks you've had so far: 5
How many hours ago did you start drinking: 1
Enter your gender(m or f): Test output buffer char
10
Enter your gender(m or f): m
Test output buffer char m 109


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

Your BAC is: 0.118923

**Discalimer: The information from this calculator is only an estimate**

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?
 
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.
 
Question is it 10 each time? Or does it change each time you run the program?
 
Davorak said:
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.


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...
 
Davorak said:
Question is it 10 each time? Or does it change each time you run the program?

10 is the ASCII code for a newline. And it is 10 each time.
 
  • #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.
 
  • #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.
 
  • #12
So it willl not reask the question 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?
 
  • #13
All you have to do is add a getchar() to your while loop (in your original program), like this:

Code:
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.
 
  • #14
Davorak said:
So it willl not reask the question 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?

Exactly.

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?

Gcc-3.3.4, on Linux.

I don't do any work for anything in windows. Not voluntarily anyway.
 
  • #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;
}
 
  • #16
Thats what i already did.
 
  • #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.
 
  • #18
Did you guys read post #13?
 
  • #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.
 
  • #20
gnome said:
Did you guys read post #13?


Yes. And i liked that idea more than moving the prompt out of the loop, but i had submitted it already.