1

I just started to learn programming, and in school the teacher used a Macbook and a program called "X-Code", and at home I have windows with Visual Studio (2017). The teaches gave 0 explanation on what "setbuf" is, and also said that we have to use scanf a little different in Visual Studio. Now I'm at home and completely helpless. Actually VS said that it would better to try scanf_s, so I did, and the program runs until I could input the "Operation". After I input the first two arguments, it stops, and the window closes itself. Can any of you help me, and give me a bit of an explanation on the things I don't understand?

Thanks in advance. Here is the code, that I have written

void main() {

    int a, b, c;
    char m;

    printf("Erstes Argument: ");
    scanf_s("%d", &a);

    printf("Zweites Argument: ");
    scanf_s("%d", &b);

    printf("Operation: "),
    //setvbuf(stdin,NULL); 
    scanf_s("%c", &m);

    if (m == '*') {
        c = a * b;
        printf("%d * %d = %d \n", a, b, c);
    }
    else {
        printf("Falsche Operation! \n");
    }

    return 0;
}
cleblanc
  • 3,678
  • 1
  • 13
  • 16
  • 1
    *Actually VS said that it would better to try scanf_s* Yes, Visual Studio promotes non-portable, Microsoft-specific language extensions with misleading messages about functions **that are required by the C Standard** being "deprecated". See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm: "As a result of the numerous deviations from the specification the Microsoft implementation cannot be considered conforming or portable." See also https://stackoverflow.com/questions/119578/disabling-warnings-generated-via-crt-secure-no-deprecate – Andrew Henle Sep 06 '18 at 16:20
  • You can read about MSVC 2017 library function `setbuf` [here](https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setbuf?view=vs-2017). Bookmark this page, for future reference. – Weather Vane Sep 06 '18 at 16:20
  • 1
    Your teacher might have a different opinion than mine: MS wants to rule the world and *warns* about standard functions it thinks you should not be using. Please stick to C standard functions. Before any `#include` directives I place the following 3 lines in MSVC code: `#define _CRT_SECURE_NO_WARNINGS` and `#define _CRT_SECURE_NO_DEPRECATE` and `#define _CRT_NONSTDC_NO_DEPRECATE`. Sadly some of their so-called "safer" versions are no safer at all, or there are safe ways to use the standard function. In particular their `scanf_s` family is even trickier to use than the standard functions. – Weather Vane Sep 06 '18 at 16:22
  • For example, you have used `scanf_s("%c", &m);` incorrectly, because it requires a length argument: *"Unlike `scanf` and `wscanf`, `scanf_s` and `wscanf_s` require the buffer size to be specified for all input parameters of type `c`, `C`, `s`, `S`, or string control sets that are enclosed in `[]`. The buffer size in characters is passed as an additional parameter immediately following the pointer to the buffer or variable."* – Weather Vane Sep 06 '18 at 16:25
  • Better install x-code on your home computer and forget about MS for C programming. That's a general advice. – Eugene Sh. Sep 06 '18 at 16:25
  • @EugeneSh. Neat trick, since the OP's computer is Windows and the instructors is a Mac. – WhozCraig Sep 06 '18 at 16:26
  • @WhozCraig Woops. Was sure x-code is portable. – Eugene Sh. Sep 06 '18 at 16:28
  • @EugeneSh. VS Code is portable (and appears to be what the instructor is using), Xcode is far from it. Perhaps that's what you meant. I'm not sure why clebanc edited the question to change what the OP had for the instructor using a program called "Code" to "X-Code" It is very likely the OP posted that part correctly. – WhozCraig Sep 06 '18 at 16:28
  • Your program crashed. My MSVC compiler gives detailed warnings about `scanf_s("%c", &m);` *— warning C4473: 'scanf_s' : not enough arguments passed for format string — note: placeholders and their parameters expect 2 variadic arguments, but 1 were provided — note: the missing variadic argument 2 is required by format string '%c' — note: this argument is used as a buffer size.* – Weather Vane Sep 06 '18 at 16:39

1 Answers1

1

If you wanted to use all the MS nuances and non-portable library calls, you can do so, but understand that in the end it is teaching you to code using functions that are not documented with the language standard.

To that end, also understand the C "language" has two primary components: the actual language itself (what makes it C code), and an mandatory accompanying library of standard functions (some of which you're familiar with, printf, scanf, etc). One can learn the first part, the language, and understand how it works independent of the accompanying standard library. In the end, the latter (the library) provides you a plethora of operations that you can utilize, and if you stay strictly within those defined by the standard, your code will be more robust, portable, and understandable by any C engineer familiar with said-same.

Regardless, the minimal change to make your program "work" using library extensions Microsoft chose to foist upon users of their implementation is:

#include <stdio.h>

// FIXED return type
int main() {

    int a, b, c;
    char m;

    printf("Erstes Argument: ");
    scanf_s("%d", &a);

    printf("Zweites Argument: ");
    scanf_s("%d", &b);

    printf("Operation: ");

    // FIXED arguments passed to setvbuf
    setvbuf(stdin, NULL, _IONBF, 0);

    // FIXED arguments passed to scanf_s
    // FIXED added white space consumption prior to character read
    scanf_s(" %c", &m, 1);

    if (m == '*') 
    {
        c = a * b;
        printf("%d * %d = %d \n", a, b, c);
    }
    else 
    {
        printf("Falsche Operation! \n");
    }

    return 0;
}

A proper, standard compliant version with no dependence on MS-isms could be:

#include <stdio.h>

int main() {

    int a, b, c;
    char m;

    printf("Erstes Argument: ");
    scanf("%d", &a);

    printf("Zweites Argument: ");
    scanf("%d", &b);

    printf("Operation: ");
    scanf(" %c", &m);

    if (m == '*') 
    {
        c = a * b;
        printf("%d * %d = %d \n", a, b, c);
    }
    else 
    {
        printf("Falsche Operation! \n");
    }

    return 0;
}

Without the feature disablement macro _CRT_SECURE_NO_WARNINGS, you'll be greeted with a plethora of three warnings from MS stating you should be using their "more secure" functions. While valiant of them to try and make our programs more secure , one could easily argue how it would be better if engineers simply learned how to properly write more secure code.

Finally, your code isn't done. You should be checking your IO calls for success. Right now you're assuming whatever the user provided as input for a and b, they're properly parsed, valid integers. If that isn't the case, your code marches on, ultimately using indeterminate data for calculation, and invoking undefined behavior in the process. scanf has a documented return code for a reason. Use it.

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • Nice touch with the `" %c"` containing a space, which will consume any leading whitespace, which OP may not know is done automatically by most format specifiers, but not by `"%c"`. – Weather Vane Sep 06 '18 at 17:04