0

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);
}
nhahtdh
  • 55,989
  • 15
  • 126
  • 162
IC2D
  • 471
  • 4
  • 11
  • 22
  • 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 Jul 11 '12 at 07:08
  • 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 Jul 24 '12 at 05:23
  • 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 Jul 24 '12 at 08:05
  • Does this answer your question? [Example: scanf and char errors](https://stackoverflow.com/questions/11380933/example-scanf-and-char-errors) – outis Apr 15 '22 at 04:25

7 Answers7

3

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.

perreal
  • 94,503
  • 21
  • 155
  • 181
  • @KingsIndian, they are, as function parameters. – perreal Jul 11 '12 at 06:44
  • 1
    An array decays into a pointer when passed to a function. But they are not the same as pointers. – P.P Jul 11 '12 at 06:45
  • To the compiler, int *a and int a[20] are same except that in the latter a points to first word of 20 words while in the former its not pointing to anything yet. – Cygnus Jul 11 '12 at 06:58
  • 1
    @Cygnus, no, they aren't. Try to apply the `sizeof` operator to them, you'll see that it returns different results. – Jens Gustedt Jul 11 '12 at 08:28
  • Again, sizeof returns separate values because of what i've explained in my except argument above. 'a' by itself is just pointing to the base location of the 20 words and is thus 'similar to a pointer'. – Cygnus Jul 11 '12 at 08:54
1
    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.

Jay
  • 24,173
  • 25
  • 93
  • 141
1

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);
Jeyaram
  • 9,158
  • 7
  • 41
  • 63
1

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);

rkp
  • 13
  • 5
0

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.

Cygnus
  • 3,222
  • 9
  • 35
  • 65
  • -1 for a misleading answer. Arrays and pointers are not the same. http://www.c-faq.com/aryptr/aryptr2.html – Jens Gustedt Jul 11 '12 at 08:30
  • Sorry for writing 'is a pointer'. I've made the edit. Also, its mentioned in that link that 'a' is an object. No! As i said, array is NOT a datatype. 'a' simply points to the base address of the 20 reserved words, and that is what i have explained above. – Cygnus Jul 11 '12 at 08:52
  • But really it is a separate data type. Try to assign to an array variable. – Jens Gustedt Jul 11 '12 at 09:03
  • To cite the C standard: An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type. – Jens Gustedt Jul 11 '12 at 09:06
  • Please refer this link - http://www.cplusplus.com/doc/tutorial/pointers/ It is mentioned that arrays are constant pointers. I repeat, array is a datatype only to our perception, not to the compiler. Only the PRIMITIVE data types are supported by C. Arrays and pointers are compound types. – Cygnus Jul 11 '12 at 09:07
  • And refer to this for a proper explanation on C datatypes - http://www.tutorialspoint.com/ansi_c/c_basic_datatypes.htm. – Cygnus Jul 11 '12 at 09:11
  • 1
    First your link is C++ and the other one is marked as obsolete. Then I gave you the citation from the C standard, that defines the C language, and says that it is a type. And I gave you two tools to see that arrays and pointers are not the same: the `sizeof` operator and assignment. What do you need more? Perhaps read the C standard before making such false assertions? – Jens Gustedt Jul 11 '12 at 09:15
  • How does it matter if the link is C++ ? The concept remains the same. Secondly, the C standard says there are only 4 basic types - int, float, char and double. Arrays, pointers and structures are compound types, that are made up of the basic types. sizeof returning different values does not make array a data type. Have a look at the equivalent assembly code, and ull know why different values are returned. – Cygnus Jul 11 '12 at 09:23
0

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( ...
  {
AndersK
  • 35,813
  • 6
  • 60
  • 86
0

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.

Spectre87
  • 2,374
  • 1
  • 24
  • 37
piyush_raman
  • 318
  • 2
  • 5