-1

My question is very simple, but I still can't manage to get things right because I am simply not used to the C language.

I have an array that looks like this:

char *itemArr[] = {
    "GPGGA",
    "193914.00",
    "5312.983745",
    "N",
    "00206.32143",
    "E",
    "4,17",
    "0.6",
    "43.48",
    "M",
    "47.46",
    "M",
    "1.0",
    "0000",
    "GPGLL,4916.45,N,12311.12,W,225444,A,M"
};

And I would like to add itemArr to a new multidimensional array, but when I try to copy the content of itemArr to protocols array like this:

int index = 0;
char *protocols[100][TOTAL_ITEMS];
memcpy(&protocols[index++], &itemArr, sizeof(itemArr));

It does only copy the first item of the itemArr and not the rest. So I can only see the first item like the following code:

printf("itemArr copy in protocols - index 0: %s\n", protocols[0][0]);

For example, this does not work:

printf("itemArr copy in protocols - index 1: %s\n", protocols[0][1]);

Please help me with a better example of how I should use memcpy, to copy an array to a multidimensional array. Thanks!

EDIT:

I tried my best to explain the code as simple as possible, but I guess that it only helps when pasting the real one below:

void getInputProtocolFromUser(protocol) {

char input[MESSAGE_SIZE];

do {
    printf("Voer hier een NMEA protocol in:");
    gets(input, MESSAGE_SIZE);
} while (input[0] == '\*' || input[0] == ' ');

strncpy_s(protocol, MESSAGE_SIZE, input, MESSAGE_SIZE);
}

void splitToArray(char* protocol, char *newArray[]) {

// strdup copies message to string pointer in order to create an array of the items inside the message
char *string = _strdup(protocol),
    *token;

int c = 0;

/* get the first token */
token = strtok(string, ",");

/* walk through other tokens */
while (token != NULL)
{

    char *copy = malloc(sizeof(char) * strlen(token));
    strcpy(copy, token);

    newArray[c++] = copy;
    token = strtok(NULL, ",");
}
}

void compareProtocols(char *input, char *protocols[]) {

int index = 0;
char *inputArray[TOTAL_ITEMS+1];
splitToArray(input, inputArray);
inputArray[TOTAL_ITEMS] = input;
memcpy(&protocols[index++], &inputArray, 15);

int i;
for (i = 0; i < sizeof(MESSAGES) / sizeof(MESSAGES[0]); i++) {
    char *messageArray[TOTAL_ITEMS];
    splitToArray(MESSAGES[i], messageArray);
    memcpy(&protocols[index++], &messageArray, 15);

    //processProtocol(messageArray, inputArray);
}
}

