0

I want to get a character and a string and a sentence then write each one of them in a new line. I don't know what is wrong with my code.

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

int main(){

    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
    const int MAX_LEN=100;
    char ch;
    char s[MAX_LEN];
    char sentence[MAX_LEN];
    scanf ("%c",&ch);
    scanf("%s",&s);
    scanf("%[^\n]%*c", &sentence);

    printf("%c\n",ch);
    printf("%s\n", s);
    printf("%s\n",sentence);


    return 0;
}
ryyker
  • 20,437
  • 3
  • 35
  • 78
  • 1
    @Jerry no &s is a pointer to the array, not a pointer to a pointer to the array. – Fredrik Feb 09 '21 at 21:01
  • 1
    @Fredrik when s is passed to scanf, it is a pointer to the array (`char *`). And &s doesn't work because it is another level of indirection (`char (*)[MAX_LENGTH]`). That's why removing the & works. Maybe the exact wording I used was wrong - I guess technically what I should have said was "char s[MAX_LEN]; means that when s is passed to a function that a pointer to the first character of the array is passed instead. But then scanf("%s",&s); means that you are passing a pointer to the array which isn't the same thing." But the advice to use `scanf("%s",s);` was right. – Jerry Jeremiah Feb 09 '21 at 22:03
  • @Jerry yes I was refering to the wording. People often get confused when talking about pointers to array when in fact they mean a pointer to the first element. So always a good idea to be pedantic in the wording, I think at least. – Fredrik Feb 10 '21 at 06:36
  • @Fredrik Fair enough. – Jerry Jeremiah Feb 10 '21 at 20:08
  • ObAntiScanf: https://stackoverflow.com/questions/58403537/what-can-i-use-to-parse-input-instead-of-scanf/ – Steve Summit Feb 11 '21 at 13:43
  • @JerryJeremiah - Your comment above contains the mechanics, but what it boils down to is that mis-matching format specifiers in either `scanf()` or `printf()` results in [undefined behavior](https://stackoverflow.com/a/12830110/645128) – ryyker Feb 11 '21 at 13:44

1 Answers1

1

Regarding

char s[MAX_LEN];
...
scanf("%s",&s);

Use of the & in this case is wrong. s is created here as an array type, so its symbol by itself already points to the location of the first element, (its address) and has type char *, which agrees with the "%s" format specifier used in the scanf statement. Prepending s with the & changes its type to char(*)[100], which is no longer compatible with "%s". Using mismatched format specifiers with scanf() invokes undefined behavior, which is far worse than your program simply being mal-formed, it is unpredictable.

Note that with warnings turned on (eg, in GCC by compiling with -Wall) it should result in a message describing all of this. On my system (not GCC) the following message is issued:

enter image description here

Likewise, when in debug mode with appropriate settings during runtime I see the following assert:

"Parameter type mismatch, expecting pointer to char but found pointer to aggregate or user defined."

By the way, when I allowed execution to continue after this warning message the code appeared to work normally, i.e. it output the content entered into stdin. But that is the nature of undefined behavior, anything can happen..

The fix here is to simply replace this:

scanf("%s",&s);

With either this:

scanf("%s",s);  //okay

or this;

fgets(s, sizeof(s), stdin);//better
s[strcspn(s, "\n")] = 0; // optional, if need to eliminate the newline

either approach works as a replacement for those places in your code where you use an & on an array.

Aside: It is also a good practice to use variable names that self describe themselves. Consider using something more descriptive than s, eg: char string[MAX_LEN]; or char string_array[MAX_LEN];.

ryyker
  • 20,437
  • 3
  • 35
  • 78