дублирование массива строк (или копирование их в другой массив)? - PullRequest
4 голосов
/ 06 марта 2011

Мне нужны аргументы, которые были переданы моему процессу, когда он был запущен. Это означает, что argv[] мне нужно все, кроме первого (это имя моего процесса).

У меня проблемы с копированием, потому что это тип char * argv[]. Может кто-нибудь дать мне суть того, как это сделать правильно, или, возможно, небольшой фрагмент кода. Я бы предпочел, чтобы я ударился головой о стену.

EDIT:

Разъяснение моей проблемы:

Главное, мне нужно все, кроме первого аргумента argv. Поэтому я не могу просто отправить его другим процессам, так как на самом деле я использую его в качестве аргумента execv.

Ответы [ 8 ]

5 голосов
/ 06 марта 2011

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

#include <stdio.h>

int myargc;
char **myargv;

void print_args()
{
    int i;
    for (i = 1; i < myargc; ++i) {
        puts(myargv[i]);
    }
}    


int main(int argc, char **argv)
{
    myargc = argc;
    myargv = argv;

    print_args();

    return 0;
}    
3 голосов
/ 06 марта 2011

Вы написали в комментарии «Моя первая программа будет иметь список аргументов« pname otherpname -arg1 -arg2 -arg3 », и я хочу использовать execv для вызова otherpname с -arg1 -arg2 -arg3».В этом случае список аргументов, который вы хотите передать в execv: [otherpname -arg1 -arg2 -arg3] ... список аргументов, передаваемый в execv, - это то, что основная подпрограмма otherpname будет видеть как argv, и она должна включать argv [0] который обычно является именем программы.Удобно, что этот список является именно тем, на что указывает argv + 1 ... не нужно ничего копировать.

[править] Однако у вас есть проблема с тем, что передать execv как его первый аргумент - имя файла программы для exec.Либо otherpname должно быть полным путем, либо вы должны использовать execvp, который ищет PATH для программы.

3 голосов
/ 06 марта 2011

Обратите внимание, что argv является char **, при необходимости вы можете просто сохранить указатель argv на глобальную переменную этого типа.

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

char **copy_of_argv = malloc(sizeof(char *) * (argc-1));
memcpy(copy_of_argv, argv + 1, sizeof(char *) * (argc - 1));

(хотя вы можете или не хотите выделять дополнительный слот в copy_of_argv для завершающего указателя NULL в качестве стража).

Если вам нужно скопировать строки по неизвестной причине, это немного сложнее:

int i;
char **copy_of_argv = malloc(sizeof(char *) * (argc-1));
for (i = 0; i < argc - 1; i++) {
    copy_of_argv[i] = strdup(argv[i + 1]);
}

(опять же, вы можете выделить дополнительный слот для дозорного).

2 голосов
/ 06 марта 2011

Если вы хотите, чтобы изменяемая копия аргументов делала это:

    #include <stdio.h>

    void main(int argc, char** argv) {
            int myargc = argc;
            char** myargv = malloc( (argc-1)*sizeof(void*));
            int i;
            for(i=1; i<argc; i++) {
                    int len = strlen(argv[i]);
                    myargv[i-1] = malloc(len+1);
                    memcpy(myargv[i-1], argv[i], len+1); // +1 so \0 copied too.
            }               
            getch();
    }
1 голос
/ 22 июля 2011

Интересно, что вы должны сказать:

Главное, мне нужны все, кроме первого аргумента аргумента argv.Поэтому я не могу просто отправить его другим процессам, так как на самом деле я использую его как аргумент для execv

Это очень похоже на то, что я делаю, где я хочу установить LD_LIBRARY_PATH, а затемзапустите бинарный файл, используя мою собственную копию ld.so, чтобы системные библиотеки по умолчанию вообще не использовались.Аргумент execve является моей копией ld.so, но как только запускается настоящий двоичный файл, я хочу, чтобы его argv выглядел нормально (и окружающий мир).Вот как я это сделал в Linux:

include <stdlib.h>
#include <stdio.h>

#define PYBINARY "/data1/packages/python272/bin/python"
#define LDSO "/data1/packages/python272/lib/ld-linux-x86-64.so.2"
#define MYLIBS "/data1/packages/python272/lib"

extern char **environ;

main(int argc, char **argv, char **envp)
{
  int retcode;
  char **e;
  char **myargv;

  setenv("LD_LIBRARY_PATH",MYLIBS,1);
  setenv("_",PYBINARY,1);

  /* copy argv */
  int i = 0;
  myargv = (char **)malloc(sizeof(char *) * 100);
  for(;argv[i] != NULL; i++) {
    myargv[i+1] = (char *)malloc(sizeof(char) * (strlen(argv[i]) + 1));
    memcpy(myargv[i+1], argv[i], strlen(argv[i]));
  }
  myargv[i+1] = NULL;
  myargv[0] = LDSO;
  myargv[1] = PYBINARY;

  e = myargv;
  while (*e != NULL){
    printf("arg: %s\n",*e++);
  }

  retcode = execve(LDSO, myargv, environ);
  perror("exec2: execve() failed");
  exit(1);
}

Если вы поместите это в test.py:

import sys
print sys.argv
import os
print os.environ["_"]

и запустите его с python -i test.py, вы получите те же результаты, что и ./mypy -i test.py поэтому все, что зависит от argv или envp, не сломается.

0 голосов
/ 06 марта 2011

Для execv, что-то вроде этого, тогда

#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    int i;
    char** myargs;

    if (argc <= 0)
    {
        return EXIT_FAILURE;
    }

    myargs = malloc(sizeof *myargs * (argc + 1));

    myargs[0] = "your_program_name_here"; 
    for (i = 1; i < argc; ++i)
    {
        myargs[i] = argv[i];
    }
    myargs[argc] = 0;
    execv("/your/program/here", myargs);
    return EXIT_FAILURE;
}
0 голосов
/ 06 марта 2011

Что именно вам нужно сделать с аргументами?

arg 1 , arg [2], arg [3] ... и т. Д. - простые строки C (char *).

Если вам нужно , чтобы скопировать их в другой массив, вы можете использовать функцию strcpy (например, strcpy(destination,arg[1]), но так как значения параметров не являютсяСобираясь измениться, вам, скорее всего, не придется его копировать.

0 голосов
/ 06 марта 2011

Если вы хотите получить доступ к одной из строк argv, сделайте это:

printf ("% s", argv [0]);

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