C语言 在 C 中读取用户输入的可变长度字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7672560/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 09:50:40  来源:igfitidea点击:

Reading in a variable length string user input in C

cstringinput

提问by bhavs

I am trying to read in a variable length user input and perform some operation (like searching for a sub string within a string).

我正在尝试读取可变长度的用户输入并执行一些操作(例如在字符串中搜索子字符串)。

The issue is that I am not aware how large my strings (it is quite possible that the text can be 3000-4000 characters) can be.

问题是我不知道我的字符串有多大(文本很可能是 3000-4000 个字符)。

I am attaching the sample code which I have tried and the output:

我附上了我尝试过的示例代码和输出:

char t[],p[];
int main(int argc, char** argv) {
    fflush(stdin);
    printf(" enter a string\n");
    scanf("%s",t);

    printf(" enter a pattern\n");
    scanf("%s",p);

    int m=strlen(t);
    int n =strlen(p);
    printf(" text is %s %d  pattrn is %s %d \n",t,m,p,n);
    return (EXIT_SUCCESS);
}

and the output is :

输出是:

enter a string
bhavya
enter a pattern
av
text is bav 3  pattrn is av 2

回答by paxdiablo

Please don't everuse unsafe things like scanf("%s")or my personal non-favourite, gets()- there's no way to prevent buffer overflows for things like that.

永远不要使用不安全的东西,比如scanf("%s")我个人不喜欢的东西,gets()- 没有办法防止缓冲区溢出。

You can use a safer input method such as:

您可以使用更安全的输入法,例如:

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

#define OK       0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
    int ch, extra;

    // Get line with buffer overrun protection.
    if (prmpt != NULL) {
        printf ("%s", prmpt);
        fflush (stdout);
    }
    if (fgets (buff, sz, stdin) == NULL)
        return NO_INPUT;

    // If it was too long, there'll be no newline. In that case, we flush
    // to end of line so that excess doesn't affect the next call.
    if (buff[strlen(buff)-1] != '\n') {
        extra = 0;
        while (((ch = getchar()) != '\n') && (ch != EOF))
            extra = 1;
        return (extra == 1) ? TOO_LONG : OK;
    }

    // Otherwise remove newline and give string back to caller.
    buff[strlen(buff)-1] = '
// Test program for getLine().

int main (void) {
    int rc;
    char buff[10];

    rc = getLine ("Enter string> ", buff, sizeof(buff));
    if (rc == NO_INPUT) {
        // Extra NL since my system doesn't output that on EOF.
        printf ("\nNo input\n");
        return 1;
    }

    if (rc == TOO_LONG) {
        printf ("Input too long [%s]\n", buff);
        return 1;
    }

    printf ("OK [%s]\n", buff);

    return 0;
}
'; return OK; }

You can then set the maximum size and it will detect if too much data has been entered on the line, flushing the rest of the line as well so it doesn't affect your next input operation.

然后,您可以设置最大大小,它会检测该行是否输入了太多数据,并刷新该行的其余部分,以免影响您的下一个输入操作。

You can test it with something like:

您可以使用以下内容对其进行测试:

int main(int argc, char** argv) {
    char text[4096]; 
    char pattern[4096]; 
    fflush(stdin);
    printf(" enter a string\n");
    fgets(text, sizeof(text), stdin);

    printf(" enter a pattern\n");
    fgets(pattern, sizeof(pattern), stdin);

    int m=strlen(text);
    int n =strlen(pattern);
    printf(" text is %s %d  pattrn is %s %d \n",text,m,pattern,n);
    return (EXIT_SUCCESS);
}

回答by RushPL

In practice you shouldn't bother too much to be precise. Give yourself some slack to have some memory on the stack and operate on this. Once you want to pass the data further, you can use strdup(buffer)and have it on the heap. Know your limits. :-)

在实践中,你不应该太费心去精确。给自己一些时间在堆栈上有一些内存并对其进行操作。一旦你想进一步传递数据,你就可以使用strdup(buffer)它并将其放在堆上。了解你的极限。:-)

int main(int argc, char** argv) {
    int s1[4096], s2[4096];
    fflush(stdin);
    printf(" enter a string\n");
    scanf("%s", s1);

    printf(" enter a pattern\n");
    scanf("%s", s2);

    int m = strlen(s1);
    int n = strlen(s2);
    printf(" text is %s of length %d, pattern is %s of length %d \n", s1, m, s2, n);
    return (EXIT_SUCCESS);
}

回答by Bogdan

The main problem in your case is having char arrays of unknown size. Just specify the array size on declaration.

您的情况的主要问题是具有未知大小的字符数组。只需在声明时指定数组大小。

##代码##

回答by doron

Don't use scanfor getsfor that matter because as you say, there is not real way of knowing just how long the input is going to be. Rather use fgetsusing stdinas the last parameter. fgetsallows you to specify the maximum number of characters that should be read. You can always go back and read more if you need to.

不要使用scanfgets就此而言,因为正如您所说,没有真正的方法知道输入将持续多长时间。而是使用fgetsusingstdin作为最后一个参数。fgets允许您指定应该读取的最大字符数。如果需要,您可以随时返回并阅读更多内容。

scanf(%s)and getsread until they find a terminating character and may well exceed the length of your buffer causing some hard to fix problems.

scanf(%s)gets阅读,直到他们找到一个终止字符,并且可能会超过缓冲区的长度,从而导致一些难以修复的问题。