Я пропустил пункт указателей? - PullRequest
3 голосов
/ 09 сентября 2010

ОК, извините за плохой каламбур: P

Я закодировал старый трюк HAL => IBM в C. Я только что прочитал первые несколько страниц в K & R, посвященныхих, и я подумал, что будет хорошей первой игрой с ними.

char evil[] = "HAL";
char *ptr = evil;   
for (int i = 0; i < strlen(evil); ++i, ++ptr) {             
    (*ptr)++;           
}   
printf("%s\n", evil); // IBM

Моя проблема в том, что у меня есть две приращения переменных, i и ptr, и что-то подсказывает мне одну из нихявляется избыточным (возможно, я все еще не думаю * достаточно хорошо C).

Единственная причина, по которой я использую i, состоит в том, чтобы определить, прочитали ли мы до конца строки.Есть ли способ проверить указатель, чтобы убедиться, что он достиг конца строки?

Обновить

Извините за путаницу в вопросе.Под я пропустил точку Я имел в виду, почему я должен использовать указатель, когда мне нужен инкрементный индекс, чтобы также проверить длину.Я мог бы просто использовать этот индекс для подбора правильного символа из массива.

Ответы [ 8 ]

11 голосов
/ 09 сентября 2010

Вы могли бы также написать

for (char *ptr = evil; *ptr != '\0' ; ++ptr)
6 голосов
/ 09 сентября 2010

Я набрал вопрос, перечитал его, а затем понял что-то совершенно очевидное, что я упустил из виду!

char evil[] = "HAL" 
char *ptr = evil;   
for (; *ptr != '\0'; ++ptr) {                       
    (*ptr)++;           
}   
printf("%s\n", evil);

Это, похоже, помогло.

5 голосов
/ 09 сентября 2010

Вы выяснили правильную реализацию, но я все же хотел бы сделать одно замечание по поводу вашего исходного кода, который может дать вам другой способ думать о таких проблемах.

Ваше оригинальное решение может быть даже хуже, чем вы думаете, потому что его сложность на самом деле O (n ^ 2), где n - длина строки. strlen() имеет сложность O (n), потому что он должен перебирать все символы в строке, пока не найдет '\0'. Таким образом, у вас есть цикл, который выполняет n итераций и каждый раз вызывает strlen(), что приводит к сложности O (n ^ 2).

По крайней мере, вы должны вызвать strlen() один раз перед циклом и кэшировать длину строки. И, конечно, у вас есть правильное решение, которое вообще не вызывает strlen().

3 голосов
/ 09 сентября 2010

In C строки заканчиваются на '\0'.Вы можете использовать этот факт, чтобы остановить цикл.

for (; *ptr != '\0' ; ++ptr) {
    /* ... */
}
2 голосов
/ 09 сентября 2010

Вызов strlen(evil) неэффективен. Вместо того, чтобы полагаться на strlen, используйте то же самое, что делает strlen stop: нулевой терминатор:

for (char *ptr = evil; *ptr; ++ptr) {             
    (*ptr)++;           
}
2 голосов
/ 09 сентября 2010

Указанный символ будет '\0'.Но будьте осторожны, неправильное размещение байта NUL может стать причиной сбоев программы или дыр в безопасности.

1 голос
/ 09 сентября 2010

Поскольку мы говорим о зле:

#include <stdio.h>

int main()
{
    char evil[] = "HAL";
    char *ptr;

    // Increment the pointer and its content in the same expression
    // Just to be really evil

    for (ptr = evil; *ptr != '\0'; ++*(ptr++)) { }

    printf("%s\n", evil);
}
1 голос
/ 09 сентября 2010

Это бы сработало:

char evil[] = "HAL";
*(int*) evil += 65793;
printf("%s\n", evil);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...