Программирование на C: gets() и Char String Array Issue - strcpy() копирует в другие строки в массиве

Я использую функцию gets() для получения строки, введенной пользователем. Затем я сохраняю эту строку в массиве символов char transdestmp[DESMAX], где DESMAX равен 31. Если имя_переменной больше 30 символов, попросите пользователя взять другую строку. В противном случае скопируйте строку с помощью strcpy() в двумерный массив char - acctdes[31][20].

accttitle получает transdestmp[DESMAX]

void accttitle(char descr[DESMAX])
{
    printf("\nEnter title for new account %d: ", transinpt);
    gets(descr);
    while(strlen(descr)>DESMAX){
        printf(" **Title entered is longer than 30 characters\n");
        printf(" Please reenter : ");
        gets(descr);
    }
    strcpy(acctdes[transcntr],descr);
    printf("---->vacctdes[transcntr]: %s\n", acctdes[transcntr]);
    printf("---->vacctdes[transcntr-1]: %s\n", acctdes[transcntr-1]);
}

По какой-то причине, когда я ввожу длинную строку, а затем ввожу другую строку, кроме второй строки, acctdes[1] перезаписывает другую строку, хранящуюся в acctdes[0].

Например,

Первый ввод: acctdes[0] = "Это длинная строка"

Оно работает...

Второй ввод acctdes[1] = "обезьяна"

Оно работает...

но тогда кажется, что когда я вывожу acctdes[0], acctdes[0] имеет часть значения из acctdes[1]... например, вывод - это длинный монах...

Пожалуйста, дайте мне знать, если вам нужна дополнительная информация. Заранее спасибо.


person roxxar    schedule 02.12.2012    source источник
comment
Когда transcntr равно нулю, вы также получите доступ к acctdes[-1], который не является частью массива acctdes.   -  person Some programmer dude    schedule 02.12.2012
comment
Пожалуйста, выполните поиск червя Морриса в Google. Подсказка: strlen() вас не спасет.   -  person wildplasser    schedule 02.12.2012
comment
Никогда не используйте gets(). Его интерфейс не подлежит ремонту и удален из последнего стандарта C. Вместо этого используйте fgets().   -  person ninjalj    schedule 03.12.2012


Ответы (3)


У вас есть размеры в вашем массиве в обратном порядке. Попробуйте acctdes[20][31].

Причина, по которой строки сливаются друг с другом, заключается в том, что C размещает двумерный массив как один длинный блок памяти. Когда вы делаете acctdes[2], на самом деле под капотом выполняется арифметика указателя, например *(acctdes + (31 * 2)), чтобы пропустить первую часть блока памяти, чтобы добраться до вашего третьего элемента. Таким образом, если одна строка выходит за свои границы, она попадет в следующую строку.

person Ben Kelly    schedule 02.12.2012

Ваше объявление массива должно быть наоборот.

В настоящее время у вас есть: acctdes[31][20], что означает 31 заполнителя для 20 длины символа каждый; в то время как вам нужно 20 заполнителей по 31 символу каждый.

Его следует изменить на acctdes[20][31]

person Yogendra Singh    schedule 02.12.2012
comment
Да, это устранило проблему. Спасибо! Ваше здоровье.. :) - person roxxar; 02.12.2012

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

Это ваша проблема, или, по крайней мере, ее часть.

Никогда не используйте функцию gets(). Это по своей сути небезопасно, если у вас нет полного контроля над тем, какой ввод будет отображаться на stdin. У него нет механизма, чтобы указать, сколько символов ввода будет принято. Если пользователь вводит больше данных, чем помещается в целевой массив, поведение вашей программы не определено.

Вместо этого используйте fgets(); он принимает аргумент, определяющий размер целевого буфера. Вам все равно придется иметь дело с возможностью слишком длинной строки ввода (в этом случае fgets() просто сохраняет неполную строку). Если строка ввода не слишком длинная, fgets() оставляет '\n' в буфере, в отличие от gets().

Это настолько плохо, что его удалили из последнего (2011 г.) стандарта ISO C.

(См. также другие ответы.)

person Keith Thompson    schedule 02.12.2012