-7

it always returns 1 even if they aren't same and im wondering that why i have to write down buffer size in scanf_s if i don't the scnaf_s does not work

int main(void) {
    char str1[30] = "push";
    char str2[30] = { 0 };
    scanf_s("%s", &str2,2);
    int result = strcmp(str1, str2);
    printf("%d\n", result);
    printf("%d %d", strlen(str1), strlen(str2));
    return 0;
}

to compare the str1 and str2s length i was tring to use strlen but the result comes out 4 and 0 how could the str2 is 0?

  • "_it always returns 1 even if they aren't same_": That's exactly how [`strcmp`](https://en.cppreference.com/w/c/string/byte/strcmp) works. "_how could the str2 is 0?_": What was your input? – user17732522 Mar 18 '23 at 00:26
  • `scanf_s("%s", &str2,2);` should be `scanf_s("%s", str2, sizeof(str2));` – user3386109 Mar 18 '23 at 00:32
  • Welcome to Stack Overflow. "it always returns 1 even if they aren't same" - in your own words, if they aren't the same, what do you think should be returned instead? Why? How do you believe `strcmp` works, and how did you come to that conclusion? For example, did you try to read the documentation? – Karl Knechtel Mar 18 '23 at 01:00

1 Answers1

1

it always returns 1 even if they aren't same and im wondering that why i have to write down buffer size in scanf_s if i don't the scnaf_s does not work

Do not use scanf_s() or Microsoft's other supposedly security-enhanced functions if you can possibly avoid it. They are non-standard* and not particularly more secure than their more conventional counterparts, notwithstanding Microsoft's assertions to the contrary. And in this particular case, they have bitten you. Hard.

Why do I have to pass the buffer size to scanf_s when I use a %s specifier?

Because you do. It's a well-documented characteristic of the function. The intent is that it allows the function to avoid overrunning the buffer provided for receiving the result. But of course, to do that successfully, the programmer has to pass a buffer length that in fact does not exceed the actual buffer size. There are other, better ways to approach this problem.

strcmp() always returns 1 even if they aren't [sic] same

strcmp() should return nonzero when the strings differ. I presume you mean that strcmp() returns 1 when they are the same, but you are mistaken. It is impossible for the strcmp() call in your program to compare equal strings because one of the strings being compared, "push" is four characters long, and this scanf_s() call ...

    scanf_s("%s", &str2,2);

... will not read a string longer than one character, no matter what you enter. The 2-byte buffer size specified must accommodate the string characters and the terminating null.

How could the length of str2 be 0?

Easily. Per the docs,

When a token is too large to fit, nothing is written to the buffer unless there's a width specification.

"Too large" is meant relative to the buffer size you pass (2), and you do not provide a width specification, so if you try to enter a string larger than will fit (i.e., larger than 1 character; see above) nothing is written to str2. You took care to initialize it to all-zeroes (good for you) so the very first character is a string terminator -- hence a zero-length string.

How can you fix it?

If you must use scanf_s, then pass a buffer size argument that reflects the actual buffer size (30 bytes). It is advisable to also include a width specifier:

    char str2[30] = { 0 };
    scanf_s("%29s", &str2, (unsigned int) sizeof(str2));

If you don't need to use scanf_s() then you have lots of possibilities. Among the best would be fgets():

    fgets(str2, sizeof(str2), stdin);

But you could also use conventional scanf():

    scanf_s("%29s", &str2);

Note that an appropriate width specifier, such as is shown, is sufficient for avoiding a buffer overrun in that case.


*Microsoft managed to get versions of these functions added to the C language specification as an optional annex, but their own implementation does not conform, and few other C libraries provide any version at all.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157