1

Assume I have char **argv, so that argv[0] = some string and argv[1] = another string etc...

I have another double pointer string array in a struct, call it s1->argv also defined as char **argv within the struct.

I am trying to copy argv into s1->argv1. I tried mallocing s1->argv to something with a max value (so 7 strings, each string of max 100 chars) and using strcpy but that obviously does not work. It only ends up copying argv[0]. This is how I used it: strcpy(*s1->argv, *argv)

How can I preserve each index of the array too?

darksky
  • 20,411
  • 61
  • 165
  • 254

2 Answers2

4

It sounds like you just want to copy the entire argv into another char** value. If so then do the following

char** copy_all(char** argv, int length) {
  char** ppDest = malloc(sizeof(char**) * length);
  if (!ppDest) {
    return NULL;
  }

  int i = 0;
  for (i < length; i++) {
    char* pCurrent = argv[i];
    size_t currentLength = strlen(pCurrent);
    ppDest[i] = malloc(currentLength + 1);
    if (!ppDest[i]) {
      goto Error;
    }
    strcpy(ppDest[i], argv[i]);
  }

  return ppDest;

Error:
  while (i > 0) {
    free(ppDest[i - 1]);
    i--;
  }
  free(ppDest);
  return NULL;
}
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
0

The code below makes a copy of argc and argv arguments of main into user defined structure. The copy is exactly the same as original arguments (argv is terminated by NULL as in main). This code does not handle any abnormal events (like malloc failures, signal interruption etc.).

You may want to avoid casting the result of malloc (it is not required in C), there is a lot of debate whether this casting is a good or bad thing. The choice is yours. I value portability more, so I choose to cast, compile with all warnings enabled and eliminate all of them in the code (see the comments to this answer).

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

struct my_struct
{
    int    argc;
    char** argv;
};

int main(int argc,char** argv)
{
    int    i = 0;
    size_t n = 0;
    struct my_struct s;

    memset(&s,0,sizeof(s));
    s.argc = argc;
    /* alloc one more element than 'argc' to terminate 's.argv' with NULL */
    s.argv = (char**)malloc((argc + 1) * sizeof(char*));
    /* terminate 's.argv' with NULL exactly as 'argv' in 'main' */
    s.argv[argc] = NULL; 
    for(i = 0; i < argc; ++i)
    {
        n = strlen(argv[i]) + 1;
        s.argv[i] = (char*)malloc(n);
        strcpy(s.argv[i],argv[i]);
    }
    return 0;
}

Another option for copying the strings in argv could be using strdup function, then you could replace the three lines:

n = strlen(argv[i]) + 1;
s.argv[i] = (char*)malloc(n);
strcpy(s.argv[i],argv[i]);

with

s.argv[i] = strdup(argv[i]);
sirgeorge
  • 6,331
  • 1
  • 28
  • 33
  • This is just an example, not intercontinental missle control code. If malloc failes, then you can (in most cases) only abort. What if your machine is hit by a meteorite while executing the code ? – sirgeorge Mar 13 '12 at 23:15
  • I don't think the C standard covers meteorite impact. :) – JaredPar Mar 13 '12 at 23:21
  • 1
    Not yet, but I suspect the guys from C++ standardization committe may be already working on it :) – sirgeorge Mar 13 '12 at 23:25
  • Don't cast `malloc` unless you're writing C++. – Alex Reynolds Mar 13 '12 at 23:47
  • @Alex Reynolds: I know that you don't have to do it, but not doing it does not necessary means it is a good thing. When you are casting pointers explicitly and compiling with '-Wall' (gcc) it helps to avoid many nasty errors. Moreover, it makes your intensions clear to the reader(s) of your code. – sirgeorge Mar 13 '12 at 23:57
  • There is a lot of arguments for and against this practice. I am on the 'against' side. non-casting the result of malloc is not an absolute truth - it all depends what you value more (e.g. portability vs readability). You can see clearly the debate in the post that you sent the link to. – sirgeorge Mar 14 '12 at 01:43
  • Casting has nothing to do with portability. Portability is about libraries across platforms, not between C++ and C, which are two different languages (which share some syntactic similarities). – Alex Reynolds Mar 14 '12 at 20:55
  • That is your opinion on the subject of portability. What about compatibility with older compilers ? If you do not loose anything (maybe a litle bit of readability) then what is the problem with this (almost religious) belief about casting. BTW: I read everything in the post that you sent the link to. The guy is WRONG in quite a few points (I veryfied it myself - independent thinking is a good thing). – sirgeorge Mar 14 '12 at 21:00
  • Your answer is wrong or at least highly questionable in several respects. I'll leave it at that. – Alex Reynolds Mar 15 '12 at 04:39