2

I'm new to programming I'm about to write my first programs. I successfully installed VS Code and MinGW 64 on my Windows 10 system. My program is compiling and the scanf is recognised by the compiler. The problem is that it gives 0 as an output for the variable. The code has German comments because of my German background. Please bear with me, I'm new to programming.

The code is as follows:

#include <stdio.h>

int main()
{
    const double PI = 3.14159;  // Kreiskonstante pi
    double r = 0.0;             // Radius der Kugel
    double A = 0.0;             // Oberfläche der Kugel
    double V = 0.0;

    // Radius vom Benutzer einlesen
    printf("Kugelradius: ");
    scanf("%.2lf", &r);

    // Oberfläche berechnen
    A = 4.0 * PI * r * r;

    // Hier Code zur Volumenberechnung angeben
    V = (4.0 / 3.0) * r * r * r * PI;

    // Ausgabe des Ergebnisses
    printf("Radius: %.2lf\n", r);
    printf("Oberflaeche: %.2lf\n", A);

    // hier Code für Ausgabe des Volumens angeben
    printf("Volumen: %.2lf\n", V);
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 3
    What is your input? What is your expected full output? What is your actual full output? Please [edit] your question to tell us. – Some programmer dude Aug 14 '23 at 08:43
  • 2
    What input are you giving it? – Lundin Aug 14 '23 at 08:43
  • 1
    Welcome to SO. you should check the return value of `scanf`. Does it return `1`? – Gerhardh Aug 14 '23 at 08:44
  • 1
    And have you tried to [*debug*](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) your program? For example using a [*debugger*](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) to step through the code line by line while monitoring variables and their values? For this it helps to break down longer expressions into simpler and smaller expressions, saving their intermediate results in temporary variabled. – Some programmer dude Aug 14 '23 at 08:45
  • Oh, and you really should check what `scanf` [*returns*](https://en.cppreference.com/w/cpp/io/c/fscanf#Return_value). – Some programmer dude Aug 14 '23 at 08:45
  • Since you mention german background: do not use decimal commas! Use decimal points insted in your input – Gereon Aug 14 '23 at 08:46
  • What happens when you replace ```scanf("%.2lf", &r);``` with ```scanf("%lf", &r);```? – cforler Aug 14 '23 at 08:50
  • 1
    Do you get any warnings from the compiler? GCC 11 on Ubuntu warns me that the format is invalid (there should be no dot in the format). In general, you should also check the return value of `scanf` and enable the warnings in your compiler (and make sure they are understood or fixed). – Simon Doppler Aug 14 '23 at 08:58
  • 1
    Welcome to Stack Overflow! You might enjoy reading [this](https://blog.inkforall.com/bear-with-me-or-bare-with-me) – chqrlie Aug 14 '23 at 09:14
  • As a side note, your comments are useless. Instead, give your variables descriptive names. Comments should never explain what the code is doing. Only HOW. I understand you're a beginner but it's best not to make a habit out of it. Instead of `double A = 0.0; // Oberfläche der Kugel` why not simply write `double surfaceArea = 0.0`; it is immediately clear even 20 lines further below what that variable is about. – infinitezero Aug 14 '23 at 09:21
  • @infinitezero: I agree with you, yet `surfaceArea` is somewhat ambiguous, `sphereSurfaceArea` would better convey the actual meaning of *Oberfläche der Kugel*. – chqrlie Aug 14 '23 at 09:32
  • 1
    @chqrlie true but depends on context. For example, within a function "calculateSphereProperties" it would be redundant. – infinitezero Aug 14 '23 at 09:34

2 Answers2

5

scanf() does not support a precision field as printf does. The . causes scanf() to fail and return the successful conversions so far, ie: 0.

There is no simple way to ensure the user types 2 digits after the decimal point, %lf accepts the full floating point syntax according to the current locale, which I strongly recommend to leave unchanged as the default C locale.

You should use just %lf and always test the return value of scanf(). As a matter of fact, it is recommended to read a line of input with fgets() and parse it with sscanf() to detect and report conversion failures.

Also note that printf does not require the l for double values, as floating point values of type float are automatically converted to double when passed to vararg functions. printf ignores the l for %f and other floating point conversions.

Since you are using the GNU toolchain, you should enable more warnings with -Wall -Wextra -Werror to let the compiler detect and reject many potential bugs such as this invalid format in scanf().

Here is a modified version:

#include <stdio.h>

int main(void)
{
    const double PI = 3.14159;  // Kreiskonstante pi
    double r = 0.0;             // Radius der Kugel
    double A = 0.0;             // Oberfläche der Kugel
    double V = 0.0;
    char buf[80];

    // Radius vom Benutzer einlesen
    printf("Kugelradius: ");
    if (!fgets(buf, sizeof buf, stdin)) {
        printf("Keine Daten\n");
        return 1;
    }
    if (sscanf(buf, "%lf", &r) != 1) {
        printf("Konvertierungsfehler: %s\n", buf);
        return 1;
    }

    // Oberfläche berechnen
    A = 4.0 * PI * r * r;

    // Hier Code zur Volumenberechnung angeben
    V = (4.0 / 3.0) * r * r * r * PI;

    // Ausgabe des Ergebnisses
    printf("Radius: %.2f\n", r);
    printf("Oberflaeche: %.2f\n", A);

    // hier Code für Ausgabe des Volumens angeben
    printf("Volumen: %.2f\n", V);
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • The C standards other than C90 recognize `%lf` etc for `printf()` — and symmetry with `scanf()` makes it perfectly sensible to use it (unless C90 conformance is an issue, which it should not be — it's time to upgrade if it is). – Jonathan Leffler Aug 14 '23 at 13:56
  • 1
    @JonathanLeffler: I don't disagree, but symmetry might be the reason the OP used `"%.2lf"` in the first place. – chqrlie Aug 14 '23 at 14:21
  • 1
    Well, that `.2` part in a `scanf()` conversion specification is incorrect regardless of whether it is followed by `lf` or not. That asymmetry is unfortunate, as is the choice to use `*` in `scanf()` to suppress assignment instead of allowing the size to be configured as in `printf()`. Ancient history causes these quirks, sadly. – Jonathan Leffler Aug 14 '23 at 14:25
2

Probably the culprit: scanf("%.2lf", &r);

You should only restrict the number during printing. %.2lf will cause scanf to fail, just do %lf instead. Also ensure that only the . decimal separator is used.

If you actually need detailed input formatting control, it might be easier to read the number as a string, which can then be verified in detail before passed on to a double.


Also please note than some versions of the stdio.h lib used by Mingw had poor C99 (or later) compliance. %lf in printf was only standardized in C99. On some older versions you had to add this:

#define __USE_MINGW_ANSI_STDIO 1
#include <stdio.h> // now we can include the header and use it as expected

This shouldn't be necessary in latest Mingw64, but only if you are using an older version of the compiler.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • The format specifier is the culprit, `scanf` doesn't have precision specifiers, only field width (so not `.` in the format). GCC 11 on Ubuntu warns about it even with no warning flags enabled. – Simon Doppler Aug 14 '23 at 09:02