Как я могу использовать указатели для отображения строк в массиве? - PullRequest
4 голосов
/ 18 марта 2009

Я тренируюсь, используя указатели.

У меня есть указатель на массив из 3 строк: "собака", "кошка", "крыса".

Я могу напечатать содержимое, используя цикл for и массив.

Однако у меня проблемы с печатью с использованием арифметики с указателями. Я хотел бы увеличить указатель на следующий элемент в массиве. Однако все, что он делает - это печатает собачьи буквы.

Код:

int main(int argc, char **argv)
{
    char *str[3] = { "DOG", "CAT", "RAT"};
    int i = 0;

    /* display using an array element */
    for(i = 0; i < 3; i++)
    {
    printf("str: %s\n", str[i]);
    }

    /* display using a pointer arthimatic */
    while((*str)++)
    {
    printf("str: %s\n", str);
    }

    getchar();

    return 0;
}

Как мне это сделать?

Edit:

Код:

while(str)
{
    printf("str: %s\n", *(str++));
}

Однако я получаю это сообщение об ошибке. Разве I-значение не должно быть какой-то переменной?

ошибка C2105: для '++' необходимо l-значение

Ответы [ 5 ]

13 голосов
/ 18 марта 2009

Сначала вы должны получить указатель, и вам нужно условие, когда нужно остановиться. Для этого можно использовать последний пустой указатель. Таким образом, код становится

char *str[] = { "DOG", "CAT", "RAT", NULL };
char **elem_p = str;

/* display using a pointer arthimatic */
while(*elem_p) {
    printf("str: %s\n", *elem_p);
    elem_p++;
}

Что вы сделали, чтобы увеличить указатель, хранящийся в первом элементе массива. Этот указатель никогда не будет слишком скоро равным нулевому указателю (если вообще будет), поэтому цикл не остановится, пока внутреннее значение этих указателей не переполнится или что-то еще не произойдет, так что он будет равен нулевому указателю. Затем вы передаете указатель на первый элемент массива в printf (вы передаете массив, но компилятор преобразует его в указатель - см. Ниже). Printf будет интерпретировать байты этих указателей как символы и печатать их, что приведет к распечатке мусора, если он не вылетит сразу.

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

str++

Потому что str - это массив. Это не указатель, даже если он может быть преобразован в указатель, который затем будет указывать на его первый элемент. Итак, мы создаем указатель, который изначально указывает на str[0], но снова увеличиваем его. Обратите внимание, что мы увеличиваем его после печати, поэтому мы также распечатываем первый элемент.

На самом деле, я думаю, я должен объяснить, почему вы не можете сделать str++. Ну, str это массив. Массив - это объект, который занимает фиксированный объем памяти. Выше массив занимает 4-кратный размер указателя на символ, 4 * sizeof(char*). То, что на первый взгляд выглядит как указатель, представляет собой блок элементов одного типа. Для адресации элементов компилятор может составлять указатель из массива в выражениях, который затем может использоваться для адресации элементов в массиве. Если вы сделаете str++, компилятор создаст указатель для вас. Но этот указатель является временным, существует только на короткое время с единственной целью немедленно что-то сделать с ним, но его нельзя изменить, например, увеличивая. По этой причине мы создаем реальную переменную-указатель, которую затем можем увеличивать.

1 голос
/ 18 марта 2009

str, будучи массивом, не может быть увеличен.

Прямо сейчас вы увеличиваете (*str), то есть str[0]: первый элемент этого массива. Поскольку этот элемент является указателем, вы увеличиваете указатель, заставляя его ссылаться на последующие элементы строки «DOG».

Вам нужен указатель, который может указывать (и таким образом проходить) элементы str. Поскольку элементы char*, указатель на них будет char** - двойной указатель.

1 голос
/ 18 марта 2009
(*str)++

Увеличивает значение, на которое указывает s. Вам нужно будет увеличить сам указатель и вывести значение pointee. Обратите внимание, что str не является l-значением, и вы также не можете увеличить его.

Кроме того, если вы увеличиваете сначала, то у вас остается только две допустимые строки, которые вы можете напечатать. Вы вызываете UB после этого.

Попробуйте это:

int main(void)
{
    /* we have added a sentinel to mark the end of the array */
    char *str[] = { "DOG", "CAT", "RAT", 0 };
    /* since str is an array, you cannot use it to loop, have a walker */
    char **w = str;

    /* display using a pointer arthimatic */
    while(*w)
    {
        printf("str: %s\n", *w++);
    }


    return 0;
}

Поиск приоритета оператора и связывания в C.

1 голос
/ 18 марта 2009

Проблема с вашим кодом в том, что вы увеличиваете разыменованный указатель str, который дает вам символ * для первого элемента в массиве (то есть, для собаки).

Вы должны увеличивать саму строку, а не то, на что она указывает.

Однако ваша проверка завершения цикла не будет работать в этом случае, так как в данный момент в массиве нет элемента, для которого выполняется str == 0. Чтобы это работало, вам нужно добавить четвертый элемент в массив, равный 0.

0 голосов
/ 18 марта 2009
while((*str)++)    
{        printf("str: %s\n", str);    }

Это увеличивает * str, что является буквой 'd'. Вы не хотите этого делать. Вы хотите увеличить указатель. Этот код должен делать то, что вы хотите:

while((str)++)    
{        printf("str: %s\n", str);    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...