(C ++) Основные вопросы относительно синтаксиса - PullRequest
7 голосов
/ 10 мая 2011

C ++ новичок здесь.У меня есть несколько основных вопросов.В int main( int argc, char *argv[] )

  1. Как char *argv[] должен быть прочитан (или высказан человеку)?
  2. Возможно ли очистить / стереть конкретный контент (ы), символ (ы) в этом случае такого массива?Если да, то как?
  3. Можно ли изменить размеры массивов?Если да, то как?
  4. Как скопировать все содержимое argv[] в одну переменную std::string?
  5. Существуют ли другие способы определения количества слов / параметры в argv[] без argc?Если да, то как?(*)

Буду признателен за объяснения (не код) для чисел 2-5.Я сам разберусь в коде (так учусь быстрее).

Заранее спасибо.

(*) Я знаю, что main(char *argv[]) незаконно.Я имею в виду, есть ли хотя бы способ, который вообще не включает argc, как в следующих выражениях:

for( int i = 0; i < argc; ++i ) {
    std::cout << argv[i] << std::endl;
}

и

int i = 0;    
while( i < argc ) {
    std::cout << argv[i] << std::endl;
    ++i;
}

или

int i = 0;
do { 
     std::cout << argv[i] << std::endl;
     ++i; } while( i < argc );

Ответы [ 7 ]

2 голосов
/ 10 мая 2011
  1. Это массив указателей на символ.

  2. В некотором роде - вы можете перезаписать их.

  3. Только путем копирования в новый массив.

  4. Написать цикл и добавить каждый argv [i] в ​​строку C ++.

  5. Большинство реализаций завершают массив указателем NULL. Я не помню, стандарт это или нет.

1 голос
/ 10 мая 2011
  1. Несколько параметров: массив указателей на символ ИЛИ массив C-строки.

  2. Вы можете назначить определенным символам их очистку или сдвинуть оставшуюся часть массива вперед для «стирания» символов / элементов.

  3. Нормальные массивы в стиле C не могут быть изменены. Если вам нужен массив с изменяемым размером в C ++, вы должны использовать std::vector.

  4. Вам придется перебирать каждый из элементов и добавлять их в строку. Это может быть достигнуто с помощью алгоритмов C ++, таких как copy в сочетании с ostream_iterator, используемым в ostringstream.

  5. Нет. Если бы было таким образом, не было бы необходимости в argc. РЕДАКТИРОВАТЬ: Очевидно, для argv только последний элемент массива является нулевым указателем.

1 голос
/ 10 мая 2011
char **argv[]

неправильно.Это должно быть либо char **argv, либо char *argv[], а не смесь обоих.И тогда он становится указателем на указатель на символы или, вернее, указателем на c-строки, т. Е. Массивом c-строк.:) cdecl.org также весьма полезен при таких вещах.
Тогда, для доступа, конечно.Просто получи доступ.:) argv[0] будет первой строкой, argv[3] будет 4-й строкой.Но я бы совершенно не рекомендовал заменять вещи в массиве, который не принадлежит вам или о котором вы знаете внутренности.
При изменении размера массива, поскольку вы пишете на C ++, используйте std::vectorкоторый делает все сложные вещи для вас и действительно безопасен.Как правило, это зависит от типа массива.Динамически распределяемые массивы (int* int_arr = new int[20]) могут, статические массивы (int int_arr[20]) не могут.
Чтобы скопировать все в argv в один std::string, переберите массив и добавьте каждую c-строку к вашемуstd::string.Я не рекомендовал бы, хотя, скорее, иметь std::vector<std::string>, то есть массив std::strings, каждый из которых содержит один из аргументов.

std::vector<std::string> args;
for(int i=0; i < argc; ++i){
  args.push_back(argv[i]);
}

В вашем последнем пункте, поскольку стандарт требует argv завершается указателем NULL, это довольно просто.

int myargc = 0;
char** argv_copy = argv;
while(++argv_copy)
  ++myargc;

