如何使用scanf()仅捕获字符串

时间:2017-03-05 10:38:46

标签: c arrays char scanf

您好我是C的新手,我正在尝试使用下面的字符数组类型来捕获用户的输入。如何阻止或转义数字字符。我只想要捕获字符串。

char str_input[105];

已经尝试了

scanf("%[^\n]s",str_input);
scanf("%[^\n]",str_input);
scanf("%[^0-9]",str_input);
scanf("%[A-Zaz-z]",str_input);
str_input = fgetc(stdin);

以上都不适合我。

输入

  

2

     

黑客

预期输出

  

Hce akr

int main() {
    char *str_input;
    size_t bufsize = 108;
    size_t characters;

    str_input = (char *)malloc(bufsize * sizeof(char));
    if (str_input == NULL)
    {
        perror("Unable to allocate buffer");
        exit(1);
    }

    characters = getline(&str_input,&bufsize,stdin);
    printf("%zu characters were read.\n",characters);
    int i;
    int len = 0;

    for (i = 0, len = strlen(str_input); i<=len; i++) {
        i%2==0? printf("%c",str_input[i]): 'b'; 
    }
    printf(" ");

    for (i = 0, len = strlen(str_input); i<=len; i++) {
        i%2!=0? printf("%c",str_input[i]): 'b'; 
    }
    return 0;
}

错误

solution.c: In function ‘main’:
solution.c:21:5: warning: implicit declaration of function ‘getline’ [-Wimplicit-function-declaration]
     characters = getline(&str_input,&bufsize,stdin);

3 个答案:

答案 0 :(得分:2)

如果你正在使用Linux,我会使用getline()函数来获取整行文本,然后验证它。如果它不是有效输入,我会循环询问用户一次又一次地输入一行文字,直到输入可以接受为止。

如果不使用Linux,那么最好的选择可能是重新实现getline()。如果找到可接受的有限大小的缓冲区,也可以使用fgets()。我没有找到可接受的有限大小的缓冲区,所以我更喜欢getline()。

getline()根据其手册页中解释的方式使用:http://man7.org/linux/man-pages/man3/getdelim.3.html

基本上,你的循环应该类似于:

char *buf = NULL;
size_t bufsiz = 0;
while (1)
{
    if (getline(&buf, &bufsiz, stdin) < 0)
    {
        handle_error();
    }
    if (is_valid(buf))
    {
        break;
    }
    printf("Error, please re-enter input\n");
}
use_buffer(buf);
free(buf);

答案 1 :(得分:2)

由于您的缓冲区大小有限,因此使用fgets(3)就可以了。 fgets()在未读取行时返回NULL,并在缓冲区末尾附加换行符。

就防止数字字符在缓冲区中而言,您可以简单地创建另一个缓冲区,并且只向其添加非数字字符。您可以从原始缓冲区中删除数字字符,但如果您仍然掌握C的基础知识,这可能是一个繁琐的过程。另一种方法是只读取getchar(3)的单个字符输入,这将允许您评估每个角色并简单地忽略数字。到目前为止,这种方法最容易实现。

由于您要求使用fgets()的示例,以下是一些示例代码:

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

#define INPUTSIZE 108

int main(void) {
    char str_input[INPUTSIZE], characters[INPUTSIZE];
    size_t slen, char_count = 0;

    printf("Enter input:\n");
    if (fgets(str_input, INPUTSIZE, stdin) != NULL) {

        /* removing newline from fgets() */
        slen = strlen(str_input);
        if (slen > 0 && str_input[slen-1] == '\n') {
            str_input[slen-1] = '\0';
        } else {
            fprintf(stderr, "Number of characters entered exceeds buffer size\n");
            exit(EXIT_FAILURE);
        }

        /* checking if string is valid */
        if (*str_input == '\0') {
            fprintf(stderr, "No input found\n");
            exit(EXIT_FAILURE);
        }

        printf("Buffer: %s\n", str_input);

        /* only adding non-numbers */
        for (size_t i = 0; str_input[i] != '\0'; i++) {
            if (!isdigit(str_input[i])) {
                characters[char_count++] = str_input[i];
            }
        }

        /* terminating buffer */
        characters[char_count] = '\0';

        printf("New buffer without numbers: %s\n", characters);
    }

    return 0;
}

示例输入:

Enter input:
2ttt4y24t4t3t2g

输出:

Buffer: 2ttt4y24t4t3t2g
New buffer without numbers: tttytttg

<强>更新

您可以使用这种更简单的方法来忽略非数字字符:

char str_input[INPUTSIZE];
int ch;
size_t char_count = 0;

while ((ch = getchar()) != EOF && ch != '\n') {
    if (!isdigit(ch)) {
        if (char_count < sizeof(str_input)) {
            str_input[char_count++] = ch;
        }
    }
} 

str_input[char_count] = '\0';

答案 2 :(得分:1)

那是不可能的。数字也是字符串。但您可以设置循环以查找数字和打印错误。像这样:

 char *str = "ab234cid20kd", *p = str;
while (*p) { // While there are more characters to process...
    if (isdigit(*p)) { // Upon finding a digit, ...
        printf("Numbers are forbidden");
        return 0;
    } else {
        p++;
    }
}