2

I am trying to copy a 1D array of Strings into a 2D array of strings in C.

I was able to achieve this with integer enter image description here

//Here is what I tried for integers.
        int main() 
    { 
        int arr[3][3];
        int arr2[9]={1,2,3,4,5,6,7,8,9}; 
    
        int i,j,k=0; 
    
        for(i=0; i<3;i++){
            for(j=0; j<3;i++){
              arr[j][i] = arr2[i];
                //rintf("%d\n",arr2[i]);
            }
            
        }
    
     for(i=0; i<3; i++) { 
        for(j=0; j<3; j++) 
          printf("%2d  ", arr[j][i]); 
        printf("\n"); 
      } 
    
        return 0; 
    } 

I changed my data to char and I tried to run the same code I got a segmentation error. Here is what I have tried so far and it didnt work. error :Segmentation fault (core dumped)

 #include<stdio.h> 
#include<string.h> 
 
int main() 
{ 
    char *d[3][3];  // Destination array 

    char *s[9]={"orange","apple","table","chair","cable","TV", "124","HI"};   // Source 1 Day array

    int i,j,k=0; 

    for(i=0; i<3;i++){
        for(j=0; j<3;i++){
            
          strcpy(d[j][i], s[i]);
           
        }
            }

 for(i=0; i<3; i++) { 
    for(j=0; j<3; j++) 
      printf("%s  ", d[j][i]); 
    printf("\n"); 
  } 

    return 0; 
} 

I have made some adjustment and now it print some weird strings

#include<stdio.h> 
#include<string.h> 
 
int main() { 

    char d[3][3] ={0};  // Destination array 

    char s[9][8]={"orange","apple","table","chair","cable","TV", "124","HI"};   // Source 1 Day array

    int i,j,k=0; 
    
    for(i=0; i<3;i++){
        for(j=0; j<3;j++){

            d[j][i] = *s[i];
           
        }
            }
    
    for(i=0; i<3; i++) { 
        for(j=0; j<3; j++) 
            printf("%s  ", &d[j][i]); 
            printf("\n"); 
    } 

    return 0; 
} 

enter image description here

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Moodkiller
  • 43
  • 7
  • In the line `for(j=0; j<3;i++){`, I believe `i++` supposed to be `j++`. Otherwise, the loop will never end. – Andreas Wenzel Jun 16 '22 at 14:13
  • In your first code `arr[j][i] = arr2[i]` should be something like `arr[j][i] = arr2[i*3+j]` – wohlstad Jun 16 '22 at 14:13
  • In your second code you didn't allocate the space for the `char*` elements in `s`. – wohlstad Jun 16 '22 at 14:15
  • Have you tried running your code line by line in a debugger while monitoring the values of all variables, in order to determine in which line your program stops behaving as intended? If you did not try this, then you may want to read this: [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/q/25385173/12149471) You may also want to read this: [How to debug small programs?](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) – Andreas Wenzel Jun 16 '22 at 14:16
  • @AndreasWenzel I fixed and made some other adjustment now I am getting some weird value – Moodkiller Jun 16 '22 at 14:23
  • You did `char *s[9]` but there are only 8 strings in the initializer for it (i.e.) `s[8]` will be `NULL` – Craig Estey Jun 16 '22 at 14:24
  • @Moodkiller: Normally, you should not change your question, as this invalidates existing answers. However, since you do not have any existing answers yet (only comments), it would probably be appropriate to change your question to your current problem. Note that you can [edit] your question. – Andreas Wenzel Jun 16 '22 at 14:29
  • @AndreasWenzel I just wanted to add some of the adjustment, but Ok Thank you. – Moodkiller Jun 16 '22 at 14:31
  • 1
    Please remove the images of input and output and copy paste the actual text instead. – Gabriel Staples Jun 16 '22 at 14:32
  • Note that to use `strcpy` you have to allocate space in `d` with (e.g.) `malloc`. Or, you can do: `d[j][i] = strdup(s[i]);` instead. In fact, you could just do: `d[j][i] = s[i];` if you don't change the data – Craig Estey Jun 16 '22 at 14:33
  • Note that your change from `char *d[3][3]` to `char d[3][3]` is wrong. The former had space for 9 strings (_if_ you allocated it). But, the second has space for [only] 3 strings and the max length of any of the strings is 2 (i.e. 2 chars + 1 zero byte for the string terminator). – Craig Estey Jun 16 '22 at 14:37
  • @CraigEstey Thank you, I made those changes and Now I am getting duplicate columns instead of having unique columns orange orange orange apple apple apple table table table chair chair chair – Moodkiller Jun 16 '22 at 14:44

3 Answers3

1

This for loop

    for(i=0; i<3;i++){
        for(j=0; j<3;i++){
          arr[j][i] = arr2[i];
            //rintf("%d\n",arr2[i]);
        }
        
    }

is incorrect. In the inner loop there are used the same elements arr2[i] where i is changed from 0 to 2 inclusively.

You need to write

    for(i=0; i<3;i++){
        for(j=0; j<3;i++){
          arr[j][i] = arr2[ 3 * i + j];
        }
    }

Another way to write loops is the following

    for ( i = 0; i < 9; i++ )
    {
        arr[i / 3][i % 3] = arr2[i];
    }

