-3

I am trying to use scanf (or some variant like scanf_s) to send a character array from the stdin stream into a (pre-defined) character array variable.

The error (unhanled exception) is thrown at runtime by windows as soon as the user hits enter; it is triggered as soon as scanf() is called..

I am new to working with C and just trying to get the basics down of working with variables in a more low level way, its fun but sometimes frustrating

Should I just make my own scanf function? - How would one do that?

Below is the code that isnt working, in its simplest form so easy for you to read.. (Its literally just the scanf part thats throwing an exception.. gah!)

Below the code is the error message

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

int main()
{
    char string[20];

    printf("%s\n", string);

    scanf_s("%s", &string);



    system("Pause");
    return 0;
}

Error is:

Exception thrown at 0x1011E63C (ucrtbased.dll) in Project.exe: 0xC0000005: Access violation writing location 0x00760000.
Unhandled exception at 0xFEFEFEFE in Project.exe: 0xC00001A5: An invalid exception handler routine has been detected (parameters: 0x00000003).
Obsidian
  • 3,719
  • 8
  • 17
  • 30
  • 2
    `printf("%s\n", string);` - what exactly is supposed to be printed here? – Eugene Sh. May 17 '19 at 19:25
  • 2
    Also [`scanf_s` does **not** work like `scanf`](https://stackoverflow.com/questions/23378636/string-input-using-c-scanf-s). Also you do not need `&` for reading a *string* in `scanf`. – Antti Haapala -- Слава Україні May 17 '19 at 19:27
  • Have you thought about reading the manual pages for these two functions? – Ed Heal May 17 '19 at 19:29
  • I have tried to read the manual pages but they involve more abstract language which im not familiar with yet - thought i would just try and get a quick answer The first printf(); is meaningless im just playing around here - literally started C two days ago aha.. im just playing I have got this to work by doing scanf_s("%s", string, 20); Hmm – Ollie Hancock May 17 '19 at 19:36
  • @OllieHancock Stackoverflow does not work the way you seem to think it works. Please read [ask] and [faq]. – dandan78 May 17 '19 at 19:41
  • Please could you give me the URL for the manual page that you read – Ed Heal May 17 '19 at 19:53
  • Anyone using (or thinking of using) any of the (not really) safer functions such as `scanf_s()` should read [**Field Experience With Annex K — Bounds Checking Interfaces**](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm): "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 May 17 '19 at 20:00
  • 1
    (cont) "... **Using the APIs has been seen to lead to worse quality, less secure software than relying on established approaches or modern technologies.** More effective and less intrusive approaches have become commonplace and are often preferred by users and security experts alike. Therefore, we propose that Annex K be either removed from the next revision of the C standard, or deprecated and then removed." – Andrew Henle May 17 '19 at 20:00

1 Answers1

2

Few things:

  1. Why are you calling printf on the uninitialized buffer string? That is undefined behavior.
  2. To use scanf_s properly to read a string, use this: scanf_s("%19s\n", string, 20);. The general pattern is "%s", buffer, X where X is the capacity of the buffer. Also, notice that it's string, not &string.

That is, if you insist on using scanf_s at all; fgets is better for reading strings.

Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
  • Is `"%X-1s"` required for `scanf_s`? That kind of makes passing the size as an argument redundant. – Kevin May 17 '19 at 19:31
  • 1
    @Kevin read the documentation at https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/scanf-s-scanf-s-l-wscanf-s-wscanf-s-l?f1url=https%3A%2F%2Fmsdn.microsoft.com%2Fquery%2Fdev15.query%3FappId%3DDev15IDEF1%26l%3DEN-US%26k%3Dk(STDIO%2Fscanf_s);k(scanf_s);k(DevLang-C%2B%2B);k(TargetOS-Windows)%26rd%3Dtrue&view=vs-2019 – Govind Parmar May 17 '19 at 19:32
  • Hmm, the example on [cppreference](https://en.cppreference.com/w/c/io/fscanf) disagrees with that. Could be a difference between C11 and whatever microsoft supports? Honestly I don't understand why you need to specify in both places. One would be sufficient. – Kevin May 17 '19 at 19:37
  • 1. Thats not to do with the question its just some left over code I accidentally copied in 2. Thanks! :D Thanks man x – Ollie Hancock May 17 '19 at 19:37
  • Do you know where I can find some very current (like 2019) documentation for C? All of the tutorials ive found stick to old standards using things like scanf and scanf_s -- I dont feel confident enough to dive in to using something like fgets with little online doc' , yknow? Thank you so much for your help btw also how does one enter a line break in these comments ffs aha – Ollie Hancock May 17 '19 at 19:39
  • @OllieHancock `scanf` and `scanf_s` aren't outdated or deprecated, but using either of them as the go-to method for reading input from the user has never been a good idea. Asking for educational advice is off topic on Stack Overflow, though there may be other Stack Exchange sites where it is appropriate. – Govind Parmar May 17 '19 at 19:41
  • 1
    According to the MS docs, no, a field width is *not* required in the format. What's required is a separate buffer-size argument. Where a field width suitable for the actual array argument is used, `scanf_s` indeed has no advantage over `scanf`. – John Bollinger May 17 '19 at 19:47
  • 2
    Also, although `scanf_s` is not deprecated, it ***is*** optional, and not widely implemented, and the version of that and the other `*_s` functions that were standardized disagree in some details with the version implemented by their primary champion (Microsoft). The mismatch makes it unlikely that they will *ever* be widely implemented. Many consider them flawed, and their supposed additional security illusory. My advice: don't use the `*_s` unless forced to. – John Bollinger May 17 '19 at 19:52
  • @JohnBollinger Updated my answer – Govind Parmar May 17 '19 at 19:55