复制字符串数组(或将它们复制到另一个数组)?

时间:2011-03-05 21:18:38

标签: c string pointers arguments

我需要在启动时传递给我的进程的参数。 这意味着,argv[]我需要除了第一个之外的所有内容(这是我的进程名称)。

我无法复制它,因为它是char * argv[]类型。 任何人都可以给我一个如何正确地做到这一点的要点,或者可能是一个小代码片段。我宁愿把头撞在墙上。

编辑:

澄清我的问题:

关键是我需要除argv的第一个参数以外的所有参数。所以我不能把它发送到其他进程,因为我实际上将它作为execv的参数。

8 个答案:

答案 0 :(得分:5)

没有必要复制字符串 - 它们将在程序的生命周期内持续存在,并且不允许您修改它们。只需将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;
}    

答案 1 :(得分:3)

请注意,argvchar **,如果需要,您可以将argv指针存储到此类型的全局变量中。

否则,要复制它,您需要分配一个数组并复制指针。如果你不需要自己复制字符串,那么这样的事情应该有效:

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

(尽管您可能想要或不想在copy_of_argv中为终结空指针分配额外的插槽作为标记)。

如果您因某些未知原因需要复制字符串,则会更复杂一些:

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 :(得分:3)

你在评论中写道“我的第一个程序将有参数列表'pname otherpname -arg1 -arg2 -arg3',我想用execv用-arg1 -arg2 -arg3调用otherpname。”在这种情况下,您要传递给execv的参数列表是[otherpname -arg1 -arg2 -arg3] ...传递给execv的参数列表正是otherpname的主例程将看作argv,并且它必须包含argv [0 ]通常是程序名称。方便的是,该列表正是argv + 1指向的......不需要复制任何内容。

[编辑] 但是,你确实有一个问题,即将execv传递给它的第一个参数 - exec程序的文件名。 otherpname需要是一个完全限定的路径,或者你应该使用execvp,它会在PATH中搜索该程序。

答案 3 :(得分:2)

如果你想要一个可修改的参数副本,请执行以下操作:

    #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();
    }

答案 4 :(得分:1)

有趣的是你应该说:

  

关键是我需要除argv的第一个参数以外的所有参数。所以我不能   只是把它发送到其他进程,因为我实际上使用它作为一个   execv的参数

这听起来很像我正在做的事情,我想设置LD_LIBRARY_PATH,然后使用我自己的ld.so副本运行二进制文件,这样根本就不会使用默认的系统共享库。执行的arg是我的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的内容都不会中断。

答案 5 :(得分:0)

如果要访问其中一个argv字符串,请执行以下操作:

printf(“%s”,argv [0]);

答案 6 :(得分:0)

你究竟需要对参数做些什么?

arg 1,arg [2],arg [3] ......等是简单的C字符串(char *)。

如果你需要将它们复制到另一个数组,你可以使用strcpy函数(例如strcpy(destination,arg[1]),但由于参数的值不会改变,你很可能不必复制它。

答案 7 :(得分:0)

对于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;
}