Что означает char a [50] [50] в C?

Я работаю над домашним заданием, связанным со строками. Вот код


int main(){
    char a[50][50];
    int n;
    printf("Enter the value of n\n");
    scanf("%d",&n);
    printf("Enter %d names\n",n);
    fflush(stdin);
    for(int i=0; i<n; i++){
        gets(a[i]);
    }

Я пытался изменить char a [50] [50] на char a [50], но вся программа не запустилась, вместе с этим сообщением об ошибке: «Неверное преобразование от 'char' до '* char' Я не очень понимаю, как это работает.

-10
задан Hoàng Thủy Tiên 17 July 2019 в 09:57
поделиться

4 ответа

char a[50][50] объявляет a как массив с 50 элементами массивов с 50 элементами char. Это означает, что каждый a[i] является массивом с 50 элементами char. Это будет размечено в памяти как:

   +---+
a: |   | a[0][0]
   +---+
   |   | a[0][1]
   +---+
   |   | a[0][2]
   +---+
    ...
   +---+
   |   | a[0][49]
   +---+
   |   | a[1][0]
   +---+
   |   | a[1][1]
   +---+
    ...
   +---+
   |   | a[1][49]
   +---+
   |   | a[2][0]
   +---+ 
    ...

Этот код хранит до 50 строки , каждый до 49 символов в длину, в a (IOW, каждый a[i] может сохранить 49 символьных строк). В C строка является последовательностью символьных значений включая 0-значный разделитель. Например, строка "hello", представлен как последовательность {'h', 'e', 'l', 'l', 'o', 0}. То запаздывание 0 метки конец строки. Строковые функции обработки и функции вывода как [1 113] и printf с %s потребность спецификатора, что 0 разделителей для обработки строки правильно.

Строки хранятся в массивах типа символов, или char (для ASCII, UTF-8 или наборов символов EBCDIC) или wchar_t для "широких" строк (наборы символов, которые требуют, чтобы больше чем приблизительно 8 битов закодировали). N-символьная-строка требует массива, который это по крайней мере [1 142] элементы N+1, широкие для составления 0 разделителей.

, Если это не операнд sizeof или унарный & оператор или является строковым литералом, раньше инициализировал массив типа символов, , выражение типа "массив N-элемента [1 120]" будет преобразовано ("затухают") к выражению типа "указатель на [1 121]", и значение выражения будет адресом первого элемента массива.

, Когда Вы звоните

gets( a[i] );

, выражение a[i] преобразовывается из типа "массив с 50 элементами [1 123]" к "указателю на [1 124]", и значение выражения является адресом первого элемента массива (&a[i][0]) <глоток> 1 . gets считает символы из стандартного входа и сохранит их к массиву, запускающемуся в том адресе. Обратите внимание, что gets больше не часть стандартной библиотеки для C - она была удалена в версии 2011 года стандарта, потому что это небезопасно. C не требует никакого вида границ, проверяющих доступы к массиву - если Вы введете в большем количестве символов, чем целевой буфер измерен для содержания (в этом случае, 50), те дополнительные символы будут записаны в память сразу после последнего элемента массива, который может вызвать все виды погрома. Переполнение буфера является популярным вредоносным использованием. Необходимо заменить эти gets вызов с [1 154]

fgets( a[i], 50, stdin );

, который считает до 49 символов в [1 129] от стандартного входа. Обратите внимание, что любые избыточные символы оставляют во входном потоке.

кроме того, поведение [1 130] не определяется для входных потоков <глоток> 2 - там бесполезно, безопасен, портативный способ очистить избыточный вход кроме считать его с помощью [1 131] или fgetc.

<час> <глоток>
  1. Поэтому Вы получили сообщение об ошибке, которое Вы сделали, когда Вы изменились a с [1 134] до [1 135] - в этом случае, a[i] имеет тип char, не char *, и значение [1 139] не адрес .
  2. компилятор C Visual Studio Microsoft является существенным исключением - он очистит избыточный вход от входного потока. Однако это характерно для MSVC и не портативно через различные компиляторы. Операция также немного бессмысленна относительно семантики "сброса".

0
ответ дан 9 September 2019 в 21:06
поделиться

char a[50][50] объявляет a быть массивом 50 массивов 50 char.

Затем a[0] массив 50 char и так a[1], a[2]. a[3], и так далее [до 118]. Существует 50 отдельных массивов, и каждый из них имеет 50 char.

С тех пор a[0] массив 50 char, a[0][0] char. В целом, a[i][j] символ j из массива i.

gets(a[i]) говорит, чтобы считать символы из входа и поместить их в [1 118]. Чтобы это работало, a[i] должен быть массив [1 120] — gets чтения несколько символов и помещает их в массив. Если бы a[i] был отдельный символ, [то 1123] не мог бы работать.

, Хотя gets(a[i]) говорит для помещения символов в [1 125], это работает путем передачи адреса вместо того, чтобы передать массив. Когда массив используется в выражении кроме как операнд [1 126], или операция взятия адреса &, C автоматически преобразовывает его в указатель на его первый элемент. С тех пор a[i] массив, он автоматически преобразовывается в указатель на свой первый элемент (указатель на [1 129]). gets получает этот указатель и использует его для заполнения символов, которые это читает из стандартного входного потока.

1
ответ дан 9 September 2019 в 21:06
поделиться

Та программа, кажется, хранит n имена в массиве a. Это сначала просит количество имен и затем имен. Метод char *gets(char *str) хранилища каждая различная строка в записи a.

n имеет 2 размера. Первое относится к количеству имен, и второе для длины каждого имени. Что-то как n[number_of_names][lenght_of_name]

Однако это, вероятно, откажет, если пользователь обеспечит n> 50, или если имя содержит больше чем 50 символов.

кроме того, gets() опасно. См. это другое сообщение .

РЕДАКТИРОВАНИЕ: Изменение a к размерам заставляет программу попытаться сохранить целую строку в символе, следовательно ошибка

-2
ответ дан 9 September 2019 в 21:06
поделиться

В основном в C это показывает, что массив длины от 0 до 50 из этого содержит символьное значение 50 в каждой ячейке массива

0
ответ дан 9 September 2019 в 21:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: