0

But the calculation doesn't work or change when I run it and plug in any random number...need some guidance. I'm a novice to C and programming in general so please include easy to understand help.

 #include <stdio.h>
double const change_celcius = 32.0;
double const change_kelvin = 273.15;

void temperatures(double n);

int main(void)
{
    int q = 'q';
    double user_number;

    printf("Enter the fahrenheit: \n");
    scanf("%f", &user_number);

    while (user_number != q)
    {
        temperatures(user_number);
        printf("\n");
        printf("Enter the fahrenheit: \n");
        scanf("%f", &user_number);
    }
}

void temperatures(double n)
{
    double celsius, kelvin;

    celsius = 5.0 / 9.0 * (n - change_celcius);
    kelvin = 5.0 / 9.0 * (n - change_celcius) + change_kelvin;

    printf("fahrenheit: %.2f - celsius is: %.2f - kelvin is: %.2f", 
            n, celsius, kelvin);

}
dazedandconfused
  • 33
  • 2
  • 2
  • 7

5 Answers5

3

I don't believe the all the use %lf instead of %f comments, by themselves, fix your program. The handling of q (for "quit") is also problematic so let's fix that too. First, we'll use POSIX function getline() to read it into a string and test if it's "q". If not, we'll sscanf it into a double and use it as our temperature:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

double const change_celsius = 32.0;
double const change_kelvin = 273.15;

void temperatures(double n)
{
    double celsius = 5.0 / 9.0 * (n - change_celsius);
    double kelvin = 5.0 / 9.0 * (n - change_celsius) + change_kelvin;

    printf("fahrenheit: %.2f - celsius is: %.2f - kelvin is: %.2f\n", n, celsius, kelvin);
}

int main(void)
{
    char *user_string = NULL;
    ssize_t user_string_length;
    size_t user_string_capacity = 0;

    while (1)
    {
        printf("Enter the fahrenheit: ");

        if ((user_string_length = getline(&user_string, &user_string_capacity, stdin)) < 1)
            break;

        if (strncmp(user_string, "q\n", (size_t) user_string_length) == 0)
            break;

        double user_number;

        if (sscanf(user_string, "%lf", &user_number) == 1)
            temperatures(user_number);
    }

    if (user_string != NULL)
        free(user_string); // free memory allocated by getline()

    if (user_string_length == -1)
        putchar('\n'); // output courtesy newline if user used ^D to exit

    return(0);
}

We check the return value of sscanf so that bad input won't cause the program to recalculate using the last good input. Instead, it will just prompt again for input.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
cdlane
  • 40,441
  • 5
  • 32
  • 81
  • This is the correct answer. You are reading a float into a double, then testing it as an int (which won't work, because scanf is looking for a floating-point number; it won't just grab a `q` incidentally, and even then, the 'q' will be cast to an inexact double for equality testing, which will break). OP needs to work more to understand how scanf works in the first place here, and how function arguments are cast. – Taywee Aug 28 '16 at 19:01
  • `scanf("%s", user_string);` is a bad as `gets()` which has no buffer protection. Suggest `fgets()`. – chux - Reinstate Monica Aug 28 '16 at 19:47
  • @chux, thanks. Instead I used this as an opportunity to rewrite it with `getline()` and restructure the loop. – cdlane Aug 29 '16 at 02:09
1

You need to use "%lf" in scanf() and print() to read and write the value of type double.

Note that the printf() will work with "%f" too.

For more details please refer : Why does scanf() need "%lf" for doubles, when printf() is okay with just "%f"?

Community
  • 1
  • 1
Shravan40
  • 8,922
  • 6
  • 28
  • 48
1