As for arrays of pointers of the type char * then the nested loops will look similarly

for(i=0; i<3;i++){
    for(j=0; j<3;i++){
        
      d[i][j] = s[ 3 * i + j];
       
    }
}

provided that the array s is declared like

char * s[9]={"orange","apple","table","chair","cable","TV", "124","HI"};   

And to output the result array you need to write

 for(i=0; i<3; i++) { 
    for(j=0; j<3; j++) 
      printf("%s  ", d[i][i]);
                     ^^^^^^^ 
    printf("\n"); 
  } 

As for your last program then it can look like

#include<stdio.h> 
#include<string.h> 
 
int main( void ) 
{ 

    char d[3][3][8] ={0};  // Destination array 

    char s[9][8]={"orange","apple","table","chair","cable","TV", "124","HI"};   // Source 1 Day array

    for( size_t i = 0; i < 3; i++ )
    {
        for ( size_t j = 0; j < 3;j++ )
        {
            strcpy( d[j][i], s[3 * i + j] );
           
        }
    }
    
    for ( size_t i = 0; i < 3; i++ ) 
    { 
        for ( size_t j = 0; j < 3; j++ )
        { 
            printf( "%s  ", d[i][j] ); 
        }
        putchar( '\n' ); 
    } 

    return 0; 
} 
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Thank you So much, I was able to print as the rows and columns like I wanted. Thank you – Moodkiller Jun 16 '22 at 14:49
  • I was able to print this by also changing d[j][i] = s[ 3 * j+i]; Because I wanted it to print columns by columns and ordered. orange chair 124 apple cable HI table TV Once again Thank you. – Moodkiller Jun 16 '22 at 14:55
1

Some issues ...

  1. d is unitialized so the pointers within point to random locations.

  2. To fix, we need to use malloc to get space and then do strcpy. An easier way is to just use strdup. Or, just assign the s value directly.

  3. Your j loop should increment j and not i.

  4. Using s[i] will repeat after three elements. To fix, we can do: s[k++]

  5. You are short one initializer for s (i.e. it is length 9 but you have only 8 strings).


Here is the refactored code:

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

int
main(void)
{
    char *d[3][3];                      // Destination array

    char *s[9] = {
        "orange", "apple", "table", "chair", "cable", "TV", "124", "HI",
#if 1
        "raindrops"
#endif
    };  // Source 1 Day array

    int i, j, k = 0;

    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) {
// NOTE/BUG: we must allocate space for d[j][i]
#if 0
            strcpy(d[j][i], s[i]);
#else
            d[j][i] = strdup(s[k++]);
#endif
        }
    }

    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++)
            printf("%s  ", d[j][i]);
        printf("\n");
    }

    return 0;
}

Here is the output:

orange  apple  table
chair  cable  TV
124  HI  raindrops
Craig Estey
  • 30,627
  • 4
  • 24
  • 48
  • @Moodkiller You are SO welcome! You've already accepted the best answer (Vlad's) but with sufficient rep, you can also upvote other good answers. See: https://stackoverflow.com/help/someone-answers – Craig Estey Jun 16 '22 at 15:06
0

There's numerous big problems here.

  • You could have simply solved this with memcpy(arr, arr2, sizeof *arr2);

  • (Probably the least of your problems, but...) This is badly written performance-wise: for(j=0; j<3;i++){ arr[j][i] = arr2[i]; Multiple loops should always have the inner-most loop work with the inner-most array item, in this case it should have been arr[i][j], or you get needlessly bad data cache performance.

  • for(j=0; j<3;i++) How about j++.

  • char *d[3][3]; is an uninitialized 2D array of pointers, each pointing at la-la-land. So you can't copy jack into those addresses - pointers need to point at valid, allocated memory.

  • char d[3][3] is a 2D array of 3x3 characters, so it can't contain the data you wish to store there, let alone the mandatory null terminators required for strings to work.

  • char *s[9] = ... In case you meant the 9th item to be NULL, a so-called sentinel value, you should type out NULL explicitly or otherwise the reader can't tell if a NULL sentinel is intended or if you just sloppily added one by accident.

  • As you can tell from previous comments, the overall slopiness is a recurring major problem here. Take for example:

      for(j=0; j<3; j++) 
          printf("%s  ", &d[j][i]); 
          printf("\n"); 
    

    Because of sloppy indention, we can't tell if the printf("\n"); was intended to sit inside the inner loop or not (it is not, despite the indention). You can't just type some almost correct stuff down in a hurry. You have to carefully type down actually correct code. There's various myths that great programmers are smart, great at math or abstract thinking etc - in reality, great programmers are careful and disciplined, taking some pride in their own craft.

The quick & dirty fix is to use the second example char* d[3][3] and then instead of strcpy use strdup (currently non-standard, soon to become standard):

for(size_t i=0; i<3; i++){
  for(size_t j=0; j<3; j++){
    d[i][j] = strdup(s[i]);
  }
}

(And ideally also call free() for each item in d at the end.)

But the root problem here is that you need to go back and carefully study arrays, pointers and strings, in that order, before using them.

Lundin
  • 195,001
  • 40
  • 254
  • 396