Rupam
Rupam

Reputation: 1642

C scanf not working for multi word input

I have this code.

#include <stdio.h>
struct name
{
    int age;
    char fullname[20];
};

struct name names[20];

int main()
{
    int n,i;
    printf("Count of names:\n");
    scanf("%d",&n);
    for (i = 0; i < n; i++)
    {
        printf("Name %d : ",i);
        scanf("%[^\n]s",names[i].fullname);
    }
    return 0;
}

And when i execute :

rupam@linux ~ $ ./a.out 
Count of names:
5
Name 0 : Name 1 : Name 2 : Name 3 : Name 4 : 
rupam@linux ~ $

It don't wait for user input. Somehow the scanf is not working.

Well, if i use

scanf("%s",names[i].fullname);

It works for single word inputs. What am i doing wrong here ?

Upvotes: 0

Views: 338

Answers (3)

Chris Dodd
Chris Dodd

Reputation: 126203

So lets see what happens with the input here. First, you call scanf("%d" to read an integer. Assuming you enter something like 5Enter, the scanf call will read digits and convert them to an integer. Since it finds at least one digit, it will succeed, reading that digit and leaving the \n from the Enter to be read.

Now you go into the loop, where you call scanf("%[^\n]s" which attempts to read one or more non-newline characters followed by a newline, then attempts to read an s. Since the next character of input is a newline, this immediately fails (reading nothing), but you don't check the return value of scanf, so you don't notice. You then loop attempting to read more, which will fail again.

So what you need to do is ignore the newline. The easiest way is probably to just use a space in the format, which causes scanf to read and ignore whitespace, until it finds a non-whitespace character; change your second scanf to:

scanf(" %19[^\n]", names[i].fullname);

Note some additional changes here. We got rid of the spurious s as you don't particularly want to match an s after the name. We also added a limit of 19 characters to avoid overflowing the fullname array (19 characters max + 1 for the terminating NULL byte).

Upvotes: 2

user12205
user12205

Reputation: 2702

If you may work with files with Windows line-ending in the future (redirecting files to stdin), then instead of using one getchar() as suggested by @jahan you can use

if(getchar()=='\r') getchar();

This can increase the portability of your code.

Upvotes: 0

jahan
jahan

Reputation: 521

Use getchar() after printf in for loop:

#include <stdio.h>
struct name
{
    int age;
    char fullname[20];
};

struct name names[20];

int main()
{
    int n,i;
    printf("Count of names:\n");
    scanf("%d",&n);
    for (i = 0; i < n; i++)
    {
        printf("Name %d : ",i);
        getchar();//getchar here
        scanf("%[^\n]s",names[i].fullname);
    }
    return 0;
}

Upvotes: 0

Related Questions