1

I am writing a program, and in my program I need to Copy info from 1st 1D array into 2D array, but every time there is a \n in 1d array, it suppose to go into different slots in 2D array. For example if 1D array is Hello\nWorld in 2d array it will become hello/n in first slot and world in the second slot.

Here is my code But I am getting segmentation error. The array called chars is already made in my program before this step.

words = (char**) malloc(numWords*sizeof(char));
  int copyCountForChars=0;
  int copyCountForWords=0;


  while(copyCountForWords <= numWords)
    {

      words[copyCountForWords][copyCountForChars] = chars[copyCountForChars];
      // printf("%c",chars[copyCountForChars]);                                                    
      if(chars[copyCountForChars] == '\n')
        {
          //  printf("%c",chars[copyCountForChars]);                                               

          copyCountForWords++;

        }

      copyCountForChars++;
    }
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
user1335175
  • 181
  • 7
  • 20
  • 1
    You neglected to allocate any memory for that `numWords` sequence of pointers you allocated in your first line of code. Both dereferencing them (write or read, make no difference) and even *evaluating* them invokes undefined behavior. ([OT: Don't cast `malloc` in C code](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc?s=1|6.6202). – WhozCraig Feb 17 '15 at 05:45
  • Actually Numwords is declared earlier in my code, sorry. Numwords is just the number of words that 1D array contains – user1335175 Feb 17 '15 at 05:51
  • Actually that factoid has *nothing* to do with my comment; read it again. You're initially allocating a sequence of **pointers**. The pointers you allocated are themselves **indeterminate**; they point to the unknown; the undefined; the great beyond. They've been assigned no valid addresses. Dereferencing those pointers invokes *undefined behavior*. You need each pointer to point to *something* valid, probably another allocation per. – WhozCraig Feb 17 '15 at 05:58
  • Your code does not null terminate the strings when it encounters a newline. You also don't start copying at the next word's offset 0, which I think you probably should. You also don't allocate space the copied characters. – Jonathan Leffler Feb 17 '15 at 06:04
  • And I neglected to mention, `numWords * sizeof(char)`is wrong regardless. That should be `numWords * sizeof(char*)`, and ideally to avoid that mistake in the first place, `numWords * sizeof *words`. That assuming `words` is declared as `char **`, as you didn't include its declaration in your post. – WhozCraig Feb 17 '15 at 06:09
  • I am confused. Can anyone explain to me the right way how can I copy the content of 1D array to 2D array, where the word breaks are at newlines ? – user1335175 Feb 17 '15 at 07:09

3 Answers3

3

Memory allocation for a 2D array should be done like this.

words = malloc(sizeof(char *) * size1);
for(i = 0; i< size1; i++)
{
    words[i] = malloc(sizeof(char) * size2);
}
niyasc
  • 4,440
  • 1
  • 23
  • 50
  • 3
    Shouldn't that be sizeof(char*) in that first allocation? – paisanco Feb 17 '15 at 05:56
  • An effective technique is `words = (char **)malloc(sizeof(*words) * numWords);` in this context. You used `size1` where the question used `numWords`, which is marginally misleading. It is not clear how `size2` in your answer is calculated (and the corresponding size is not calculated in the question, AFAICS). – Jonathan Leffler Feb 17 '15 at 06:06
  • Stop repeating youself. Remove the casts. – Spikatrix Feb 17 '15 at 06:06
  • `sizeof(char)` is 1 by definition, thus multiplying with it is unnecessary. If it's possible that the element type changes, you should use `sizeof(**words)` instead (likewise `sizeof(*words)` in the first `malloc`). And like said above, you should not cast the return values of `malloc` (this is C, not C++). – Arkku Feb 17 '15 at 06:09
0

WhozCraig is right. Your malloc for words doesn't allocate enough memory and is probably causing crash for accessing memory outside the bounds. Here's why: Say numWords = 2, then the following line:

words = (char**) malloc(numWords*sizeof(char));

actually does malloc(2*1). sizeof(char) is 1.

You have only allocated 2 bytes of memory.

Did you mean sizeof(chars) in terms of allocation? That would give you the size of the 1 dimensional array. Even then you still have to copy each byte at a time from one array to another, which is not being done currently.

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

int main(){
    char str[100] = "hello\nworld\nstack\noverflow";

    int numWords = 4; // you can handle this part
    char **words = malloc(numWords * sizeof(char *));

    char *tok = strtok(str, "\n");
    int counter = 0;
    while(tok != NULL){
        words[counter] = tok;
        counter++;
        tok = strtok(NULL, "\n");
    }

    printf("%s\n", words[0]); // hello
    printf("%s\n", words[1]); // world
    printf("%s\n", words[2]); // stack
    printf("%s\n", words[3]); // overflow

}

I visualize pointer relations like this

diagram


If want to append \n at the end a string you can use this snippet. But I think it's bad coding stile when you are hiding \n inside variable.

int main(){
    char *str = "stackoverflow";
    int size = strlen(str);
    char str2[size+1];
    strcpy(str2, str);
    strcpy(str2+size, "\n");

    printf("%s", str2);
}
gkiko
  • 2,283
  • 3
  • 30
  • 50
  • Thank you very much, one question. How can I do it so every word array have /n at the end, so I don`t have to put \n when using printf. Also is this possible to do without using strings ? – user1335175 Feb 17 '15 at 07:58
  • You can use ascii codes to print characters and other symbols. [source](http://www.cquestions.com/2008/01/write-c-program-for-printing-ascii.html) But again, this is bad practice to use ascii codes and make your code hard to understand. – gkiko Feb 17 '15 at 11:20
  • Not really hiding \n in my variables if I understand your remark correctly, because my program is designed to used in combination with od -c command in linux, so I kinda want to see the \n at the end of every word. – user1335175 Feb 17 '15 at 21:17