# Is there a better way to code this block of C code?

This was a homework assignment that I'm now done with - I submitted it as is. However the fact that I needed to use the same code twice bugged me... The double code is:

printf("Enter a distance in inches (0 to quit): ");
scanf("%f",&input);


Is there a better way to do the same thing in my loop instead of the double scanf/printf? It does need to quit the program immediately if a 0 is entered.

#include <stdio.h>
int main()
{
float distance, floatFeet, input;
int feet;

printf("Enter a distance in inches (0 to quit): ");
scanf("%f", &input);
while (input != 0)
{
feet = input/12;
distance = (input-feet*12);
floatFeet = input/12;
printf("%d feet and %f inches or %f feet \n\n", feet, distance, floatFeet);
printf("Enter a distance in inches (0 to quit): ");
scanf("%f", &input);
}
}

-

## migrated from stackoverflow.comFeb 22 '13 at 15:41

This question came from our site for professional and enthusiast programmers.

there is a codereview.SO where questions like are better suited –  ratchet freak Feb 21 '13 at 14:29
And off we go... –  Michael Myers Feb 22 '13 at 15:41
I would flush the output before reading for the input.. –  renoX Feb 26 '13 at 9:10

In general, you would need to insert an explicit conditional somewhere in order to distinguish between the first iteration (when no results should be displayed before the prompt) and any subsequent ones. That's because the "do not display output" condition is different from the "exit program" condition, so you can't just shove both into the loop condition.

Since you are going to insert an if no matter what, you might as well make it break out of the loop and make the loop infinite:

while (1)
{
printf("Enter a distance in inches (0 to quit): ");
scanf("%f",&input);

if (input == 0) break;

feet = input/12;
inches = (input-feet*12);
floatFeet = input/12;
printf("%d feet and %f inches or %f feet \n\n",feet,inches,floatFeet);
}

-
In C, you'd probably want while(1), not while(true). –  Antimony Feb 21 '13 at 13:52
@Antimony: So true, thanks (no pun intended). I 've blown my cover! ;-) –  Jon Feb 21 '13 at 13:53
while (true) throws an 'undeclared' error at me, should I just use while (1)? –  Symon Feb 21 '13 at 13:57
ah okay thanks antimony, comments didn't refresh right away :P –  Symon Feb 21 '13 at 13:57
In C, the idiom for "infinite loop" is for(;;) { .... } –  vonbrand Feb 22 '13 at 1:56

You could move the duplicated lines into a function, something like this should work:

#include <stdio.h>

float get_input(void)
{
float input;

printf("Enter a distance in inches (0 to quit): ");
scanf("%f", &input);

return input;
}

int main()
{
float inches, floatFeet, input;
int feet;

while (input = get_input())
{
feet = input/12;
inches = (input-feet*12);
floatFeet = input/12;
printf("%d feet and %f inches or %f feet \n\n",feet,inches,floatFeet);
}

printf("Goodbye!\n");
}

-
+1. This is by far the most elegant solution. –  mskfisher Feb 21 '13 at 14:26
@mskfisher, thanks! Maybe out of scope though, if the OP has not learned about functions and such yet. –  harald Feb 21 '13 at 14:37
@Marton while(input = get_input()) checks whether input is 0. –  Daniel Fischer Feb 21 '13 at 14:43
@Marton It's not while(0), it's while(input) - except that input also gets assigned when the loop condition is evaluated. –  Daniel Fischer Feb 21 '13 at 14:56
@marco-fiset This is possible in C99 but not in classic C. C99 doesn't really seem to have set off yet –  Felix Dombek Feb 21 '13 at 15:13

You can use a do while loop, which will always execute once and check the condition at the end of the loop.

If you need the program to exit immediately without printing when a 0 is entered, you could just put the calculation and printing code in an if statement within the loop:

do {
printf("Enter a distance in inches (0 to quit): ");
scanf("%f",&input);
if( input != 0 ) {
feet = input/12;
inches = (input-feet*12);
floatFeet = input/12;
printf("%d feet and %f inches or %f feet \n\n",feet,inches,floatFeet);
}
} while (input != 0)


Or, to avoid repeating anything:

