简体   繁体   中英

Scanf clarification in c language

Is it possible to read an entire string including blank spaces like gets() function in scanf() ?

I am able to do it using the gets() function.

char s[30];
gets(s);

This will read a line of characters. Can this be done in scanf() ?

You can read a line, including blank spaces, with scanf() , but this function is subtle, and using it is very error-prone. Using the %[^\\n] conversion specifier, you can tell scanf() to match characters to form a string, excluding '\\n' characters. If you do this, you should specify a maximum field width. This width specifies the maximum number of characters to match, so you must leave room for the '\\0' terminator.

It is possible that the first character in the input stream is a '\\n' . In this case, scanf() would return a value of 0 , since there were no matches before encountering the newline. But, nothing would be stored in s , so you may have undefined behavior. To avoid this, you can call scanf() first using the %*[\\n] conversion specifier, discarding any leading '\\n' characters.

After the string has been read, there will be additional characters in the input stream. At least a '\\n' is present, and possibly more characters if the user entered more than the maximum field width specifies. You might then want to discard these extra characters so that they don't interfere with further inputs. The code below includes a loop to do this operation.

The first call to scanf() will consume all newline characters in the input stream until a non-newline character is encountered. While I believe that the second call to scanf() should always be successful, it is good practice to always check the return value of scanf() (which is the number of successful assignments made). I have stored this value in result , and check it before printing the string. If scanf() returns an unexpected result, an error message is printed.

It is better, and easier, to use fgets() to read entire lines. You must remember that fgets() keeps the trailing newline, so you may want to remove it. There is also a possibility that the user will enter more characters than the buffer will store, leaving the remaining characters in the input stream. You may want to remove these extra characters before prompting for more input.

Again, you should check the return value of fgets() ; this function returns a pointer to the first element of the storage buffer, or a NULL pointer in the event of an error. The code below replaces any trailing newline character in the string, discards extra characters from the input stream, and prints the string only if the call to fgets() was successful. Otherwise, an error message is printed.

#include <stdio.h>

int main(void)
{
    char s[30];
    int result;

    printf("Please enter a line of input:\n");
    scanf("%*[\n]");                // throw away leading '\n' if present
    result = scanf("%29[^\n]", s);  // match up to 29 characters, excluding '\n'

    /* Clear extra characters from input stream */
    int c;
    while ((c = getchar()) != '\n' && c != EOF)
        continue;                   // discard extra characters

    if (result == 1) {
        puts(s);
    } else {
        fprintf(stderr, "EOF reached or error in scanf()\n");
    }

    printf("Please enter a line of input:\n");    
    char *ps = fgets(s, 30, stdin); // keeps '\n' character

    if (ps) {
        while (*ps && *ps != '\n') {
            ++ps;
        }
        if (*ps) {                  // replace '\n' with '\0'
            *ps = '\0';
        } else {
            while ((c = getchar()) != '\n' && c != EOF)
                continue;           // discard extra characters
        }

        puts(s);

    } else {
        fprintf(stderr, "EOF reached or error in fgets()\n");
    }

    return 0;
}

Note that these two methods of getting a line of input are not exactly equivalent. The scanf() method, as written here, does not accept an empty line (ie, a line consisting of only the '\\n' character), but does accept lines consisting of other whitespace characters. The fscanf() method will accept an empty line as input.

Also, if it is acceptable to ignore leading whitespace characters, it would be simpler to follow the recommendation given by Jonathan Leffler in the comments to use only a single call to scanf() :

result = scanf(" %29[^\n]", s);

This will ignore leading whitespace characters, including newlines.

Do not use scanf() or gets() function — use fgets() instead. But for the above question please find the answer.

int main() {
    char a[30];
    scanf ("%29[^\n]%*c", name);
    printf("%s\n", a);
    return 0;
}

Its also highly recommended like I told in the beginning to use fgets() instead. We clearly do not understand the weird requirement. I would have used the fgets() to read the character.

fgets(a, size(a), stdin);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM