0

I am trying to use scanf() with strcmp. However, it doesn't work. I've included the right header files. I've tried out gets(). It works but I don't want to be vulnerable of a buffer overflow attack.

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

int main() {
    char a[100] = "Hello World!";
    char b[100];

    scanf("%s", &b);

    if(strcmp(a, b) == 0) {
        printf("This should work!\n");
    }
}

I compile the program. Then, type Hello World! into the program. It won't show the message. Also, why does strcmp() show me all kinds of return values?

Please help.

melpomene
  • 84,125
  • 8
  • 85
  • 148
  • 3
    `%s` of `scanf` does not include spaces. – BLUEPIXY Jul 02 '17 at 21:46
  • Did you try to find out what the string that got read in was if it wasn't what you expected? Shouldn't `strcmp` show different return values for different inputs, as its documentation says? – Scott Hunter Jul 02 '17 at 21:47
  • [notthecause] `scanf("%s", &b);` -->> `scanf("%s", b);` – wildplasser Jul 02 '17 at 21:47
  • 3
    Did you try to print b? – klutt Jul 02 '17 at 21:47
  • Yes, printing b was successful. – Ashland Simpson Jul 02 '17 at 21:48
  • `fgets()` is probably best, but you could also use `scanf("%99[^\n]", b);`. This will leave the newline in the input stream. – ad absurdum Jul 02 '17 at 21:51
  • 2
    Printing `b` could never have been successful unless you tested with a different text, and only one word. If you entered 'Hello world' and asked for `b`, you would have received 'Hello' in answer. – LSerni Jul 02 '17 at 21:51
  • I don't belive you. If you add printf("%s", b) after the scanf and enter "Hello World" it will only print "Hello" – klutt Jul 02 '17 at 21:51
  • Wait. I just typed wow into it. Yes, it only says Hello. – Ashland Simpson Jul 02 '17 at 21:52
  • 2
    @DavidBowling `scanf("%99[^\n]", b);` is also a problem when user enters only `"\n"`. – chux - Reinstate Monica Jul 02 '17 at 21:59
  • 1
    @chux-- a problem how? If the user enters only `"\n"`, then no characters are read into `b`, but `scanf()` will return. Of course, code needs to check the return value from `scanf()` before using `b`, e.g., in `strcmp()`. Is this what you meant? Note that my example did not have leading space, as the answer below did. – ad absurdum Jul 02 '17 at 22:05
  • 2
    @DavidBowling The problem is that too often expectations are that `b[]` has updated data in it. And with input like `'\n'`, that does not happen. Yes, checking the return value of `scanf()` is good programming to detect that case. – chux - Reinstate Monica Jul 03 '17 at 04:57

1 Answers1

2

Reading the manual on scanf -- you will see that it stops scanning a %s at the first whitespace found

scanf("%s", b);

of Hello World

will give you Hello but not Wolrd

Also note that scanf is equally vulnerable to buffer overflow, as you are still not limiting the size of the input in %s -- to limit the input you should probably try to do %99s making sure that you are not reading more than your 100 byte buffer still leavng space for your null termination.

As per this question you need something like

scanf("%[^\n]",str)

to read everything up to the newline, and combining that with a length restrction, you would need something like

scanf("%99[^\n]",str)
Soren
  • 14,402
  • 4
  • 41
  • 67
  • OK. How do I fix it so it does both words? – Ashland Simpson Jul 02 '17 at 21:50
  • You don't use `scanf`; you need something like `fgets`. And you need to trim the carriage return at the end. – LSerni Jul 02 '17 at 21:53
  • You can still use scanf, but it does not make it easier – Soren Jul 02 '17 at 21:53
  • I've tried fgets(b, 100, stdin). That still doesn't do much. It prints both words but doesn't go onto the if statement. – Ashland Simpson Jul 02 '17 at 22:00
  • @AshlandSimpson -- did you try the code I suggested.? – Soren Jul 02 '17 at 22:02
  • 1
    `scanf(" %[^\n]",str)` does not read "everything up to the newline,". It first consumes leading whitespace including newlines - then reads everything up to the next newline. – chux - Reinstate Monica Jul 02 '17 at 22:02
  • @xing -- that is terrible advice as that can result in a different buffer overflow -- why don't you move this into a separate answer instead of adding comments here? – Soren Jul 02 '17 at 22:07
  • @xing -- I can construct input that is 100 bytes long without a newline and the strcspn will modify memory beyond the 100 buffer length. – Soren Jul 02 '17 at 22:10
  • 2
    @Soren: `strcspn()` stops at the first newline or null byte. Since `fgets()` always includes a null byte, even when it does not reach a newline, the `strcspn()` idiom is safe. – Jonathan Leffler Jul 02 '17 at 22:29
  • 1
    Note that `scanf("%99[^\n]",str)` (with or without 99) will have trouble if line input is only `"\n"` --> `str` is not changed and `'\n'` remains in `stdin`. `fgets()` is a better tool to real a _line_. – chux - Reinstate Monica Jul 03 '17 at 04:53