Чтение в строке переменной длины пользовательского ввода в C - PullRequest
6 голосов
/ 06 октября 2011

Я пытаюсь прочитать пользовательский ввод переменной длины и выполнить некоторую операцию (например, поиск подстроки в строке).

Проблема в том, что я не знаю, насколько велики мои строки (этовполне возможно, что текст может быть 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

Ответы [ 4 ]

10 голосов
/ 06 октября 2011

Пожалуйста, не никогда не используйте небезопасные вещи, такие как 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;
}
2 голосов
/ 06 октября 2011

На практике не стоит слишком беспокоиться, чтобы быть точным. Дайте себе немного времени, чтобы иметь немного памяти в стеке и работайте над этим. Если вы хотите передать данные дальше, вы можете использовать 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);
}
0 голосов
/ 17 января 2014

Основная проблема в вашем случае - наличие массивов символов неизвестного размера. Просто укажите размер массива в объявлении.

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);
}
0 голосов
/ 06 октября 2011

Не используйте scanf или gets в этом отношении, потому что, как вы говорите, нет реального способа узнать, как долго будет ввод.Вместо этого используйте fgets, используя stdin в качестве последнего параметра.fgets позволяет указать максимальное количество символов, которые должны быть прочитаны.Вы всегда можете вернуться назад и прочитать больше, если вам нужно.

scanf(%s) и gets читать до тех пор, пока они не найдут завершающий символ и могут значительно превысить длину вашего буфера, вызывая некоторые проблемы, которые трудно исправить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...