1

I just started C++ and now I'm making a simple program. But don't know how to fix this problem. I'm not a native english speaker so some sentences may not be understandable.

int main()
{
    char test[5][4] = { "abc", "def", "ghi", "jkl", "mno" };
    for (int i = 0; i < 5; ++i)
        std::cout << test[i] << "\t";
    
    return 0;
}

with this simple code, I made a print function

void printTest(char* pArr)
{
    for (int i = 0; i < 5; ++i)
        std::cout << pArr[i] << "\t";
}

Then in my main function, I typed printTest(*test); but the result was 'a b c d' while my expectation was 'abc def ghi jkl mno'


So I fixed printTest function like below (changed const char* test[5][4] = { ... } in main function)

void printTest(const char** pArr)
{
    for (int i = 0; i < 5; ++i)
        std::cout << pArr[i] << "\t";
}

which worked well.

The problem is, I want to use strcpy_s fucntion also. strcpy_s(test[0], "xyx"); like this.

As strcpy_s get char* for the first parameter (not const char*), I think I need to use char* for my array, and print function. While that thing cause a wrong printing issue.

Did i wrote something wrong in my printTest function? Or Is there any way that I can use strcpy_s function with const char* parameter?

PS. I used std::string and made it as I expected. But I want to have a understanding and control of Char array.

JunGi_Lee
  • 13
  • 3
  • 1
    Why not just use `char**` as the parameter for `printTest`? – Alan Birtles Dec 25 '22 at 06:44
  • 1
    `strcpy_s` may not work the way you expect. For example, it doesn't prevent overflow by truncating the input and stopping before overrun, no it calls a handler function that defaults to aborting the program. – user4581301 Dec 25 '22 at 06:44
  • 1
    Second, [`strcpy_s` takes 3 parameters](https://en.cppreference.com/w/c/string/byte/strcpy`), destination, maximum copy length, and source. [Microsoft has an groovy extra overload when called with an array that infers the length for you](https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strcpy-s-wcscpy-s-mbscpy-s?view=msvc-170), but this is useless with pointers as array length cannot be inferred from a pointer. – user4581301 Dec 25 '22 at 06:47
  • Can you post the whole program you've got now which doesn't work? It's not easy to understand what you're running because you've posted a `main()` which never calls `printTest()`. – John Zwinck Dec 25 '22 at 06:50
  • @AlanBirtles You must be kidding! – Michaël Roy Dec 25 '22 at 07:25

2 Answers2

0

I think you are a but confused about he use of const. Don't worry, it's happened to pretty much every one.

What's important to understand is that a non-const variable can be implicitly cast to a const variable at any time, but the reverse is not possible.

For your function PrintTest()

// Here, the const char** declaration is correct, your function only prints pArr, 
// and the caller should not expect the function to modify his precious data.

// Another thing to remember: pArr is valid (and thus constant) only within
// the scope of PrintTest().  It simply does not exist anywhere else. 

void printTest(const char** pArr)
{
    for (int i = 0; i < 5; ++i)
        std::cout << pArr[i] << "\t";
}

// this naturally allows printing of const and non-const data, as one would expects.

const char const_strings[2][4] = { "abc", "def" };

printTest(const_strings); // works!

// Note that if printTest() required a non_const pointer, the line above
// would not compile.  
// const_strings being const, there is no way to modify it using strcpy_s();

//  The code below also works fine, 

char modifiable_strings[2][4] = { "tuv", "xyz" };

printTest(modifiable_strings); // works!

strcpy_s(modifiable_strings[0], "abc");  // is OK, because modifiable is not const.

printTest(modifiable_strings); // works, with different output!
Michaël Roy
  • 6,338
  • 1
  • 15
  • 19
0

I don't think void printTest(const char** pArr) will work with char test[5][4].

The c++ compiler should refuse something like

    void printTest(const char** pArr);
    char test[5][4];
    printTest(test);

Because test is a pointer to char [4], while printTest() expects a pointer to char *.

You may have interesting in this function:

    void printTest2(const char (*pArr)[4] )
    {
        for (int i = 0; i < 5; ++i)
            std::cout << pArr[i] << "\t";
        std::cout <<  "\n";
    }

And the const keyword tells compiler (and what more important, the reader of your code) that "you won't modify the contents of 'pArr'". So compiler will not allow you to strcpy to pArr[i]. And this will compile and run.


void printTest3(char (*pArr)[4] )
{
    for (int i = 0; i < 5; ++i)
    {
        strcpy(pArr[i], "123");
        std::cout << pArr[i] << "\t";
    }
    std::cout <<  "\n";
}
...
printTest3(test);

grizzlybears
  • 492
  • 2
  • 9