1
votes

Okay, I'm reading C for dummies, and once again I am having scanf problems. I wrote another questioner earlier with the similar problem but the fix will not work here. Every time I compile, gcc always says:

MADLIB1.C: In function ‘int main()’:
MADLIB1.C:19:27: warning: format ‘%s’ expects argument of type ‘char*’, but argument 2 has type ‘char ()[20]’ [-Wformat]
MADLIB1.C:21:22: warning: format ‘%s’ expects argument of type ‘char
’, but argument 2 has type ‘char ()[20]’ [-Wformat]
MADLIB1.C:23:23: warning: format ‘%s’ expects argument of type ‘char
’, but argument 2 has type ‘char ()[20]’ [-Wformat]
MADLIB1.C:25:27: warning: format ‘%s’ expects argument of type ‘char
’, but argument 2 has type ‘char (*)[20]’ [-Wformat]
MADLIB1.C:31:52: error: expected ‘}’ at end of input

Here's my code:

/*
MADLIBI.C Source Code
Written by Arshad Husain
*/

#include <stdio.h>

int main()
{

    char adjective[20];
    char food[20];
    char chore[20];
    char furniture[20];

    /* Get the words to use in the madlib */

    printf("Enter an adjective");     /* prompt */
    scanf("%s",&adjective);
    printf("Enter a food");
    scanf("%s",&food);
    printf("Enter a household chore (past tense):");
    scanf("%s",&chore);
    printf("Enter an item of furniture");
    scanf("%s",&furniture);

    /* Display the output */

    printf("\n\nDon't touch that %s %s!\n", adjective, food);
    printf("I just %s the %s!\n", chore, furniture);

    return(0);
}
7
To avoid the buffer overflow that has been mentioned in the answers, instead of hard coding the length,if you have declared int array[len],u can use scanf("%*s",len-1,array); where * denotes the length u want and should be followed by corresponding variable name after the comma.Cygnus
I got it to compile after removing the & from the variable names. What you suggested in your last comment, is that just good programming practice?IC2D
Not really a programming practice. Only if its not dependant ons some other value or you could take input from user regarding the desired string length and use that input length as the 'len-1' argument. Otherwise, hardcoding is fine. Just for convenience rather !!Cygnus

7 Answers

3
votes

You should not use address-of for arrays, they are already pointers:

printf("Enter an adjective");     /* prompt */
scanf("%s",adjective);

When you use address-of, e.i., &, it becomes char **, which is not what scanf expects.

also, for this example it is safer to do:

scanf("%19s",adjective); /* maximum 19 chars */

to protect against overflows.

1
votes

No need to pass the address of address of char array. i.e Just modify the scanf statements as follows

scanf("%s",adjective);
scanf("%s",food);
scanf("%s",chore);
scanf("%s",furniture);
1
votes
    printf("Enter an adjective");     
   /* prompt */ scanf("%s",&adjective); 
   printf("Enter a food"); 
   scanf("%s",&food); 
   printf("Enter a household chore (past tense):"); 
   scanf("%s",&chore); 
   printf("Enter an item of furniture"); 
   scanf("%s",&furniture); 

can be

   printf("Enter an adjective");     
   /* prompt */ scanf("%s",adjective); 
   printf("Enter a food"); 
   scanf("%s",food); 
   printf("Enter a household chore (past tense):"); 
   scanf("%s",chore); 
   printf("Enter an item of furniture"); 
   scanf("%s",furniture); 

No need for prepending a & before them. %s expects a char * which will be satisfied without adding a & itself.

1
votes

the syntax of your code you have written : scanf("%s",&food); doesn't make any sense because to take input in a string(char array) you don't need to prefix the array name with &. further to avoid buffer overflow you should use
scanf("ONE_LESS_THEN_THE_SIZE_OF_CHAR_ARRAY%s",food); in case of food you should use scanf("%19s",food);

0
votes

When you read from the keyboard using scanf, characters are placed in a buffer and the arguments to scanf extract from that buffer so in the case of scanf("%s",adjective); when you enter a string "ABC" and press ENTER the ENTER character(s) (CR[LF]) are also placed in the buffer. The %s extracts the string "ABC" but the ENTER remains. Next time you do scanf() the ENTER is still in the buffer and will just return without reading anything.

in the beginning you would be better off using fgets() to read strings to avoid the hassle of working with the input buffer directly and will not crash if you enter a larger string than the array can hold.

if ( fgets( adjective, sizeof(adjective), stdin) )
{
  if ( fgets( ...
  {
0
votes

An array in C is not a separate data type. It is similar to a pointer. For example, when i write

int a[20];

It reserves 20*4 = 80 bytes for storing 20 integers. Now, 'a' points to the first word of these 20 allocated integers i.e. 'a' contains the address of the first word. It applies similarly to any array which in your case is of type char. Internally, adjective is of type char *.

Now when in scanf you say &adjective, you are actually giving the address of 'char *adjective', which is not a string array and hence data types do not match.

I do not know how far you have progressed with your reading, but these things will become much clearer to you once you read about pointers and arrays.

0
votes

Don't use an extra '&' during scanf. The name of an array string is itself the base address of string - i.e. adjective == &(adjective[0]). So you don't need the extra '&' before adjective n other arrays.