while(++argv_copy) сначала увеличивает указатель массива, позволяя ему указывать на следующий элемент (например, послеПервая итерация будет указывать на c-строку # 2 (argv[1])).После этого, если указатель оценивается как ложный (если это NULL), то цикл тормозит, и у вас есть myargc.:)

0 голосов
/ 10 мая 2011

Массив в C / C ++ - это не объект, а просто указатель на первый элемент массива, поэтому вы не можете просто удалить или вставить значения.

Отвечая на ваши вопросы:

  1. char *argv[] можно прочитать как 'массив указателей на char'
  2. Это возможно, но включает в себя прямые манипуляции с данными в памяти, такие как копирование и / или перемещение байтов.
  3. Нет.Но вы можете выделить новый массив и скопировать необходимые данные
  4. , вручную скопировав каждый элемент в std::string объект
  5. Нет.

Как итог: C ++ оченьболее низкоуровневый язык, который вы думаете.

0 голосов
/ 10 мая 2011

1) Предполагается, что это будет char **argv или char *argv[], что a pointer to an array of characters более широко известно как an array of strings

2) CString - это библиотека std для манипулирования строками C (массивами символов). Вы не можете изменить размер массива без перераспределения, но вы можете изменить содержимое элементов, ссылаясь на него по индексу:

for(int i = 0; i < argc; ++i)
{
   //set all the strings to have a null character in the
   //first slot so all Cstring operations on this array, 
   //will consider it a null (empty) string
   argv[i] = 0;
}


3) Технически нет, однако их можно удалить, а затем перераспределить:

int *array = new int[15]; //array of size 15
delete[] array;
array = new int[50]; //array of size 50

4) Это один из способов:

string *myString;
if(argc > 0)
{
   myString = new string(argv[0]);
   for(int i = 1; i < argc; ++i)
      myString->append(argv[i]);
}

5) Да, согласно Кубби:

POSIX указывает окончательный нулевой указатель для argv, см. например " Приложение должно гарантировать, что последний член этого массива является нулевым указатель. "на pubs.opengroup.org / onlinepubs / 9699919799 / функции / exec.html

Что означает, что вы можете сделать:

char *val = NULL;
int i = 0;
do
{
   val = argv[i++]; //access argv[i], store it in val, then increment i
   //do something with val
} while(val != NULL); //loop until end of argv array
0 голосов
/ 10 мая 2011
  1. Он произносится как «массив указателей на указатели на символ» (обратите внимание, что это не сигнатура основной функции, которая является либо int argc, char **argv, либо int argc, char *argv[] - что эквивалентно).
  2. Массив argv является изменяемым (отсутствие const). Запрещается писать за пределами одной из строк или расширять массив; если вам нужно расширить строку, создайте ее копию и сохраните указатель в массиве; если вам нужно расширить массив, создайте копию массива.
  3. Они не могут быть изменены сами по себе, но могут быть истолкованы как меньший массив (что объясняет ответ на последний вопрос).
  4. Вы потеряете информацию таким образом - argv - это массив массивов, потому что отдельные аргументы для вас уже разделены. Вы можете создать список строк, используя std::list<std::string> args(&argv[1], &argv[argc]);.
  5. Не совсем. В большинстве систем argv NULL завершен, но это не гарантия.
0 голосов
/ 10 мая 2011
  1. char *argv[] можно читать как «массив указателей на символ»

    char **argv можно читать как: «указатель на указатель на символ»

  2. Да, вы можете изменить массив argv. Например, argv[0][0] = 'H' изменит первый символ первого параметра. Если под «стереть / очистить» вы имеете в виду удалить символ из массива и все автоматически переместится: не существует автоматического способа сделать это - вам нужно будет скопировать все символы один за другим слева (включая NULL прекращение)

  3. Нет, размеры массивов не могут быть изменены. Вам нужно будет создать новый и скопировать содержимое

  4. Как вы хотите представить ВСЕ строки параметров как 1 std :: string? Было бы разумнее скопировать его в массив std :: strings

  5. Нет, особой индикации последней записи в массиве нет. вам нужно использовать argc

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