Понимание массива char [] и строки
Я новичок в программировании. Я изучаю C как свой первый язык программирования. Я нашел что-то странное, чтобы понять.
Я узнал, что в C мы можем представить String как последовательность символов, подобных этому (используя массив char):
char status[10] = "Married";
Я узнал, что проблема такого подхода заключается в том, что во время компиляции мы должны указать размер массива status
.
Но теперь я узнал, что мы можем использовать указатель char
для обозначения string
like -
char status[10] = "Married";
char *strPtr;
strPtr = status;
Я не понимаю его правильно. Мои вопросы -
-
Как я могу получить char в индексе 4 (i в Женат) с помощью strPtr
?
-
В status
есть нулевой символ (\0
) в конце string
, представленный массивом char
- M
- a
- r
- r
- i
- e
- d
- \0
. Поэтому, используя нулевой символ (\0
), мы можем понять конец строки. Когда мы используем strPtr
, как мы можем понять конец string
?
Ответы
Ответ 1
char *strPtr;
strPtr = status;
Теперь ваш указатель strPtr
указывает на первый символ в массиве, и вы можете сделать
int i =0;
while( strPtr[i] != '\0')
{
printf("%c ",strPtr[i]);
i++;
}
*strPtr
называется разыменованием указателя, чтобы получить значение, хранящееся в местоположении, на которое указывает указатель.
Запишите, что
strPtr[4] = *(strPtr +4);
Оба получат вам значение, хранящееся в индексе 4 массива.
Обратите внимание на разницу между указателем и именем массива:
----------------------------------
| s | t | r | i | n | g | \0 |
----------------------------------
|
strPtr
status
strPtr ++
заставит ваш указатель указывать на следующий элемент в массиве.
| s | t | r | i | n | g | \0 |
----------------------------------
|
strPtr
Если вы не можете сделать это для имени массива
status++
не допускается, потому что массив не является изменяемым значением l.
Ответ 2
Полезно знать:
char status[10] = "Married";
- это просто синтаксический сахар для эквивалента:
char status[10]; // allocate 10 Bytes on stack
status[0] = 'M';
status[1] = 'a';
...
status[6]= 'd';
status[7] = '\0'; // same as 0
Ничего больше, не меньше.
также:
char c = status[3];
точно совпадает с
char c = *(status+3);
Ответ 3
Выражение status[10]
является простым синтаксическим сахаром для *(status+10)
.
Терминация \0
используется под капотом для проверки конца, если вы сами выполняете какой-либо обработчик строк, вы тоже можете это сделать или можете игнорировать его и использовать какой-либо другой параметр size
, указанный с помощью строка или вы можете (не надо!) выбирать что-либо еще в качестве символа завершения.
Это не справедливо для массивов char
или "строк", массив C - это просто указатель на непрерывный блок подобранных элементов с проверкой времени компиляции, чтобы ваши индексы "массива" не отображались, t выходит за пределы "конца", указанного в момент объявления. С обозначением *(array+offset)
вам нужно проверить это для себя.
Ответ 4
Чтобы получить символ в индексе 4 strPtr
, вы просто используете strPtr[4]
(это также работает для status
).
Чтобы получить конец строки при использовании strPtr
, вам нужно пройти через символы и искать завершающий \0
. Это то, что printf("%s", strPtr)
делает при печати строки (а также при анализе выражения "%s"
, которое представляет собой еще одну строку). Чтобы найти несколько допустимых символов в строке в C, вы используете функцию strlen()
. О, и убедитесь, что вы не делаете что-то вроде этого:
char a[3];
strcpy(a, "Hello!");
Поскольку это будет записывать 7 байтов в трехбайтовое пространство памяти и, следовательно, перезаписать то, что вы не хотите перезаписывать.
Ответ 5
Я собираюсь сделать провокационное выражение: способ думать об этом состоит в том, что C
не имеет строк. C
имеет только массивы char
. И, несмотря на его название, char
на самом деле является числовым типом (например, 'A'
, это просто забавный способ записать число, обычно 65).
Массив char
не сильно отличается от массива int
или любого другого массива числового типа; это просто, что язык предлагает некоторые дополнительные способы записи объектов типа char
и массивов из них, и существует общее соглашение (систематизированное с такими функциями, как strlen
), как интерпретировать данные, хранящиеся в массивах char
, как представления строк.
char status[10]; // declares an array of `char` of length 10.
char *strPtr; // declare a pointer to `char`
strPtr = status; // make `strPtr` point to the first element of `status`
// Declare an array of 6 `char`, and initialize it.
char hello[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
// Shorthand notation for initializing an array of 6 `char` as above
char world[6] = "World";
// I want to store numeric data in this one!
char other[6] = {0, 1, 2, 3, 4, 5};
// "World" is shorthand for a constant array of 6 `char`. This is
// shorthand for telling the compiler to actually put that array in
// memory someplace, and initialize worldPtr to point to that memory.
const char *worldPtr = "World";
// This does the same thing as above. But it still a *constant* array.
// You should *never* do this; it should be syntactically illegal to
// make a nonconstant `char*` to point to it. This is only allowed for
// historical reasons.
char *helloPtr = "Hello";
Ответ 6
"\ 0" в конце строки - бесполезное дополнение, предназначенное для простоты или безопасности. Вы можете указать строчный последний символ, используя 'sizeof' следующим образом:
char status[] = "Married";
size_t szLastCharstatus = sizeof(status) / sizeof(status[0]) - 2;
char chLastChar = status[szLastCharstatus];
Подробное объяснение:
sizeof(status)
Возвращает количество штрихов массива байтов.
sizeof(status[0])
Возвращает число байтов, занятых первым элементом (и, следовательно, остальное).
Разделение между этими двумя значениями дает нам количество элементов в массиве. Чтобы получить доступ к последнему элементу, нам нужно вычесть один раз, потому что элементы в массиве отсчитываются от нуля и потому, что последний символ в строке равен '\ 0'.
Также обратите внимание, что массивы не являются указателями и наоборот. Массивы имеют неявное преобразование в указатель их первого элемента, постоянный размер и собственный тип. Они могут передаваться указателями или по значению (для второго требуется использование хакера структуры).
Обратите внимание, что я использую size_t ', который является типом def переменной, хранящей некоторый размер данных.