Арифметика указателя пошла не так

Я пытаюсь использовать char * для хранения строки, и поскольку указатель указывает на ячейку памяти первого char данной строки, я попытался использовать арифметику указателя (ptr++) для перехода к следующему символу (поскольку они сохраняются последовательно). Однако в моем примере программы размер "строки" равен 22, но когда я пытаюсь запустить цикл for, как показано ниже, он выполняется только 12 раз. Есть идеи, почему? Я пропустил что-то важное о том, как работает арифметика указателя?

#include <stdio.h>

int main(void) {
  char *strVar = "testfordifferentlength";
  int i,timesCalled=0;
  printf("\nLength = %d\n\n",strlen(strVar));
  for(i=0;i <= strlen(strVar);i++){
    printf("%c",*strVar);
    strVar++;
    timesCalled++;
  }
  printf("\n\nFor loop run %d times!\n",timesCalled);
  return 0;
}

person Stelios Papamichail    schedule 06.11.2018    source источник
comment
Что вы на самом деле пытаетесь достичь или узнать здесь?   -  person jarmod    schedule 07.11.2018
comment
Еще одна вещь, о которой еще не упоминалось, это то, что вы не хотите делать printf("%c" на нулевом терминаторе.   -  person M.M    schedule 07.11.2018


Ответы (1)


Проблема в том, что вы вызываете strlen(strVar) при каждой проверке условия (неэффективно как есть), а также одновременно изменяете, куда указывает strVar. Сохраните начальный размер в переменной и сравните свой индекс с начальным размером, а не с оставшейся длиной строки. Кроме того, вы, вероятно, захотите использовать <, а не <= в своем условии, поскольку вы начинаете с 0. В противном случае вы также повторяете завершающий символ NULL, поскольку строки в C заканчиваются нулем.

#include <stdio.h>

int main(void) {
  char *strVar = "testfordifferentlength";
  int i, timesCalled = 0, length = strlen(strVar);
  printf("\nLength = %d\n\n",length);
  for(i = 0; i < length; i++){
    printf("%c", *strVar);
    strVar++;
    timesCalled++;
  }
  printf("\n\nFor loop run %d times!\n", timesCalled);
  return 0;
}

Для дальнейшего понимания представьте каждую итерацию цикла с исходным кодом:

i = 0, strVar = "testfordifferentlength", length = 22, output is 't'
i = 1, strVar = "estfordifferentlength", length = 21, output is 'e'
i = 2, strVar = "stfordifferentlength", length = 20, output is 's'
i = 3, strVar = "tfordifferentlength", length = 19, output is 't'
...
i = 11, strVar = "erentlength", length = 11, output is 'e'
And this point your loop ends

По сути, вы в конечном итоге напечатаете (strlen/2) + 1 символов, поскольку вы увеличиваете свой индекс на 1 и уменьшаете длину строки на 1 на каждой итерации цикла.

person John    schedule 06.11.2018
comment
Это правильный ответ. Возможно, вы сможете прояснить проблему с помощью иллюстрации. - person jxh; 07.11.2018
comment
Просто используйте указатель strVar как итератор char *p = strVar; while (*p != '\0') { ...;p++;, что значительно упрощает код. - person jwdonahue; 07.11.2018
comment
Деталь: в противном случае вы зацикливаетесь 1 раз после конца строки. --› В C string — это непрерывная последовательность символов, заканчивающаяся первым нулевым символом и включающая его. Так что я бы сказал, иначе вы зацикливаетесь на конце строки. с <=. Как бы это ни называлось, i < length правильный тест. - person chux - Reinstate Monica; 07.11.2018
comment
@Джон, спасибо за такой четкий ответ. Теперь я понимаю, что я сделал неправильно, еще раз спасибо! - person Stelios Papamichail; 07.11.2018