Понимание массива 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 переменной, хранящей некоторый размер данных.