C++ a value of type “char” cannot be assigned to an entity of type “char *”












0














I'm getting the error from the title when I try to initialize a two dimensional array.



//strX and strY are strings
int m = strX.length();
int n = strY.length();

//declare two dynamic 2-Dimensional array of variable length B is m X n
char** B;

InitializeTable(&B, m, n);

//function below
InitializeTable(char***B, int m, int n)
{
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; i++)
{
B[i][j] = ' '; //getting the error on the equals sign
}
}


I think is something very simple I'm missing. Thank you!










share|improve this question






















  • char*** would be a 3-dimensional character array. B[i][j] is a char*.
    – Ryan Pierce Williams
    Nov 12 '18 at 22:23










  • char***B....Are you sure of triple pointer?
    – Naidu
    Nov 12 '18 at 22:23






  • 2




    char** B; declares an Unitialized pointer to pointer to char - it points nowhere until you allocate memory for the pointers, and then allocate memory for what the pointers point to.
    – David C. Rankin
    Nov 12 '18 at 22:23












  • C++ is not a script language. The first lines from int m... up to InitializeTable(&B, ...) must be inside a function (like main). Furthermore you declare B as a multidimensional array, but you don't assign memory for it. This will result into a memory access violation.
    – tangoal
    Nov 12 '18 at 22:25


















0














I'm getting the error from the title when I try to initialize a two dimensional array.



//strX and strY are strings
int m = strX.length();
int n = strY.length();

//declare two dynamic 2-Dimensional array of variable length B is m X n
char** B;

InitializeTable(&B, m, n);

//function below
InitializeTable(char***B, int m, int n)
{
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; i++)
{
B[i][j] = ' '; //getting the error on the equals sign
}
}


I think is something very simple I'm missing. Thank you!










share|improve this question






















  • char*** would be a 3-dimensional character array. B[i][j] is a char*.
    – Ryan Pierce Williams
    Nov 12 '18 at 22:23










  • char***B....Are you sure of triple pointer?
    – Naidu
    Nov 12 '18 at 22:23






  • 2




    char** B; declares an Unitialized pointer to pointer to char - it points nowhere until you allocate memory for the pointers, and then allocate memory for what the pointers point to.
    – David C. Rankin
    Nov 12 '18 at 22:23












  • C++ is not a script language. The first lines from int m... up to InitializeTable(&B, ...) must be inside a function (like main). Furthermore you declare B as a multidimensional array, but you don't assign memory for it. This will result into a memory access violation.
    – tangoal
    Nov 12 '18 at 22:25
















0












0








0







I'm getting the error from the title when I try to initialize a two dimensional array.



//strX and strY are strings
int m = strX.length();
int n = strY.length();

//declare two dynamic 2-Dimensional array of variable length B is m X n
char** B;

InitializeTable(&B, m, n);

//function below
InitializeTable(char***B, int m, int n)
{
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; i++)
{
B[i][j] = ' '; //getting the error on the equals sign
}
}


I think is something very simple I'm missing. Thank you!










share|improve this question













I'm getting the error from the title when I try to initialize a two dimensional array.



//strX and strY are strings
int m = strX.length();
int n = strY.length();

//declare two dynamic 2-Dimensional array of variable length B is m X n
char** B;

InitializeTable(&B, m, n);

//function below
InitializeTable(char***B, int m, int n)
{
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; i++)
{
B[i][j] = ' '; //getting the error on the equals sign
}
}


I think is something very simple I'm missing. Thank you!







c++ multidimensional-array char






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 12 '18 at 22:20









ogdev1234ogdev1234

103




103












  • char*** would be a 3-dimensional character array. B[i][j] is a char*.
    – Ryan Pierce Williams
    Nov 12 '18 at 22:23










  • char***B....Are you sure of triple pointer?
    – Naidu
    Nov 12 '18 at 22:23






  • 2




    char** B; declares an Unitialized pointer to pointer to char - it points nowhere until you allocate memory for the pointers, and then allocate memory for what the pointers point to.
    – David C. Rankin
    Nov 12 '18 at 22:23












  • C++ is not a script language. The first lines from int m... up to InitializeTable(&B, ...) must be inside a function (like main). Furthermore you declare B as a multidimensional array, but you don't assign memory for it. This will result into a memory access violation.
    – tangoal
    Nov 12 '18 at 22:25




















  • char*** would be a 3-dimensional character array. B[i][j] is a char*.
    – Ryan Pierce Williams
    Nov 12 '18 at 22:23










  • char***B....Are you sure of triple pointer?
    – Naidu
    Nov 12 '18 at 22:23






  • 2




    char** B; declares an Unitialized pointer to pointer to char - it points nowhere until you allocate memory for the pointers, and then allocate memory for what the pointers point to.
    – David C. Rankin
    Nov 12 '18 at 22:23












  • C++ is not a script language. The first lines from int m... up to InitializeTable(&B, ...) must be inside a function (like main). Furthermore you declare B as a multidimensional array, but you don't assign memory for it. This will result into a memory access violation.
    – tangoal
    Nov 12 '18 at 22:25


















char*** would be a 3-dimensional character array. B[i][j] is a char*.
– Ryan Pierce Williams
Nov 12 '18 at 22:23




char*** would be a 3-dimensional character array. B[i][j] is a char*.
– Ryan Pierce Williams
Nov 12 '18 at 22:23












char***B....Are you sure of triple pointer?
– Naidu
Nov 12 '18 at 22:23




char***B....Are you sure of triple pointer?
– Naidu
Nov 12 '18 at 22:23




2




2




char** B; declares an Unitialized pointer to pointer to char - it points nowhere until you allocate memory for the pointers, and then allocate memory for what the pointers point to.
– David C. Rankin
Nov 12 '18 at 22:23






char** B; declares an Unitialized pointer to pointer to char - it points nowhere until you allocate memory for the pointers, and then allocate memory for what the pointers point to.
– David C. Rankin
Nov 12 '18 at 22:23














C++ is not a script language. The first lines from int m... up to InitializeTable(&B, ...) must be inside a function (like main). Furthermore you declare B as a multidimensional array, but you don't assign memory for it. This will result into a memory access violation.
– tangoal
Nov 12 '18 at 22:25