There are several issues that can be addressed in your code. First, always (Always, in case it wasn't clear) check the return of scanf. That is the only way you know whether the expected number of conversions took place -- and whether you have an actual value to work with in your code.

The return also holds the key to exiting the loop when the user enters 'q' (or anything that causes the conversion to double to fail). By simply checking

if (scanf(" %lf", &user_number) == 1)

You can determine whether to process the value as a temperature, or tell the user has indicated exit.

Another tip, never (Never) write:

printf ("\n");

Why would you want to call a variadic function simply to output a single char? That is what putchar (or fputc) is for, e.g.:

putchar ('\n');

Putting those pieces together, and noting that %lf is used as the format specifier for double, you can rewrite your code, and format the output in quite a bit fewer lines, e.g.

#include <stdio.h>

double const change_celcius = 32.0;
double const change_kelvin = 273.15;

void temperatures (double n);

int main(void)
{
    double user_number;

    while (printf ("\nEnter temp in degrees fahrenheit: ") && 
            scanf(" %lf", &user_number) == 1)
        temperatures(user_number);

    return 0;  /* main() is type 'int' and returns a value to the shell */
}

void temperatures (double n)
{
    double celsius, kelvin;

    celsius = 5.0 / 9.0 * (n - change_celcius);
    kelvin = 5.0 / 9.0 * (n - change_celcius) + change_kelvin;

    printf("  fahrenheit: % 7.2lf\n  celsius is: % 7.2lf\n  kelvin is : % 7.2lf\n", 
            n, celsius, kelvin);

}

Example Use/Output

$ ./bin/temps

Enter temp in degrees fahrenheit: 212
  fahrenheit:  212.00
  celsius is:  100.00
  kelvin is :  373.15

Enter temp in degrees fahrenheit: 0
  fahrenheit:    0.00
  celsius is:  -17.78
  kelvin is :  255.37

Enter temp in degrees fahrenheit: 68
  fahrenheit:   68.00
  celsius is:   20.00
  kelvin is :  293.15

Enter temp in degrees fahrenheit: q

Always compile your code with at minimum -Wall -Wextra warnings enabled (and if you really want to drill down, add -pedantic). Read the warnings and fix them. All of your code should compile without warning before you consider your code reliable at this stage of the game.

Look all answers over, and let me know if you have any questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • `printf ("\n");` vs. `putchar ('\n');` --> A good compiler will emit the same code. Code what is most understandable for the reviewer/maintainer.. – chux - Reinstate Monica Aug 28 '16 at 19:46
  • I don't know, I have slight disagreement with that. (not with what the compiler will do) Rather, if it is more understandable for the reviewer/maintainer to condone using a *line-orieinted* output function where *character-oriented* output is required, the reviewer/maintainer is failing to reinforce an understanding of the I/O taking place. I see your point, but from a learning standpoint, if it is coded properly to begin with, you don't have to worry about the compiler substituting the correct function in place of the one coded by the programmer. – David C. Rankin Aug 28 '16 at 21:24
  • One bit that causes me concern is treating `printf()` as a boolean so you can slip in a compound statement: `while (printf("...") && scanf(...) == 1)` Is this an acceptable C idiom that should be passed onto new programmers? (I.e. good C style but bad programming style.) Or are you genuinely concerned about `printf()` failure here (but not in `temperatures()`)? – cdlane Aug 29 '16 at 02:29
  • All of the `printf` functions return *the number of characters printed* (excluding the *nul-byte*). So you are guaranteed a positive value unless you intentionally pass an *empty-string* as the format specifier. So syntactically it is fine, but yes, it is simply to save the additional repetition of the `printf` call. As for the propriety of its introduction to new programmers, it is partially intended to provoke thought. (a bit of Socratic teaching if you will) – David C. Rankin Aug 29 '16 at 03:36
0

To read Double use %lf instead of %f. for double printf() will work with %f also.

Tanuj Yadav
  • 1,259
  • 13
  • 21
0

The calculation seems to be okay; however the you are not reading in the words properly

scanf("%f", &user_number);

You are stating you are reading in a float, yet you are declaring user_name as a double. If you wanted to use a float, you would need to change the user_name declaration from double to float. If you wanted to use a double use "%f".