Операции с двойным указателем

Предположим, у меня есть char **argv.

Во-первых, как я могу распечатать все строки в argv? Я пробовал следующее:

char *temp;
temp = *argv; // Now points to the first string?
while (temp != NULL) {
    printf("%s ", temp);
    temp++;
}

Здесь, когда temp увеличивается, он пропускает только один символ. Почему это происходит? Я знаю, что argv — это массив, содержащий точки. Каждый указатель указывает на массив char*. Если да, то почему это не работает? Я знаю, что, поскольку temp имеет тип char, увеличение этого указателя увеличит его на 1 char (или байт). Если да, то как я могу увеличить указатель на следующий массив и распечатать эту строку?


person darksky    schedule 25.03.2012    source источник


Ответы (5)


Он пропускает только один символ, потому что temp является указателем на char. Добавляя единицу, вы говорите компилятору переместить указатель на следующий char в памяти.

argv — это массив указателей. Что вам нужно сделать, так это перейти к следующему указателю на каждой итерации. Что-то типа:

char **temp = argv;  // temp is a pointer to a *pointer*, not a pointer to a *char*
while (*temp != NULL) {
    printf("%s ", *temp);
    temp++;
}
person Oliver Charlesworth    schedule 25.03.2012

Вам нужно увеличить argv, а не *argv. С локальной копией это выглядит так:

for (char ** p = argv; *p; ++p)      // or "*p != NULL"
{
    char * temp = *p;                // now points to the first string!
    printf("%s ", temp);             // or just "printf("%s", *p);"
}
person Kerrek SB    schedule 25.03.2012
comment
Является ли последний элемент argv нулевым? Я ожидаю, что это убежит от конца массива. - person Collin; 25.03.2012
comment
@CollinHockey: Да, этого требует стандарт. См. 5.1.2.2.1 стандарта C99. - person Oliver Charlesworth; 25.03.2012
comment
@CollinHockey: Судя по неудачной попытке ОП, я бы так предположил, а также потому, что в поле зрения нет других очевидных условий прекращения. Оли: ОП не сказал, что мы имеем дело со стандартным аргументом main, но давайте все притворимся, что это так. - person Kerrek SB; 25.03.2012
comment
@OliCharlesworth Приятно знать. Я предположил, что он использует стандартную пару argv/argc где-то в main. - person Collin; 25.03.2012
comment
Нет, не имеет дело со стандартным основным аргументом, но он завершается NULL. - person darksky; 25.03.2012

Во-первых, вам нужно понять, что такое char** argv. Это массив указателей на char. Указатели в этом массиве не обязательно находятся где-то рядом друг с другом в адресном пространстве. Что вы хотите, так это:

char** temp;
temp = argv;
while(temp != argv + argc) {
    printf("%s ", temp);
    temp++;
}

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

person Collin    schedule 25.03.2012
comment
argc нет. Это не стандартный главный аргумент. - person darksky; 25.03.2012

Вы должны увеличить argv, а не *argv. Обратите внимание, что если ваш argv является параметром функции main, его можно изменить, и вы можете использовать его следующим образом:

    while (*argv++) {
        printf("%s\n", *argv);
    }
person ouah    schedule 25.03.2012
comment
Если ему нужно только напечатать строковое значение, это самая компактная форма. - person ouah; 25.03.2012

то, что вы, вероятно, хотите сделать, это:

char* a = argv[0];  // first arg
char* b = argv[1];  // second arg
char* c = argv[2];  // third arg

что эквивалентно этому:

char* a = *(argv + 0);
char* b = *(argv + 1);
char* c = *(argv + 2);

который вы затем захотите обобщить в цикл.

person Preet Kukreti    schedule 25.03.2012