while(true) {
printf("Enter a distance in inches (0 to quit): ");
scanf("%f",&input);
if( input == 0 ) {
break;
}
feet = input/12;
inches = (input-feet*12);
floatFeet = input/12;
printf("%d feet and %f inches or %f feet \n\n",feet,inches,floatFeet);
}

-
This will work, although you will be repeating yourself with the exit condition. –  lc. Feb 21 '13 at 13:52
True, see edited version. –  Luke Feb 21 '13 at 13:54

You can replace this loop with a "forever" loop that exits from the middle of its body, like this:

for (;;) {
printf("Enter a distance in inches (0 to quit): ");
scanf("%f",&input);
if (input == 0) break;
feet = input/12;
inches = (input-feet*12);
floatFeet = input/12;
printf("%d feet and %f inches or %f feet \n\n",feet,inches,floatFeet);
}


There are multiple ways to do a "forever" loop; this one is borrowed from K&R's book.

-
Any reason to use a for loop instead of a while loop when making a 'forever' loop? –  Symon Feb 21 '13 at 13:55
@Symon I use for(;;) because it is a very common idiom popularized by "the" book on the C language. Other than that, there is no reason to go one way or the other: the compiler will generate identical binary code for both loops. –  dasblinkenlight Feb 21 '13 at 13:57
Some people even define: #define ever (;;) –  mouviciel Feb 21 '13 at 13:58
@mouviciel: People who have just not learned to leave the preprocessor alone if at all possible. –  Jon Feb 21 '13 at 13:59
@Symon In a compiler which does not optimize at all, while (1) might generate a comparison to a constant which is omitted in for (;;). However, all normal compilers would optimize that comparison away. –  Felix Dombek Feb 21 '13 at 15:06

Use do-while instead while.

#include <stdio.h>
int main()
{
float inches, floatFeet, input;
int feet;

do
{
printf("Enter a distance in inches (0 to quit): ");
scanf("%f",&input);
if (input == 0) break;
feet = input/12;
inches = (input-feet*12);
floatFeet = input/12;
printf("%d feet and %f inches or %f feet \n\n",feet,inches,floatFeet);
}
while (input != 0);
}

-
give the reason why vote down? –  Iswanto San Feb 21 '13 at 13:48
I didn't downvote but this doesn't work. It will still do some work after 0 is input. –  interjay Feb 21 '13 at 13:48
@Antimony The side effect is printing a line. I don't think that "shouldn't matter"...the code as edited will work though (although there is an extra comparison every time the loop loops). –  lc. Feb 21 '13 at 13:50
Also, if you're breaking out explicitly, there's no point in a do loop. Just make it while(1). –  Antimony Feb 21 '13 at 13:51
@Antimony The two methods may be functionally equivalent; but the do-while construct makes it explicit that it's not intended to be an infinite loop. That said, I'd probably replace the if (input == 0) break; construct with if(input !=0) { ...}and put the rest of the loop inside the {}'s to eliminate the second exit point from the loop as well. –  Dan Neely Feb 21 '13 at 14:05

This is exactly where you use the:

do {
//stuff
} while (condition)


... where you need to do something once, at least, but conditionally repeat the same task...

-

Symon, here is another alternative. Notice the following things:

1. I have separated getting input into a function, get_input. The function takes a pointer to a variable to accept the input value and checks whether scanf actually reads a value from the user input. It returns an integer value that is non-zero (true) if scanf really did read a value. The exit condition has changed to ctrl-d which is the standard UNIX way of indicating end-of-input. Equally, typing a non-numeric will also cause scanf to return 0.

2. The while loop now exits on failure of the input function.

3. The variables are defined at the point of use. This is better practice as it reduces the scope of the variable (ie. the amount of the code where it is valid).

4. distance is renamed inches, which seems more appropriate.

5. The division is done only once and there is a cast (int) to avoid a conversion compiler warning (turn many warnings ON in your compiler).

6. A new-line is printed on exit to be nice to the user.

#include <stdio.h>

static inline int get_input(float *input)
{
printf("\nEnter a distance in inches (ctrl-d to quit): ");
return scanf("%f", input) == 1;
}

int main(void)
{
float input;

while (get_input(&input) != 0) {

float float_feet = input / 12;
int feet = (int) float_feet;
float inches = input - (feet * 12);

printf("%d feet, %f inches or %f feet \n", feet, inches, float_feet);
}
putchar('\n');
return 0;
}

-