C++ is not a script language. The first lines from int m... up to InitializeTable(&B, ...) must be inside a function (like main). Furthermore you declare B as a multidimensional array, but you don't assign memory for it. This will result into a memory access violation.
– tangoal
Nov 12 '18 at 22:25














4 Answers
4






active

oldest

votes


















1














Your "Doahh...." moment is:



for (int j = 0; j < n; i++)


Why are you using i++ in a j loop?



Beyond the typo, you would generally want to pass only m and n to InitializeTable, declare B local to InitializeTable, allocate m pointers and then n chars and assign the beginning address for each allocation of chars to the successive pointer and return B and assign the return back in main().[1] This prevents passing the address of B as a parameter and thereby becoming a 3-Star Programmer (not a compliment). That said, there is educational purpose in the exercise.



When you declare char **B; in main(), B is an unitialized pointer to pointer to char. It has its very own address (the pointer B), but it points nowhere (actually the address held by B is indeterminate and likely just whatever was at the address of B at the time it was declared. You cannot use B for any other purpose at this point other than assigning the address of another char ** pointer that has been properly initialized.



When you pass the address of B to InitializeTable, e.g.



    InitializeTable (&B, m, n);


and B receives the address, you must allocate m pointers and assign the beginning address for the pointers as the value held by B (not as the 3-star pointer address). To do this, you must dereference B in InitializeTable. (just as you would declare int *a, b = 5; and then make a point to b with a = &b, to change the value pointed to by b you would dereference and assing, e.g. *b = 10;) Example:



void InitializeTable (char ***B, int m, int n)
{
*B = new char*[m];


By using the new operator, you have allocated storage for m pointers (char*) and assigned the beginning address to the pointer B in main(), *B in InitializeTable.



Now you need to allocate n chars for each pointer and assign the beginning address for each block to each pointer. However, since we are 3-star programmers, and have one additional level of indirection to deal with, instead of assigning to B[i], we must derefence B first -- but, C++ Operator Precedence causes to bind tighter (has higher precedence) than the '*' dereference operator, so you must enclose *B in parenthesis first, e.g. (*B)[i] with:



     for (int i = 0; i < m; i++) {
(*B)[i] = new char[n];


Now you can assign your spaces as the characters to initialize the character values in (*B)[i], e.g.



        for (int j = 0; j < n; j++)
(*B)[i][j] = ' ';


(note: all js in the loop definition)



That's all there is to it. Putting it altogether, you could do:



#include <iostream>
#include <string>

void InitializeTable (char ***B, int m, int n)
{
*B = new char*[m];
for (int i = 0; i < m; i++) {
(*B)[i] = new char[n];
for (int j = 0; j < n; j++)
(*B)[i][j] = ' ';
}
}

int main (void) {

std::string strX = "cats",
strY = "dogs";

//strX and strY are strings
int m = strX.length();
int n = strY.length();

//declare two dynamic 2-Dimensional array of variable length B is m X n
char **B;

InitializeTable (&B, m, n);

for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++)
std::cout << " '" << B[i][j] << "'";
std::cout << 'n';
delete B[i]; /* free each block of characters */
}
delete B; /* free pointers */
}


(don't forget to free both the memory holding the characters, as well as the pointers you allocate)



Example Use/Output



$ ./bin/threestarc++
' ' ' ' ' ' ' '
' ' ' ' ' ' ' '
' ' ' ' ' ' ' '
' ' ' ' ' ' ' '


Memory Use/Error Check



In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.



It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.



For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.



$ ./bin/threestarc++
' ' ' ' ' ' ' '
' ' ' ' ' ' ' '
' ' ' ' ' ' ' '
' ' ' ' ' ' ' '



$ valgrind ./bin/threestarc++
==784== Memcheck, a memory error detector
==784== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==784== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==784== Command: ./bin/threestarc++
==784==
' ' ' ' ' ' ' '
' ' ' ' ' ' ' '
' ' ' ' ' ' ' '
' ' ' ' ' ' ' '
==784==
==784== HEAP SUMMARY:
==784== in use at exit: 0 bytes in 0 blocks
==784== total heap usage: 8 allocs, 8 frees, 72,810 bytes allocated
==784==
==784== All heap blocks were freed -- no leaks are possible
==784==
==784== For counts of detected and suppressed errors, rerun with: -v
==784== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)


Always confirm that you have freed all memory you have allocated and that there are no memory errors.



footnotes:



1. Actually you would want to declare a vector of vector <char> (e.g. std::vector<std::vector<char>> in main() and pass a reference to InitializeTable for initialization letting C++ handle the memory management for you.






share|improve this answer





















  • Thanks for the incredible explanation!
    – ogdev1234
    Nov 13 '18 at 3:21










  • Sure, glad to help. Pointers are not that difficult to make friends with as long as you remember, they are just a variable that holds the address to something else as its value. Each level removed from the value by holding an address (level of indirection) simply takes a dereference (a '*') to remove, char *, one level of indirection, takes one dereference to reference the value, char ** takes two, etc... Each '&' (address of) you take, adds one level, '*' takes one away. Keep operator precedence in mind and you will have no further problems. Good luck with your coding.
    – David C. Rankin
    Nov 13 '18 at 3:38



















1














Think of it like this: Each set of removes a *. Simple case: char *string = "fred"; string[0] removes a so you get the data (f)



You have ***B and B[i][j] so you still have one * to go...



The fact that you have not initialized any memory is also a problem...



You should also give a SSCCE.






share|improve this answer





























    0














    When passing multidimensional arrays, I think it's easier to think of them as references. So in InitializeTable() you can just declare B to be a reference to char**, ie. char**&.



    //strX and strY are strings
    int m = strX.length();
    int n = strY.length();

    //declare two dynamic 2-Dimensional array of variable length B is m X n
    char** B;

    InitializeTable(B, m, n); // Just pass in B, which will be a reference to char**.

    //function below
    InitializeTable(char**&B, int m, int n) // Declare B to be a refernce to char**.
    {
    B = new char * [m]; // Allocate for first dimension, note these are pointers.
    for (int i = 0; i < m; i++)
    {
    B[i] = new char[n]; // Allocate for second dimension, note these are chars.
    for (int j = 0; j < n; j++) // Note: you had i++ here.
    {
    B[i][j] = ' ';
    }
    }
    }





    share|improve this answer





























      0














      Inside of InitializeTable(), you need to dereference B before you can then index into the array. Also, you are not allocating any memory for the array. Try something like this:



      void InitializeTable(char** *B, int m, int n)
      {
      *B = new char*[m];

      for (int i = 0; i < m; i++)
      {
      (*B)[i] = new char[n];

      for (int j = 0; j < n; i++)
      {
      (*B)[i][j] = ' ';
      }
      }
      }

      ...

      int m = strX.length();
      int n = strY.length();

      char** B;
      InitializeTable(&B, m, n);

      ...

      for (int i = 0; i < m; ++i)
      delete B[i];
      delete B;


      Alternatively, pass B by reference instead of by pointer:



      void InitializeTable(char** &B, int m, int n)
      {
      B = new char*[m];

      for (int i = 0; i < m; i++)
      {
      B[i] = new char[n];

      for (int j = 0; j < n; i++)
      {
      B[i][j] = ' ';
      }
      }
      }

      ...

      int m = strX.length();
      int n = strY.length();

      char** B;
      InitializeTable(B, m, n);

      ...

      for (int i = 0; i < m; ++i)
      delete B[i];
      delete B;


      That being said, a better solution would be to not use raw pointers at all, though. You should use std::vector instead:



      void InitializeTable(std::vector<std::vector<char>> &B, int m, int n)
      {
      B.resize(m);

      for (int i = 0; i < m; i++)
      {
      B[i].resize(n);

      for (int j = 0; j < n; i++)
      {
      B[i][j] = ' ';
      }
      }

      // alternatively:
      // B = std::vector<std::vector<char>>(m, std::vector<char>(n, ' '));
      }

      ...

      int m = strX.length();
      int n = strY.length();

      std::vector<std::vector<char>> B;
      InitializeTable(B, m, n);

      ...





      share|improve this answer





















        Your Answer






        StackExchange.ifUsing("editor", function () {
        StackExchange.using("externalEditor", function () {
        StackExchange.using("snippets", function () {
        StackExchange.snippets.init();
        });
        });
        }, "code-snippets");

        StackExchange.ready(function() {
        var channelOptions = {
        tags: "".split(" "),
        id: "1"
        };
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function() {
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled) {
        StackExchange.using("snippets", function() {
        createEditor();
        });
        }
        else {
        createEditor();
        }
        });

        function createEditor() {
        StackExchange.prepareEditor({
        heartbeatType: 'answer',
        autoActivateHeartbeat: false,
        convertImagesToLinks: true,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: 10,
        bindNavPrevention: true,
        postfix: "",
        imageUploader: {
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        },
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        });


        }
        });














        draft saved

        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53270927%2fc-a-value-of-type-char-cannot-be-assigned-to-an-entity-of-type-char%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        4 Answers
        4






        active

        oldest

        votes








        4 Answers
        4






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        1














        Your "Doahh...." moment is:



        for (int j = 0; j < n; i++)


        Why are you using i++ in a j loop?



        Beyond the typo, you would generally want to pass only m and n to InitializeTable, declare B local to InitializeTable, allocate m pointers and then n chars and assign the beginning address for each allocation of chars to the successive pointer and return B and assign the return back in main().[1] This prevents passing the address of B as a parameter and thereby becoming a 3-Star Programmer (not a compliment). That said, there is educational purpose in the exercise.



        When you declare char **B; in main(), B is an unitialized pointer to pointer to char. It has its very own address (the pointer B), but it points nowhere (actually the address held by B is indeterminate and likely just whatever was at the address of B at the time it was declared. You cannot use B for any other purpose at this point other than assigning the address of another char ** pointer that has been properly initialized.



        When you pass the address of B to InitializeTable, e.g.



            InitializeTable (&B, m, n);


        and B receives the address, you must allocate m pointers and assign the beginning address for the pointers as the value held by B (not as the 3-star pointer address). To do this, you must dereference B in InitializeTable. (just as you would declare int *a, b = 5; and then make a point to b with a = &b, to change the value pointed to by b you would dereference and assing, e.g. *b = 10;) Example:



        void InitializeTable (char ***B, int m, int n)
        {
        *B = new char*[m];


        By using the new operator, you have allocated storage for m pointers (char*) and assigned the beginning address to the pointer B in main(), *B in InitializeTable.



        Now you need to allocate n chars for each pointer and assign the beginning address for each block to each pointer. However, since we are 3-star programmers, and have one additional level of indirection to deal with, instead of assigning to B[i], we must derefence B first -- but, C++ Operator Precedence causes to bind tighter (has higher precedence) than the '*' dereference operator, so you must enclose *B in parenthesis first, e.g. (*B)[i] with:



             for (int i = 0; i < m; i++) {
        (*B)[i] = new char[n];


        Now you can assign your spaces as the characters to initialize the character values in (*B)[i], e.g.



                for (int j = 0; j < n; j++)
        (*B)[i][j] = ' ';


        (note: all js in the loop definition)



        That's all there is to it. Putting it altogether, you could do:



        #include <iostream>
        #include <string>

        void InitializeTable (char ***B, int m, int n)
        {
        *B = new char*[m];
        for (int i = 0; i < m; i++) {
        (*B)[i] = new char[n];
        for (int j = 0; j < n; j++)
        (*B)[i][j] = ' ';
        }
        }

        int main (void) {

        std::string strX = "cats",
        strY = "dogs";

        //strX and strY are strings
        int m = strX.length();
        int n = strY.length();

        //declare two dynamic 2-Dimensional array of variable length B is m X n
        char **B;

        InitializeTable (&B, m, n);

        for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++)
        std::cout << " '" << B[i][j] << "'";
        std::cout << 'n';
        delete B[i]; /* free each block of characters */
        }
        delete B; /* free pointers */
        }


        (don't forget to free both the memory holding the characters, as well as the pointers you allocate)



        Example Use/Output



        $ ./bin/threestarc++
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '


        Memory Use/Error Check



        In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.



        It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.



        For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.



        $ ./bin/threestarc++
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '



        $ valgrind ./bin/threestarc++
        ==784== Memcheck, a memory error detector
        ==784== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
        ==784== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
        ==784== Command: ./bin/threestarc++
        ==784==
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ==784==
        ==784== HEAP SUMMARY:
        ==784== in use at exit: 0 bytes in 0 blocks
        ==784== total heap usage: 8 allocs, 8 frees, 72,810 bytes allocated
        ==784==
        ==784== All heap blocks were freed -- no leaks are possible
        ==784==
        ==784== For counts of detected and suppressed errors, rerun with: -v
        ==784== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)


        Always confirm that you have freed all memory you have allocated and that there are no memory errors.



        footnotes:



        1. Actually you would want to declare a vector of vector <char> (e.g. std::vector<std::vector<char>> in main() and pass a reference to InitializeTable for initialization letting C++ handle the memory management for you.






        share|improve this answer





















        • Thanks for the incredible explanation!
          – ogdev1234
          Nov 13 '18 at 3:21










        • Sure, glad to help. Pointers are not that difficult to make friends with as long as you remember, they are just a variable that holds the address to something else as its value. Each level removed from the value by holding an address (level of indirection) simply takes a dereference (a '*') to remove, char *, one level of indirection, takes one dereference to reference the value, char ** takes two, etc... Each '&' (address of) you take, adds one level, '*' takes one away. Keep operator precedence in mind and you will have no further problems. Good luck with your coding.
          – David C. Rankin
          Nov 13 '18 at 3:38
















        1














        Your "Doahh...." moment is:



        for (int j = 0; j < n; i++)


        Why are you using i++ in a j loop?



        Beyond the typo, you would generally want to pass only m and n to InitializeTable, declare B local to InitializeTable, allocate m pointers and then n chars and assign the beginning address for each allocation of chars to the successive pointer and return B and assign the return back in main().[1] This prevents passing the address of B as a parameter and thereby becoming a 3-Star Programmer (not a compliment). That said, there is educational purpose in the exercise.



        When you declare char **B; in main(), B is an unitialized pointer to pointer to char. It has its very own address (the pointer B), but it points nowhere (actually the address held by B is indeterminate and likely just whatever was at the address of B at the time it was declared. You cannot use B for any other purpose at this point other than assigning the address of another char ** pointer that has been properly initialized.



        When you pass the address of B to InitializeTable, e.g.



            InitializeTable (&B, m, n);


        and B receives the address, you must allocate m pointers and assign the beginning address for the pointers as the value held by B (not as the 3-star pointer address). To do this, you must dereference B in InitializeTable. (just as you would declare int *a, b = 5; and then make a point to b with a = &b, to change the value pointed to by b you would dereference and assing, e.g. *b = 10;) Example:



        void InitializeTable (char ***B, int m, int n)
        {
        *B = new char*[m];


        By using the new operator, you have allocated storage for m pointers (char*) and assigned the beginning address to the pointer B in main(), *B in InitializeTable.



        Now you need to allocate n chars for each pointer and assign the beginning address for each block to each pointer. However, since we are 3-star programmers, and have one additional level of indirection to deal with, instead of assigning to B[i], we must derefence B first -- but, C++ Operator Precedence causes to bind tighter (has higher precedence) than the '*' dereference operator, so you must enclose *B in parenthesis first, e.g. (*B)[i] with:



             for (int i = 0; i < m; i++) {
        (*B)[i] = new char[n];


        Now you can assign your spaces as the characters to initialize the character values in (*B)[i], e.g.



                for (int j = 0; j < n; j++)
        (*B)[i][j] = ' ';


        (note: all js in the loop definition)



        That's all there is to it. Putting it altogether, you could do:



        #include <iostream>
        #include <string>

        void InitializeTable (char ***B, int m, int n)
        {
        *B = new char*[m];
        for (int i = 0; i < m; i++) {
        (*B)[i] = new char[n];
        for (int j = 0; j < n; j++)
        (*B)[i][j] = ' ';
        }
        }

        int main (void) {

        std::string strX = "cats",
        strY = "dogs";

        //strX and strY are strings
        int m = strX.length();
        int n = strY.length();

        //declare two dynamic 2-Dimensional array of variable length B is m X n
        char **B;

        InitializeTable (&B, m, n);

        for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++)
        std::cout << " '" << B[i][j] << "'";
        std::cout << 'n';
        delete B[i]; /* free each block of characters */
        }
        delete B; /* free pointers */
        }


        (don't forget to free both the memory holding the characters, as well as the pointers you allocate)



        Example Use/Output



        $ ./bin/threestarc++
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '


        Memory Use/Error Check



        In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.



        It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.



        For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.



        $ ./bin/threestarc++
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '



        $ valgrind ./bin/threestarc++
        ==784== Memcheck, a memory error detector
        ==784== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
        ==784== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
        ==784== Command: ./bin/threestarc++
        ==784==
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ==784==
        ==784== HEAP SUMMARY:
        ==784== in use at exit: 0 bytes in 0 blocks
        ==784== total heap usage: 8 allocs, 8 frees, 72,810 bytes allocated
        ==784==
        ==784== All heap blocks were freed -- no leaks are possible
        ==784==
        ==784== For counts of detected and suppressed errors, rerun with: -v
        ==784== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)


        Always confirm that you have freed all memory you have allocated and that there are no memory errors.



        footnotes:



        1. Actually you would want to declare a vector of vector <char> (e.g. std::vector<std::vector<char>> in main() and pass a reference to InitializeTable for initialization letting C++ handle the memory management for you.






        share|improve this answer





















        • Thanks for the incredible explanation!
          – ogdev1234
          Nov 13 '18 at 3:21










        • Sure, glad to help. Pointers are not that difficult to make friends with as long as you remember, they are just a variable that holds the address to something else as its value. Each level removed from the value by holding an address (level of indirection) simply takes a dereference (a '*') to remove, char *, one level of indirection, takes one dereference to reference the value, char ** takes two, etc... Each '&' (address of) you take, adds one level, '*' takes one away. Keep operator precedence in mind and you will have no further problems. Good luck with your coding.
          – David C. Rankin
          Nov 13 '18 at 3:38














        1












        1








        1






        Your "Doahh...." moment is:



        for (int j = 0; j < n; i++)


        Why are you using i++ in a j loop?



        Beyond the typo, you would generally want to pass only m and n to InitializeTable, declare B local to InitializeTable, allocate m pointers and then n chars and assign the beginning address for each allocation of chars to the successive pointer and return B and assign the return back in main().[1] This prevents passing the address of B as a parameter and thereby becoming a 3-Star Programmer (not a compliment). That said, there is educational purpose in the exercise.



        When you declare char **B; in main(), B is an unitialized pointer to pointer to char. It has its very own address (the pointer B), but it points nowhere (actually the address held by B is indeterminate and likely just whatever was at the address of B at the time it was declared. You cannot use B for any other purpose at this point other than assigning the address of another char ** pointer that has been properly initialized.



        When you pass the address of B to InitializeTable, e.g.



            InitializeTable (&B, m, n);


        and B receives the address, you must allocate m pointers and assign the beginning address for the pointers as the value held by B (not as the 3-star pointer address). To do this, you must dereference B in InitializeTable. (just as you would declare int *a, b = 5; and then make a point to b with a = &b, to change the value pointed to by b you would dereference and assing, e.g. *b = 10;) Example:



        void InitializeTable (char ***B, int m, int n)
        {
        *B = new char*[m];


        By using the new operator, you have allocated storage for m pointers (char*) and assigned the beginning address to the pointer B in main(), *B in InitializeTable.



        Now you need to allocate n chars for each pointer and assign the beginning address for each block to each pointer. However, since we are 3-star programmers, and have one additional level of indirection to deal with, instead of assigning to B[i], we must derefence B first -- but, C++ Operator Precedence causes to bind tighter (has higher precedence) than the '*' dereference operator, so you must enclose *B in parenthesis first, e.g. (*B)[i] with:



             for (int i = 0; i < m; i++) {
        (*B)[i] = new char[n];


        Now you can assign your spaces as the characters to initialize the character values in (*B)[i], e.g.



                for (int j = 0; j < n; j++)
        (*B)[i][j] = ' ';


        (note: all js in the loop definition)



        That's all there is to it. Putting it altogether, you could do:



        #include <iostream>
        #include <string>

        void InitializeTable (char ***B, int m, int n)
        {
        *B = new char*[m];
        for (int i = 0; i < m; i++) {
        (*B)[i] = new char[n];
        for (int j = 0; j < n; j++)
        (*B)[i][j] = ' ';
        }
        }

        int main (void) {

        std::string strX = "cats",
        strY = "dogs";

        //strX and strY are strings
        int m = strX.length();
        int n = strY.length();

        //declare two dynamic 2-Dimensional array of variable length B is m X n
        char **B;

        InitializeTable (&B, m, n);

        for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++)
        std::cout << " '" << B[i][j] << "'";
        std::cout << 'n';
        delete B[i]; /* free each block of characters */
        }
        delete B; /* free pointers */
        }


        (don't forget to free both the memory holding the characters, as well as the pointers you allocate)



        Example Use/Output



        $ ./bin/threestarc++
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '


        Memory Use/Error Check



        In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.



        It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.



        For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.



        $ ./bin/threestarc++
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '



        $ valgrind ./bin/threestarc++
        ==784== Memcheck, a memory error detector
        ==784== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
        ==784== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
        ==784== Command: ./bin/threestarc++
        ==784==
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ==784==
        ==784== HEAP SUMMARY:
        ==784== in use at exit: 0 bytes in 0 blocks
        ==784== total heap usage: 8 allocs, 8 frees, 72,810 bytes allocated
        ==784==
        ==784== All heap blocks were freed -- no leaks are possible
        ==784==
        ==784== For counts of detected and suppressed errors, rerun with: -v
        ==784== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)


        Always confirm that you have freed all memory you have allocated and that there are no memory errors.



        footnotes:



        1. Actually you would want to declare a vector of vector <char> (e.g. std::vector<std::vector<char>> in main() and pass a reference to InitializeTable for initialization letting C++ handle the memory management for you.






        share|improve this answer












        Your "Doahh...." moment is:



        for (int j = 0; j < n; i++)


        Why are you using i++ in a j loop?



        Beyond the typo, you would generally want to pass only m and n to InitializeTable, declare B local to InitializeTable, allocate m pointers and then n chars and assign the beginning address for each allocation of chars to the successive pointer and return B and assign the return back in main().[1] This prevents passing the address of B as a parameter and thereby becoming a 3-Star Programmer (not a compliment). That said, there is educational purpose in the exercise.



        When you declare char **B; in main(), B is an unitialized pointer to pointer to char. It has its very own address (the pointer B), but it points nowhere (actually the address held by B is indeterminate and likely just whatever was at the address of B at the time it was declared. You cannot use B for any other purpose at this point other than assigning the address of another char ** pointer that has been properly initialized.



        When you pass the address of B to InitializeTable, e.g.



            InitializeTable (&B, m, n);


        and B receives the address, you must allocate m pointers and assign the beginning address for the pointers as the value held by B (not as the 3-star pointer address). To do this, you must dereference B in InitializeTable. (just as you would declare int *a, b = 5; and then make a point to b with a = &b, to change the value pointed to by b you would dereference and assing, e.g. *b = 10;) Example:



        void InitializeTable (char ***B, int m, int n)
        {
        *B = new char*[m];


        By using the new operator, you have allocated storage for m pointers (char*) and assigned the beginning address to the pointer B in main(), *B in InitializeTable.



        Now you need to allocate n chars for each pointer and assign the beginning address for each block to each pointer. However, since we are 3-star programmers, and have one additional level of indirection to deal with, instead of assigning to B[i], we must derefence B first -- but, C++ Operator Precedence causes to bind tighter (has higher precedence) than the '*' dereference operator, so you must enclose *B in parenthesis first, e.g. (*B)[i] with:



             for (int i = 0; i < m; i++) {
        (*B)[i] = new char[n];


        Now you can assign your spaces as the characters to initialize the character values in (*B)[i], e.g.



                for (int j = 0; j < n; j++)
        (*B)[i][j] = ' ';


        (note: all js in the loop definition)



        That's all there is to it. Putting it altogether, you could do:



        #include <iostream>
        #include <string>

        void InitializeTable (char ***B, int m, int n)
        {
        *B = new char*[m];
        for (int i = 0; i < m; i++) {
        (*B)[i] = new char[n];
        for (int j = 0; j < n; j++)
        (*B)[i][j] = ' ';
        }
        }

        int main (void) {

        std::string strX = "cats",
        strY = "dogs";

        //strX and strY are strings
        int m = strX.length();
        int n = strY.length();

        //declare two dynamic 2-Dimensional array of variable length B is m X n
        char **B;

        InitializeTable (&B, m, n);

        for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++)
        std::cout << " '" << B[i][j] << "'";
        std::cout << 'n';
        delete B[i]; /* free each block of characters */
        }
        delete B; /* free pointers */
        }


        (don't forget to free both the memory holding the characters, as well as the pointers you allocate)



        Example Use/Output



        $ ./bin/threestarc++
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '


        Memory Use/Error Check



        In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.



        It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.



        For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.



        $ ./bin/threestarc++
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '



        $ valgrind ./bin/threestarc++
        ==784== Memcheck, a memory error detector
        ==784== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
        ==784== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
        ==784== Command: ./bin/threestarc++
        ==784==
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ' ' ' ' ' ' ' '
        ==784==
        ==784== HEAP SUMMARY:
        ==784== in use at exit: 0 bytes in 0 blocks
        ==784== total heap usage: 8 allocs, 8 frees, 72,810 bytes allocated
        ==784==
        ==784== All heap blocks were freed -- no leaks are possible
        ==784==
        ==784== For counts of detected and suppressed errors, rerun with: -v
        ==784== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)


        Always confirm that you have freed all memory you have allocated and that there are no memory errors.



        footnotes:



        1. Actually you would want to declare a vector of vector <char> (e.g. std::vector<std::vector<char>> in main() and pass a reference to InitializeTable for initialization letting C++ handle the memory management for you.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 12 '18 at 23:18









        David C. RankinDavid C. Rankin

        40.6k32648




        40.6k32648












        • Thanks for the incredible explanation!
          – ogdev1234
          Nov 13 '18 at 3:21










        • Sure, glad to help. Pointers are not that difficult to make friends with as long as you remember, they are just a variable that holds the address to something else as its value. Each level removed from the value by holding an address (level of indirection) simply takes a dereference (a '*') to remove, char *, one level of indirection, takes one dereference to reference the value, char ** takes two, etc... Each '&' (address of) you take, adds one level, '*' takes one away. Keep operator precedence in mind and you will have no further problems. Good luck with your coding.
          – David C. Rankin
          Nov 13 '18 at 3:38


















        • Thanks for the incredible explanation!
          – ogdev1234
          Nov 13 '18 at 3:21










        • Sure, glad to help. Pointers are not that difficult to make friends with as long as you remember, they are just a variable that holds the address to something else as its value. Each level removed from the value by holding an address (level of indirection) simply takes a dereference (a '*') to remove, char *, one level of indirection, takes one dereference to reference the value, char ** takes two, etc... Each '&' (address of) you take, adds one level, '*' takes one away. Keep operator precedence in mind and you will have no further problems. Good luck with your coding.
          – David C. Rankin
          Nov 13 '18 at 3:38
















        Thanks for the incredible explanation!
        – ogdev1234
        Nov 13 '18 at 3:21




        Thanks for the incredible explanation!
        – ogdev1234
        Nov 13 '18 at 3:21












        Sure, glad to help. Pointers are not that difficult to make friends with as long as you remember, they are just a variable that holds the address to something else as its value. Each level removed from the value by holding an address (level of indirection) simply takes a dereference (a '*') to remove, char *, one level of indirection, takes one dereference to reference the value, char ** takes two, etc... Each '&' (address of) you take, adds one level, '*' takes one away. Keep operator precedence in mind and you will have no further problems. Good luck with your coding.
        – David C. Rankin
        Nov 13 '18 at 3:38




        Sure, glad to help. Pointers are not that difficult to make friends with as long as you remember, they are just a variable that holds the address to something else as its value. Each level removed from the value by holding an address (level of indirection) simply takes a dereference (a '*') to remove, char *, one level of indirection, takes one dereference to reference the value, char ** takes two, etc... Each '&' (address of) you take, adds one level, '*' takes one away. Keep operator precedence in mind and you will have no further problems. Good luck with your coding.
        – David C. Rankin
        Nov 13 '18 at 3:38













        1














        Think of it like this: Each set of removes a *. Simple case: char *string = "fred"; string[0] removes a so you get the data (f)



        You have ***B and B[i][j] so you still have one * to go...



        The fact that you have not initialized any memory is also a problem...



        You should also give a SSCCE.






        share|improve this answer


























          1














          Think of it like this: Each set of removes a *. Simple case: char *string = "fred"; string[0] removes a so you get the data (f)



          You have ***B and B[i][j] so you still have one * to go...



          The fact that you have not initialized any memory is also a problem...



          You should also give a SSCCE.






          share|improve this answer
























            1












            1








            1






            Think of it like this: Each set of removes a *. Simple case: char *string = "fred"; string[0] removes a so you get the data (f)



            You have ***B and B[i][j] so you still have one * to go...



            The fact that you have not initialized any memory is also a problem...



            You should also give a SSCCE.






            share|improve this answer












            Think of it like this: Each set of removes a *. Simple case: char *string = "fred"; string[0] removes a so you get the data (f)



            You have ***B and B[i][j] so you still have one * to go...



            The fact that you have not initialized any memory is also a problem...



            You should also give a SSCCE.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 12 '18 at 22:24









            John3136John3136

            23.9k33259




            23.9k33259























                0














                When passing multidimensional arrays, I think it's easier to think of them as references. So in InitializeTable() you can just declare B to be a reference to char**, ie. char**&.



                //strX and strY are strings
                int m = strX.length();
                int n = strY.length();

                //declare two dynamic 2-Dimensional array of variable length B is m X n
                char** B;

                InitializeTable(B, m, n); // Just pass in B, which will be a reference to char**.

                //function below
                InitializeTable(char**&B, int m, int n) // Declare B to be a refernce to char**.
                {
                B = new char * [m]; // Allocate for first dimension, note these are pointers.
                for (int i = 0; i < m; i++)
                {
                B[i] = new char[n]; // Allocate for second dimension, note these are chars.
                for (int j = 0; j < n; j++) // Note: you had i++ here.
                {
                B[i][j] = ' ';
                }
                }
                }





                share|improve this answer


























                  0














                  When passing multidimensional arrays, I think it's easier to think of them as references. So in InitializeTable() you can just declare B to be a reference to char**, ie. char**&.



                  //strX and strY are strings
                  int m = strX.length();
                  int n = strY.length();

                  //declare two dynamic 2-Dimensional array of variable length B is m X n
                  char** B;

                  InitializeTable(B, m, n); // Just pass in B, which will be a reference to char**.

                  //function below
                  InitializeTable(char**&B, int m, int n) // Declare B to be a refernce to char**.
                  {
                  B = new char * [m]; // Allocate for first dimension, note these are pointers.
                  for (int i = 0; i < m; i++)
                  {
                  B[i] = new char[n]; // Allocate for second dimension, note these are chars.
                  for (int j = 0; j < n; j++) // Note: you had i++ here.
                  {
                  B[i][j] = ' ';
                  }
                  }
                  }





                  share|improve this answer
























                    0












                    0








                    0






                    When passing multidimensional arrays, I think it's easier to think of them as references. So in InitializeTable() you can just declare B to be a reference to char**, ie. char**&.



                    //strX and strY are strings
                    int m = strX.length();
                    int n = strY.length();

                    //declare two dynamic 2-Dimensional array of variable length B is m X n
                    char** B;

                    InitializeTable(B, m, n); // Just pass in B, which will be a reference to char**.

                    //function below
                    InitializeTable(char**&B, int m, int n) // Declare B to be a refernce to char**.
                    {
                    B = new char * [m]; // Allocate for first dimension, note these are pointers.
                    for (int i = 0; i < m; i++)
                    {
                    B[i] = new char[n]; // Allocate for second dimension, note these are chars.
                    for (int j = 0; j < n; j++) // Note: you had i++ here.
                    {
                    B[i][j] = ' ';
                    }
                    }
                    }





                    share|improve this answer












                    When passing multidimensional arrays, I think it's easier to think of them as references. So in InitializeTable() you can just declare B to be a reference to char**, ie. char**&.



                    //strX and strY are strings
                    int m = strX.length();
                    int n = strY.length();

                    //declare two dynamic 2-Dimensional array of variable length B is m X n
                    char** B;

                    InitializeTable(B, m, n); // Just pass in B, which will be a reference to char**.

                    //function below
                    InitializeTable(char**&B, int m, int n) // Declare B to be a refernce to char**.
                    {
                    B = new char * [m]; // Allocate for first dimension, note these are pointers.
                    for (int i = 0; i < m; i++)
                    {
                    B[i] = new char[n]; // Allocate for second dimension, note these are chars.
                    for (int j = 0; j < n; j++) // Note: you had i++ here.
                    {
                    B[i][j] = ' ';
                    }
                    }
                    }






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Nov 12 '18 at 22:54









                    fluflu

                    35629




                    35629























                        0














                        Inside of InitializeTable(), you need to dereference B before you can then index into the array. Also, you are not allocating any memory for the array. Try something like this:



                        void InitializeTable(char** *B, int m, int n)
                        {
                        *B = new char*[m];

                        for (int i = 0; i < m; i++)
                        {
                        (*B)[i] = new char[n];

                        for (int j = 0; j < n; i++)
                        {
                        (*B)[i][j] = ' ';
                        }
                        }
                        }

                        ...

                        int m = strX.length();
                        int n = strY.length();

                        char** B;
                        InitializeTable(&B, m, n);

                        ...

                        for (int i = 0; i < m; ++i)
                        delete B[i];
                        delete B;


                        Alternatively, pass B by reference instead of by pointer:



                        void InitializeTable(char** &B, int m, int n)
                        {
                        B = new char*[m];

                        for (int i = 0; i < m; i++)
                        {
                        B[i] = new char[n];

                        for (int j = 0; j < n; i++)
                        {
                        B[i][j] = ' ';
                        }
                        }
                        }

                        ...

                        int m = strX.length();
                        int n = strY.length();

                        char** B;
                        InitializeTable(B, m, n);

                        ...

                        for (int i = 0; i < m; ++i)
                        delete B[i];
                        delete B;


                        That being said, a better solution would be to not use raw pointers at all, though. You should use std::vector instead:



                        void InitializeTable(std::vector<std::vector<char>> &B, int m, int n)
                        {
                        B.resize(m);

                        for (int i = 0; i < m; i++)
                        {
                        B[i].resize(n);

                        for (int j = 0; j < n; i++)
                        {
                        B[i][j] = ' ';
                        }
                        }

                        // alternatively:
                        // B = std::vector<std::vector<char>>(m, std::vector<char>(n, ' '));
                        }

                        ...

                        int m = strX.length();
                        int n = strY.length();

                        std::vector<std::vector<char>> B;
                        InitializeTable(B, m, n);

                        ...





                        share|improve this answer


























                          0














                          Inside of InitializeTable(), you need to dereference B before you can then index into the array. Also, you are not allocating any memory for the array. Try something like this:



                          void InitializeTable(char** *B, int m, int n)
                          {
                          *B = new char*[m];

                          for (int i = 0; i < m; i++)
                          {
                          (*B)[i] = new char[n];

                          for (int j = 0; j < n; i++)
                          {
                          (*B)[i][j] = ' ';
                          }
                          }
                          }

                          ...

                          int m = strX.length();
                          int n = strY.length();

                          char** B;
                          InitializeTable(&B, m, n);

                          ...

                          for (int i = 0; i < m; ++i)
                          delete B[i];
                          delete B;


                          Alternatively, pass B by reference instead of by pointer:



                          void InitializeTable(char** &B, int m, int n)
                          {
                          B = new char*[m];

                          for (int i = 0; i < m; i++)
                          {
                          B[i] = new char[n];

                          for (int j = 0; j < n; i++)
                          {
                          B[i][j] = ' ';
                          }
                          }
                          }

                          ...

                          int m = strX.length();
                          int n = strY.length();

                          char** B;
                          InitializeTable(B, m, n);

                          ...

                          for (int i = 0; i < m; ++i)
                          delete B[i];
                          delete B;


                          That being said, a better solution would be to not use raw pointers at all, though. You should use std::vector instead:



                          void InitializeTable(std::vector<std::vector<char>> &B, int m, int n)
                          {
                          B.resize(m);

                          for (int i = 0; i < m; i++)
                          {
                          B[i].resize(n);

                          for (int j = 0; j < n; i++)
                          {
                          B[i][j] = ' ';
                          }
                          }

                          // alternatively:
                          // B = std::vector<std::vector<char>>(m, std::vector<char>(n, ' '));
                          }

                          ...

                          int m = strX.length();
                          int n = strY.length();

                          std::vector<std::vector<char>> B;
                          InitializeTable(B, m, n);

                          ...





                          share|improve this answer
























                            0












                            0








                            0






                            Inside of InitializeTable(), you need to dereference B before you can then index into the array. Also, you are not allocating any memory for the array. Try something like this:



                            void InitializeTable(char** *B, int m, int n)
                            {
                            *B = new char*[m];

                            for (int i = 0; i < m; i++)
                            {
                            (*B)[i] = new char[n];

                            for (int j = 0; j < n; i++)
                            {
                            (*B)[i][j] = ' ';
                            }
                            }
                            }

                            ...

                            int m = strX.length();
                            int n = strY.length();

                            char** B;
                            InitializeTable(&B, m, n);

                            ...

                            for (int i = 0; i < m; ++i)
                            delete B[i];
                            delete B;


                            Alternatively, pass B by reference instead of by pointer:



                            void InitializeTable(char** &B, int m, int n)
                            {
                            B = new char*[m];

                            for (int i = 0; i < m; i++)
                            {
                            B[i] = new char[n];

                            for (int j = 0; j < n; i++)
                            {
                            B[i][j] = ' ';
                            }
                            }
                            }

                            ...

                            int m = strX.length();
                            int n = strY.length();

                            char** B;
                            InitializeTable(B, m, n);

                            ...

                            for (int i = 0; i < m; ++i)
                            delete B[i];
                            delete B;


                            That being said, a better solution would be to not use raw pointers at all, though. You should use std::vector instead:



                            void InitializeTable(std::vector<std::vector<char>> &B, int m, int n)
                            {
                            B.resize(m);

                            for (int i = 0; i < m; i++)
                            {
                            B[i].resize(n);

                            for (int j = 0; j < n; i++)
                            {
                            B[i][j] = ' ';
                            }
                            }

                            // alternatively:
                            // B = std::vector<std::vector<char>>(m, std::vector<char>(n, ' '));
                            }

                            ...

                            int m = strX.length();
                            int n = strY.length();

                            std::vector<std::vector<char>> B;
                            InitializeTable(B, m, n);

                            ...





                            share|improve this answer












                            Inside of InitializeTable(), you need to dereference B before you can then index into the array. Also, you are not allocating any memory for the array. Try something like this:



                            void InitializeTable(char** *B, int m, int n)
                            {
                            *B = new char*[m];

                            for (int i = 0; i < m; i++)
                            {
                            (*B)[i] = new char[n];

                            for (int j = 0; j < n; i++)
                            {
                            (*B)[i][j] = ' ';
                            }
                            }
                            }

                            ...

                            int m = strX.length();
                            int n = strY.length();

                            char** B;
                            InitializeTable(&B, m, n);

                            ...

                            for (int i = 0; i < m; ++i)
                            delete B[i];
                            delete B;


                            Alternatively, pass B by reference instead of by pointer:



                            void InitializeTable(char** &B, int m, int n)
                            {
                            B = new char*[m];

                            for (int i = 0; i < m; i++)
                            {
                            B[i] = new char[n];

                            for (int j = 0; j < n; i++)
                            {
                            B[i][j] = ' ';
                            }
                            }
                            }

                            ...

                            int m = strX.length();
                            int n = strY.length();

                            char** B;
                            InitializeTable(B, m, n);

                            ...

                            for (int i = 0; i < m; ++i)
                            delete B[i];
                            delete B;


                            That being said, a better solution would be to not use raw pointers at all, though. You should use std::vector instead:



                            void InitializeTable(std::vector<std::vector<char>> &B, int m, int n)
                            {
                            B.resize(m);

                            for (int i = 0; i < m; i++)
                            {
                            B[i].resize(n);

                            for (int j = 0; j < n; i++)
                            {
                            B[i][j] = ' ';
                            }
                            }

                            // alternatively:
                            // B = std::vector<std::vector<char>>(m, std::vector<char>(n, ' '));
                            }

                            ...

                            int m = strX.length();
                            int n = strY.length();

                            std::vector<std::vector<char>> B;
                            InitializeTable(B, m, n);

                            ...






                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Nov 12 '18 at 23:20









                            Remy LebeauRemy Lebeau

                            332k18251443




                            332k18251443






























                                draft saved

                                draft discarded




















































                                Thanks for contributing an answer to Stack Overflow!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53270927%2fc-a-value-of-type-char-cannot-be-assigned-to-an-entity-of-type-char%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                Popular posts from this blog

                                The Sandy Post

                                Danny Elfman

                                Pages that link to "Head v. Amoskeag Manufacturing Co."