0

It seems like there is problem in scanf_s Here is my code.

#include <stdio.h>
#include "stack.h"
int main(){ 
    int disk;
    int hanoi[3][9];
    char input[3] = { 0,0,0 };
    int moveDisk;

    for (int i = 0; i < 9; i++) {
        hanoi[0][i] = i + 1;
        hanoi[1][i] = 0;
        hanoi[2][i] = 0;
    }

    printf("Insert the number of disks(1~9): ");
    scanf_s("%d", &disk);

    while (input[0] != 'q') {
        printf("%3c %3c %3c\n", 'A', 'B', 'C');
        for (int i = 0; i < disk; i++) {
            printf("%3d %3d %3d\n", hanoi[0][i], hanoi[1][i], hanoi[2][i]);
        }
        scanf_s("%s", &input); //getting moving disk -- LOCATION OF ERROR
    }
}

I have no idea how to solve this

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
yoon-seul
  • 13
  • 3
  • There are no italics in your code. What are you entering for input? – Scott Hunter Jul 04 '21 at 10:48
  • oh, the last part of the code " scanf_s("%s", &input);" this part. Visual Studio says this part is the problem – yoon-seul Jul 04 '21 at 10:50
  • This doesn't *do* anything with `input` other than detect entering a `q`. – Scott Hunter Jul 04 '21 at 10:53
  • 0xFEFEFEFE means [*OS fill heap memory, which was marked for usage, but wasn't allocated by `HeapAlloc()` or `LocalAlloc()`. Or that memory just has been freed by `HeapFree()`*](https://stackoverflow.com/a/370362/995714) – phuclv Jul 04 '21 at 11:19
  • `scanf_s("%s", &input);` replace by `scanf_s("%s", input);`. The identifier `input` used alone is passed as a pointer to scanf_s. This is anyway dangerous if the user enter more than 2 characters! Better input using `fgets`. – fpiette Jul 04 '21 at 11:37
  • Its a coding error, you need to solve it in coding, debugging it is already broken. You _find_ the error during debugging. To _solve_ it you have to modify the code.. Be assured any problem is unlikely to be "_in scanf_s_", rather then in _your_ usage of it. – Clifford Jul 04 '21 at 13:41
  • `char input[3] = { 0 };` is sufficient to initialise all elements to zero. – Clifford Jul 04 '21 at 13:43
  • OT: regarding: `char input[3] = { 0,0,0 };` this is trying to stuff three integers into the array. Perhaps you meant: `char input[3] = { '0','0','0' };` – user3629249 Jul 05 '21 at 12:27
  • regarding: `char input[3] = { 0,0,0 };` and `scanf_s("%s", &input);` the `%s` is for inputting char arrays, suggest using ` %c` (notice the leading space) to consume leading 'white space' and input a single character – user3629249 Jul 05 '21 at 12:33
  • regarding: `scanf_s("%s", &input);` in C, a bare reference to an array degrades to the address of the first byte of the array. Therefore, the `&` is not needed – user3629249 Jul 05 '21 at 12:36
  • when moving a disk, you will need both a source AND a destination – user3629249 Jul 05 '21 at 12:38

3 Answers3

1

How can I solve this problem during debugging?

Run your program step by step using the debugger. Then when you get the exception, you've found the line causing it.

Restart your program and go up to the line where the exception will occur. That is stop on that line without execution it.

Then with the debugger, you can look at all variables and try to understand if their value is what you expect.

Does this answered your question?

BTW: The compiler should at least emitted some warnings. You really should first fix those warnings. If you have no warning, make sure you have turned on all warnings in the compiler options.

fpiette
  • 11,983
  • 1
  • 24
  • 46
1

You cited the line

scanf_s("%s", &input);

There are several things wrong with this line:

  1. You are reading a string into a character array. This is an exception to the normal pattern for scanf, in that you do not need the &.

  2. You are using the semistandard scanf_s, instead of the normal scanf. scanf_s is supposed to be "safer", but in order for it to provide its safetiness guarantees you have to call it differently than normal scanf, too. You have to tell it the size of the array you're reading the string into. Combined with #1 above, I believe a more correct call would be scanf_s("%s", input, 3);.

  3. For most purposes, a string of size 3 would be far too small for reading a line of input from the user. Since in this case I guess you're only reading a "line" to give yourself an opportunity to hit RETURN before the program makes another trip through its loop, I guess it's okay.

  4. As I mentioned, scanf_s is not quite Standard, so using it is a mixed bag. Pros: 1. It's allegedly safer. 2. Some people (including perhaps your instructor) will recommend always using it for that reason. Cons: 3. It's nut fully standard (it's an optional part of the standard) meaning that not all C compilers and libraries will support it. 4. Its calling patterns are necessarily quite different than normal scanf; it is not a drop-in replacement, so confusion is likely. (I'm not saying "don't use scanf_s", but you should be aware of its somewhat dubious status.)

  5. If you want to read a line of input from the user before continuing, and if the line might be a "q" or something else, scanf (of any variety) might not be the best choice. In particular, %s wants to read a non-whitespace string, so if you just hit the Return key, it's going to keep waiting. This might or might not be a problem for you. (Or it might not be something you need to worry about right now; you may have bigger fish to fry.)

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
  • @Clifford Thanks for the tip about the argument order. Neither of the first two compilers I tried supports `scanf_s`, so I couldn't test. – Steve Summit Jul 04 '21 at 13:58
  • @Clifford My usage of the literal `3` is a deliberate compromise. When you're just learning, there's only so much you can learn at once. Using `sizeof` in cases like this, though clearly vastly preferable in the long run and for production code, can also be an unnecessary distraction when the learner probably isn't ready to worry about that kind of maintenance issue yet. (And when it comes to scanf and variants, I believe there *is* no long-term future!) – Steve Summit Jul 04 '21 at 14:01
  • 1
    [You're being waaay too kind with your description of Microsoft's "safer" functions like `scanf_s()`](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm#impementations): "Microsoft Visual Studio implements an early version of the APIs. However, the implementation is incomplete and conforms neither to C11 nor to the original TR 24731-1. ... As a result of the numerous deviations from the specification the Microsoft implementation cannot be considered conforming or portable." – Andrew Henle Jul 04 '21 at 14:02
  • 1
    Nevermind the fact Microsoft pushes these functions by lying about the C standard functions such as `scanf()` being "deprecated"... – Andrew Henle Jul 04 '21 at 14:04
  • @AndrewHenle Thanks for that link. Don't worry, I'm no fan of the _s functions or Microsoft's role in pushing them. But this didn't seem like the place for an extended rant on that subject. (And if I wanted to persuade yoon-seul not to use scanf_s, I would *not* say "use the more standard scanf instead"!) – Steve Summit Jul 04 '21 at 14:39
1

No doubt you tried to use scanf() in the normal way and Visual Studio reported an error instructing you to use scanf_s()? It is not a direct replacement. For all %c, %s and %[ format specifiers you must provide two arguments - the target receiving the input, and the size of target (or strictly the number of elements).

In VS2019 even at /W1 warning level, it issues a clear explanation of the problem in this case:

warning C4473: 'scanf_s' : not enough arguments passed for format string
message : placeholders and their parameters expect 2 variadic arguments, but 1 were provided
message : the missing variadic argument 2 is required by format string '%s'
message : this argument is used as a buffer size

Don't ignore the warnings, and certainly don't disable them globally (/W0).

So in this case:

scanf_s("%s", input, sizeof(input) ) ;

again more strictly:

scanf_s("%s", input, sizeof(input)/sizeof(*input) ) ;

but the latter is really only necessary for wscanf_s (wide characters). In both cases you could use the _countof() macro, but it is Microsoft specific.

scanf_s("%s", input, _countof(input) ) ;

Note also the lack of an & before input. You don't need it for an argument that is already array or pointer. That is true of scanf() too.

Whilst there are arguments for using scanf_s() over scanf() (which is intrinsically more dangerous), it can just make life difficult if you are learning from standard examples or using a different toolchain. The simpler solution is just to disable the warning, and understand that it is unsafe:

enter image description here

AmigoJack
  • 5,234
  • 1
  • 15
  • 31
Clifford
  • 88,407
  • 13
  • 85
  • 165