如何将** argv复制到一个新变量?

时间:2016-04-22 23:26:08

标签: c memcpy

我想使用像memcpy之类的内容复制一个变量,例如char **argv但是如何?我可以知道大小以及如何参数化它,因为memcpy不会将二星作为参数。我必须写一个循环吗?

我必须在执行之前建立管道。因此,我希望在循环的每次迭代中“生成”argv之类的变量。

    token = strtok(cmd, "|");
    i = 0;
    while (token != NULL)
    {   
        printf("token %s\n", token);       
        makeArgs(token, &argc, &argv);
        for (int b = 0; b < argc; b++) {
           printf("makeargs %d: %s\n", b, argv[b]);   
        }   

        // Will copy argc characters from array1 to array2
       /* memcpy(makearg,argc, argc*18*sizeof(int));*/    
        shellcommand[i].argv = argv;
        i++;
        token = strtok(NULL, "|");
    }           
   /* do stuff */
   fork_pipes(argc, shellcommand);

我的目标是建立如下的管道。

/*  who | awk '{print $1}' | sort | uniq -c | sort -n */
static char *cmd0[] = { "who",                0 };
static char *cmd1[] = { "awk",  "{print $1}", 0 };
static char *cmd2[] = { "sort",               0 };
static char *cmd3[] = { "uniq", "-c",         0 };
static char *cmd4[] = { "sort", "-n",         0 };

static char **cmds[] = { cmd0, cmd1, cmd2, cmd3, cmd4 };

3 个答案:

答案 0 :(得分:5)

此代码制作了argv的深层副本:

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

int main(int argc, char** argv)
{
    // allocate memory and copy strings
    char** new_argv = malloc((argc+1) * sizeof *new_argv);
    for(int i = 0; i < argc; ++i)
    {
        size_t length = strlen(argv[i])+1;
        new_argv[i] = malloc(length);
        memcpy(new_argv[i], argv[i], length);
    }
    new_argv[argc] = NULL;

    // do operations on new_argv
    for(int i = 0; i < argc; ++i)
    {
        printf("%s\n", new_argv[i]);
    }

    // free memory
    for(int i = 0; i < argc; ++i)
    {
        free(new_argv[i]);
    }
    free(new_argv);
}

答案 1 :(得分:0)

由于使用@milleniumbug的指针,我制作了一个仅返回一个指针的版本,因此更易于跨实例或线程边界传递,并且在使用后更容易释放。没有您的提示,我就不会有线程安全的方法。

char **copy_argv(int argc, char *argv[]) {
  // calculate the contiguous argv buffer size
  int length=0;
  for(int i = 0; i < argc; i++)
  {
      length += (strlen(argv[i]) + 1);
  }
  char** new_argv = (char**)malloc((argc + 1) * sizeof(char*) + length);
  // copy argv into the contiguous buffer
  length = 0;
  for (int i = 0; i < argc; i++)
  {
      new_argv[i] = &(((char*)new_argv)[argc * sizeof(char*) + length]);
      strcpy(new_argv[i], argv[i]);
      length = (strlen(argv[i]) + 1);
  }
  new_argv[argc] = NULL;
  return(new_argv);
}

我想这个单一的指针结构是不可变的,并且易于复制。

答案 2 :(得分:0)

我喜欢@ conrad-b的解决方案,因为它在一个连续的块中分配内存。但是,其中有一些错误。

  • new_argv[i] = &(((char*)new_argv)[argc * sizeof(char*) + length]);将开始写入argv [0]数据,之后将写入终止NULL ptr。因此,new_argv [0]的前4个或8个字节将被清零。
  • length = (strlen(argv[i]) + 1);应该是+ =操作。

所以最终的解决方案应该更像这样:

char **copy_argv(int argc, char *argv[]) {
  // calculate the contiguous argv buffer size
  int length=0;
  size_t ptr_args = argc + 1;
  for (int i = 0; i < argc; i++)
  {
    length += (strlen(argv[i]) + 1);
  }
  char** new_argv = (char**)malloc((ptr_args) * sizeof(char*) + length);
  // copy argv into the contiguous buffer
  length = 0;
  for (int i = 0; i < argc; i++)
  {
    new_argv[i] = &(((char*)new_argv)[(ptr_args * sizeof(char*)) + length]);
    strcpy(new_argv[i], argv[i]);
    length += (strlen(argv[i]) + 1);
  }
  // insert NULL terminating ptr at the end of the ptr array
  new_argv[ptr_args-1] = NULL;
  return (new_argv);
}