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

发布于 2024-12-08 08:49:51 字数 558 浏览 0 评论 0原文

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

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

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

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

输出为:

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

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.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

花开雨落又逢春i 2024-12-15 08:49:51

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

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

#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] = '\0';
    return OK;
}

您可以设置最大大小,它会检测该行是否输入了过多的数据,并刷新该行的其余部分,这样就不会影响您的下一次输入操作。

你可以用类似的东西来测试它:

// 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;
}

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

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] = '\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:

// 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;
}
喵星人汪星人 2024-12-15 08:49:51

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

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

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. :-)

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);
}
东北女汉子 2024-12-15 08:49:51

不要使用 scanfgets 来解决这个问题,因为正如您所说,没有真正的方法可以知道输入的长度。而是使用 fgets 并使用 stdin 作为最后一个参数。 fgets 允许您指定应读取的最大字符数。如果需要,您可以随时返回并阅读更多内容。

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

Don't use scanf or gets for that matter because as you say, there is not real way of knowing just how long the input is going to be. Rather use fgets using stdin as the last parameter. fgets allows you to specify the maximum number of characters that should be read. You can always go back and read more if you need to.

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

剑心龙吟 2024-12-15 08:49:51

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

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

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

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文