int main(void) {

char *protocols[100][TOTAL_ITEMS];
char *inputProtocol = (char *)malloc(MESSAGE_SIZE);

getInputProtocolFromUser(inputProtocol);
compareProtocols(inputProtocol, protocols);

printf("Input index 0: %s\n", protocols[0][1]);
free(inputProtocol);

return 0;
}
Aerial
  • 1,185
  • 4
  • 20
  • 42
  • 1
    So... we will assume you forgot the `[]` in your first code snippet? – WhozCraig Jul 08 '15 at 20:31
  • 1
    That is not an array, but a pointer to `char`. I somewhat wonder your compiler does not complain. Enable warnings! – too honest for this site Jul 08 '15 at 20:32
  • possible duplicate of [How to find the 'sizeof'(a pointer pointing to an array)?](http://stackoverflow.com/questions/492384/how-to-find-the-sizeofa-pointer-pointing-to-an-array) – Siguza Jul 08 '15 at 20:35
  • Oops, I forgot to add [] in here. It is an array, trust me. Not a char pointer, I just forgot to place it in here. @WhozCraig Thanks for the warning, it should be with the square braces. – Aerial Jul 08 '15 at 20:35
  • @Xarialon: Your code works as intended. All elements are copied, assuming `TOTAL_ITEMS` is large enough to accommodate your `itemArr` array. – AnT stands with Russia Jul 08 '15 at 20:37
  • @AnT Well, it doesn't... – Aerial Jul 08 '15 at 20:38
  • 1
    @Xarialon: Yes, it does. See for yourself: https://ideone.com/IVtAUj Unless you have different expectations. In the latter case you have to explain what you expect to happen. "This does not work" is not a meaningful description of the problem. – AnT stands with Russia Jul 08 '15 at 20:39
  • 1
    If your array was declared in a different function from your `memcpy()` call, `sizeof(itemArr)` will give the size of the pointer it decayed to rather than the size of the array contents. Try passing the size separately if that's the case. – Dmitri Jul 08 '15 at 20:42
  • @Xarialon: I suspect that you are providing misleading information. In your actual code you probably forgot the `[]` in `char *itemArr[]` and the lousy diagnostic in GCC (do you use GCC?) accepted the broken code. GCC in its default configuration has a very poor quality disgnostics. You have to make an effort to properly configure it in order to whip it in some passable shape. I suspect that you fell a victim to it. Alternatively, you could have fallen into the trap described by Dmitri. – AnT stands with Russia Jul 08 '15 at 20:42
  • @Xarialon: Here's a broken version https://ideone.com/huRkK1, which some genius at GNU decided should be to accepted as valid C code. At least they issue a warning... Ideone doesn't show it though. – AnT stands with Russia Jul 08 '15 at 20:48
  • @Dmitri I changed the size with a const int value, but that didn't solve. Instead of having the second index value of the itemArr, I get to see the first index value of another itemArr. What should I do? I have pasted the code below the EDIT text. Please let me know. – Aerial Jul 08 '15 at 21:11
  • @AnT I have exactly this same problem, what should I do? – Aerial Jul 08 '15 at 21:11
  • @Xarialon: What's `15` in `memcpy` calls? Where did `15` came from? Why `15`? – AnT stands with Russia Jul 08 '15 at 21:22
  • @AnT 15 is the max size, check URL: http://www.cplusplus.com/reference/cstring/memcpy/ I have about 15 elements in itemArr, that's why. – Aerial Jul 09 '15 at 00:28

2 Answers2

1

The original version of your post declared itemArr as

char *itemArr = {
  "GPGGA",
  "193914.00",
  ...

i.e. without the [] in the declarator. My crystal ball tells me that that's what you have in your actual code.

This is not a valid declaration in C language, but GCC (if you use GCC) accepts such declarations for some reason that's beyond my understanding. (The compiler usually issues a warning about excessive number of initializers.) The declaration is effectively translated into

char *itemArr = "GPGGA";

with the rest of the initializers discarded. The behavior of your code immediately follows from that.

If one adds the missing [] to the declaration of itemArr, the code begins to work as intended. Everything gets copied to the target array.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
0

The following code works as expect on my Mac :

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

int main()
{
    int TOTAL_ITEMS = 15;

    char *itemArr[] = {"GPGGA",
                       "193914.00",
                       "5312.983745",
                       "N",
                       "00206.32143",
                       "E",
                       "4,17",
                       "0.6",
                       "43.48",
                       "M",
                       "47.46",
                       "M",
                       "1.0",
                       "0000",
                       "GPGLL,4916.45,N,12311.12,W,225444,A,M"};

   int index = 0;
   char *protocols[100][TOTAL_ITEMS];
   memcpy(&protocols[index++], &itemArr, sizeof(itemArr));

   printf("itemArr copy in protocols - index 0: %s\n", protocols[0][0]);
   printf("itemArr copy in protocols - index 1: %s\n", protocols[0][1]);
   printf("itemArr copy in protocols - index 0: %s\n", protocols[0][2]);
   printf("itemArr copy in protocols - index 1: %s\n", protocols[0][3]);
   printf("itemArr copy in protocols - index 0: %s\n", protocols[0][4]);
   printf("itemArr copy in protocols - index 1: %s\n", protocols[0][5]);
}

Maybe you should fix the itemArr declaration to itemArr[]. Your compiler might be throwing a warning and you're ending up with undesired behavior.