как я могу контролировать длину массива - PullRequest
0 голосов
/ 17 апреля 2019

Моя проблема в том, что массив b может содержать более 12 символов, и если это произойдет, он печатает только массив b без ошибок

{
int i=12;
char a[i] ,b[i];
printf("give string with no more than 12 characters ");
scanf("%s",a);
printf("give second string with no more than 12 characters\n");
scanf("%s",b);
if(a[i]>i || b[i]>i){
    printf("try again cause you typed more than 12\n");
    printf("first \n");
    scanf("%s",a);
    printf("second \n");
    scanf("%s",b);
    }
printf("you gave %s & %s \n",a,b);

Я ожидаю вывод "попробуй еще раз, потому что ты набрал больше 12" когда я набираю более 12 символов

Ответы [ 3 ]

1 голос
/ 17 апреля 2019

То, что вы хотите сделать, сложно с scanf из-за проблем с захватом символа новой строки.
С fgets символ новой строки захватывается как часть массива char. Просто проверьте, содержит ли ввод новую строку, и вы знаете, что больше нет символов для чтения.
В string.h есть полезные функции, которые делают этот код намного короче, такие как strchr и strcspn.

#include <stdio.h>

int main( void) {
    char a[14];
    char b[14];
    int toolong = 1;

    do {
        int retry = 0;//not retry
        toolong = 1;//too long
        printf ( "give string with no more than 12 characters ");
        if ( fgets ( a, sizeof a, stdin)) {//read a line
            int each = 0;
            while ( a[each]) {
                if ( '\n' == a[each]) {//found a newline
                    if ( ! retry) {//not retry
                        toolong = 0;//not too long
                        a[each] = 0;//remove newline
                    }
                    else {
                        printf ( "try again cause you typed more than 12\n");
                    }
                    break;
                }
                each++;
                if ( ! a[each]) {//found zero terminator at end of line
                    if ( ! fgets ( a, sizeof a, stdin)) {//read more to find newline
                        fprintf ( stderr, "fgets EOF\n");
                        return 0;
                    }
                    each = 0;//start over at [0]
                    retry = 1;//retry
                }
            }
        }
        else {
            fprintf ( stderr, "fgets EOF\n");
            return 0;
        }
    } while ( toolong);

    do {
        int retry = 0;
        toolong = 1;
        printf ( "give second string with no more than 12 characters ");
        if ( fgets ( b, sizeof b, stdin)) {
            int each = 0;
            while ( b[each]) {
                if ( '\n' == b[each]) {
                    if ( ! retry) {
                        toolong = 0;
                        b[each] = 0;
                    }
                    else {
                        printf ( "try again cause you typed more than 12\n");
                    }
                    break;
                }
                each++;
                if ( ! b[each]) {
                    if ( ! fgets ( b, sizeof b, stdin)) {
                        fprintf ( stderr, "fgets EOF\n");
                        return 0;
                    }
                    each = 0;
                    retry = 1;
                }
            }
        }
        else {
            fprintf ( stderr, "fgets EOF\n");
            return 0;
        }
    } while ( toolong);

    printf ( "you gave %s & %s\n", a, b);

    return 0;
}

Использование string.h и помещение дублирующего кода в функцию делает его намного короче.

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

char *strlimit ( char *str, int limit) {
    int toolong = 1;

    do {
        toolong = 0;// not too long
        printf ( "give string with no more than 12 characters ");
        if ( fgets ( str, limit, stdin)) {//read a line
            if ( ! strchr ( str, '\n')) {//no newline
                while ( ! strchr ( str, '\n')) {//look for newline
                    fgets ( str, limit, stdin);//read more
                }
                toolong = 1;// too long
                printf ( "try again cause you typed more than 12\n");
            }
            str[strcspn ( str, "\n")] = 0;//remove newline
        }
        else {
            fprintf ( stderr, "fgets EOF\n");
            return NULL;
        }
    } while ( toolong);

    return str;
}

int main( void) {
    char a[14];
    char b[14];

    if ( ! strlimit ( a, sizeof a)) {
        return 0;
    }

    if ( ! strlimit ( b, sizeof b)) {
        return 0;
    }

    printf ( "you gave %s & %s\n", a, b);

    return 0;
}
0 голосов
/ 17 апреля 2019

Хитрость заключается в том, чтобы ограничить количество символов, считываемых в a и b, а не проверять, вводил ли пользователь слишком много символов после факта (к этому времени ущерб уже будет нанесен).

Есть несколько способов сделать это.Одним из них является использование явной ширины в спецификаторе преобразования %s в вызове scanf:

scanf( "%11s", a );

Другое использование для использования fgets вместо scanf:

fgets( a, sizeof a, stdin);

Оба запретят считывание более 11 символов в a и добавят 0-терминатор.

Однако , если пользователь набрал 12 или более символов, эти дополнительные символы все еще будут ожидать в потоке ввода, который будет получен при следующей операции ввода, что, вероятно, нето, что ты хочешь.Вам нужно будет очистить входной поток, если это так.Один из подходов состоит в том, чтобы читать и отбрасывать любые непробельные символы сразу после операции ввода:

if ( fgets( a, sizeof a, stdin ) != NULL ) // if ( scanf( "%11s", a ) == 1 )
{
  // Successfully read into a
  // Scrub any non-whitespace characters remaining in the input stream
  int c;
  while ( !isspace( c = getchar() ) )
    ; // empty loop body
  if ( c != EOF ) 
    ungetc( c, stdin );
}
else
{
  // error on input
}

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

0 голосов
/ 17 апреля 2019
int i=12;
char a[i] ,b[i];

Таким образом, массивы a и b каждый имеют по 12 элементов.

if(a[i]>i || b[i]>i){

Ничто не изменило значение i, поэтому i равно 12. Итак a[i] эквивалентно a[12].Но поскольку a имеет только 12 элементов, тринадцатого элемента нет (поскольку a[0] - первый элемент, a[12] - тринадцатый).Так что это попытка получить доступ к записи в массиве, который не существует.

Если вы хотите определить, вводит ли человек более 12 символов, вам нужен код, который позволит им вводить большечем 12 символов.Это не то, что вы написали.

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