2015-06-24 1 views
3

Я хочу использовать следующий код, но без индексации массива с «[] []» и заменить его с указателямиИспользование указателей перебирать ARGV []

for (int i = 0; i < argc; i++) { 
    for (int j = 0; argv[i][j] != '\0'; j++) { 
     //code 
    } 
} 

Я знаю, что вы можете использовать указатели для перемещения массива, но я не уверен, как это сделать с неопределенной длиной во втором массиве, в этом случае строка из ввода. Поскольку каждый элемент argv [] может иметь разную длину, я хочу убедиться, что я могу правильно прочитать символы и узнать, когда заканчивается каждый элемент argv [], и начинается следующее.

Я ожидаю, что это будет что-то вроде: (. Если следующий заголовок основной неправильно, скажите, пожалуйста)

int main(int argc, char **argv) { 
    for (int i = 0; i < argc; i++) { 
     while(argv != '\0') { 
      //code 
      *argv+1; 
     } 
     //to skip null character 
     argv+1; 
    } 
} 
+2

Вы, кажется, считаете, что 'argv' является непрерывным блоком памяти. Я не думаю, что это безопасное предположение. –

+1

@CareyGregory - это право. Вы не можете просто предположить, что следующий элемент сразу после нулевого байта. Но вы можете смело предположить, что каждый элемент имеет одинаковый размер, поэтому можно с уверенностью предположить, что элементы находятся от 'argv' до' argv + argc-1'. – alvits

ответ

4

Поскольку for петля позволяет любой вид значений, не обязательно целые числа для «цикла индекс», ваш цикл может быть переписан так:

for (char **a = argv ; a != argv+argc ; a++) { 
    for(char *p = *a ; *p != '\0' ; p++) { 
     // code uses *p instead of argv[i][j] 
    } 
} 

внутренний цикл использует p в качестве переменной цикла, который увеличивается с регулярным p++ и проверенного с *p != '\0'. Условие цикла может быть сокращена до *p, так что внутренний контур будет выглядеть следующим образом:

for(char *p = *a ; *p ; p++) 
+0

Как бы вы устранили индексирование с помощью argv [i]? Возможно, мне следовало бы удалить верхний цикл, чтобы сделать его более понятным. То, что вы написали, пойдет в каждый отдельный поддиапазон из argv [] []. Так как это все рассматривается как линейный 1D-массив, я должен подумать об этом без аргументов. Часть его находила бы конец строки, поэтому внешний цикл был бы «\ n» –

+2

@BlakeLassiter Кто сказал, что это все линейный массив 1D? –

+0

комментарий должен сказать * код использует \ * p вместо ... * –

-1

Имейте в виду, что ARGV [] является, по существу, массив указателей, что означает, что * (ARGV + я) будет добавьте размер указателя i * к базовому addr (в данном случае argv) и сдерживайте его в указатель на строку. Затем вы можете манипулировать каждым указателем на строку по желанию. Следующий код представляет собой пример распечатки всех строк в ARGV:

int main(int argc, char *argv[]){ 
    int i; 
    for(i = 0; i < argc; i++) 
     printf("%s\n", *(argv+i)); 
    return 0; 
} 
+1

Какой смысл цикла 'for' здесь, когда он будет перебирать все« argv »на первом проходе. Что сделают последующие проходы? Segfault? – alvits

+0

Спасибо @alvits за указание. Цикл while в моем предыдущем ответе подвержен ошибкам. Я обновил свой ответ. – lordofire

2

Да, вы можете перебирать argv с использованием указателей.

Внутренняя петля сообщает p, чтобы указать в начале argv+i и прокрутить ее до тех пор, пока она не достигнет \0.

#include <stdio.h> 
int main(int argc, char **argv) { 
    int i; 
    char *p; 
    for(i=0; i < argc; i++) { 
     for(p=*(argv+i); *p; p++) 
      printf("%c", *p); 
     printf("\n"); 
    } 
} 

Если вы заинтересованы только в обходе каждой аргументы, но не заинтересован в разборе каждого символа, то вы можете просто.

#include <stdio.h> 
int main(int argc, char **argv) { 
    int i; 
    char *p; 
    for(i=0; i < argc; i++) { 
     printf("Argument position %d is %s\n", i, *(argv+i)); 
    } 
} 
1

Вы можете использовать любой any_t * для перебора любого any_t[], в данном случае:

int main(int argc, char **argv) { 

    char **i = argv; //iterator of argv 
    char **e = argv + argc; //end of argv 

    for(; i != e; ++i) { 

    char *j = *i; //iterator of *i 

    //condition: *j mean *j != 0 
    for(; *j; ++j) { 
     printf("%c", *j); 
    } 

    printf("\n"); 

    } 

    return 0; 

} 
+0

Хороший ответ. Но ОП запрашивает 'c' не' C++ '. – alvits

+0

@alvits Я не заметил, спасибо – DMaster

+0

@CareyGregory Это всего лишь пример для вложенного цикла, обратите внимание, что вопрос касается вложенного цикла, а не «как распечатать последовательность». Я использую 'printf' вместо строки' // code' – DMaster

2

Учитывая, что последний элемент в argv является NULL, вам не нужно индексировать или сравнивать что-либо с argc если вы действительно этого не хотите.

int main(int argc, char *argv[]) { 
    for (char **arg = argv; *arg; ++arg) { // for each arg 
    for (char *p = *arg; *p; ++p) {  // for each character 
     process(*p); 
    } 
    } 
} 

*arg будет NULL в конце списка аргументов, который является ложным. *p будет '\0' в конце каждой строки, что является ложным.

От N1256 5.1.2.2.1/2

Если они объявлены, параметры к основной функции должны соблюдать следующие ограничения:

- Значение ARGC должно быть неотрицательным.

- argv [argc] должен быть нулевым указателем.