Hi All,

I am trying to create a 2D array of the "CString" MFC class, however it needs to be declared dynamically for my application. I have read up on numerous forums but I just cant seem to find what I am looking for.

From what I have read the best way to do this would be to use a vector of CStrings. However, I am not to sure how to declare this dynamically (I am able to do it by specifying the row and column size, however these values are not known at compilation time and therefore i cannot do it this way).

What I would like to be able to do is address any "CString" of a 2D array in the following way:

MyArray[0][0]="Message ID in CString format"
MyArray[0][1]="Message in CString format"
MyArray[0][2]="Time in CString format"

MyArray[1][0]="Message ID in CString format"
MyArray[1][1]="Message in CString format"
MyArray[1][2]="Time in CString format"

and so on...

As you can see the parts which are variable an therefore dynamic are the "Row" and "CString" values. The "column" value can be set to 3 at compilation time.

Please could someone give me an example of how to do this without having to specify the row and column size.

The following code which i found on another forum is exactly what i would want, using a vector of "CStrings" however although the poster claims it is dynamic the "Width" and "Height" still need to be declared and set at compilation time:

#include <vector>
std::vector<std::vector<CString> > your2darray(width,
std::vector<CString>(height));
your2darray[x][y] = "asdf";

Vectors are indeed the way to go. But not with fixed sizes as recommended to you by 'other people'. Here's an example of what I mean:

#include <vector>
#include <iostream>

int main(){
    std::vector<std::vector<CString> > your2darray;

    std::vector<CString> row;
    row.push_back("col 1.1");
    row.push_back("col 1.2");
    row.push_back("col 1.3");
    
    your2darray.push_back(row); // push 1 row in the matrix
    row.clear();

    row.push_back("col 2.1");
    row.push_back("col 2.2");

    your2darray.push_back(row); // push 1 row in the matrix
    row.clear();
    
    row.push_back("col 3.1");
    row.push_back("col 3.2");
    row.push_back("col 3.3");
    row.push_back("col 3.4");
    
    your2darray.push_back(row); // push 1 row in the matrix

    for (unsigned y = 0; y < your2darray.size(); ++y){
        for (unsigned x = 0; x < your2darray.at(y).size(); ++x) {
            std::cout << your2darray.at(y).at(x) << " | ";
        }
        std::cout << '\n';
    }
    return 0;
}

I did not test this, but it should work fine.

Hi Niek,

Thanks for the example...Now I am getting somewhere!

Unfortunately I must ask one last stupid question.

The following line of code:

std::cout << your2darray.at(y).at(x) << " | ";

outputs the adress of the column as follows:

004219FC | 0042195C | 004218DC |
0042181C | 004217DC |
0042191C | 0042185C | 004216CC | 0042168C |

What would the correct syntax be in order to output the actual string?
I have tried numerous combinations...

Thanks again for your assistance.

Hmm, That's very odd!
After looking into this, Niek e's example compiles ok for me and outputs the strings properly.
I'm not sure why you're seeing the addresses of the columns instead of the actual strings..

What happens if you explicitly cast the result of the 'your2darray.at().at()' function call to a CString?
e.g.

std::cout << (CString)(your2darray.at(y).at(x)) << " | ";

That's about the only thing I can think of right about now.
If that doesn't work, I'm at a loss I'm afraid!
Cheers for now,
Jas.

>Hmm, That's very odd!
Not especially, though it can be surprising. This is the underlying problem:

#include <iostream>

#define UNICODE
#include <windows.h>

int main()
{
  TCHAR *s = L"test";

  std::cout<< s <<'\n';
}

My crystal ball says the UNICODE macro is defined, which causes CString to resolve to an actual type of CStringW. The implicit conversion ends up actually being CStringW to wchar_t*, which cout (the narrow stream object) isn't built to handle. Two simple options are to undefine UNICODE (if you don't need Unicode in the project), or use wcout instead of cout.

commented: Thanks Narue, I hadn't come accross that before! +1

My crystal ball says the UNICODE macro is defined, which causes CString to resolve to an actual type of CStringW. The implicit conversion ends up actually being CStringW to wchar_t*, which cout (the narrow stream object) isn't built to handle. Two simple options are to undefine UNICODE (if you don't need Unicode in the project), or use wcout instead of cout.

Aha, thanks Narue, that was beginning to bug me!
I've not done anything much with unicode, so I've never come across that particular problem before. But I guess that would make sense!

I shall endevour to remember that for future reference.

Thanks again,
Jas.

I have tried everything you have suggested however i still have the same problem....

I am using Visual Studio 6.0....
I have created a new Win 32 Application with MFC support and i still have the same issue....

However the following line of code works:

std::cout << "\nC++ is Fun!!!\n";

but when i include the code in a few posts up i get the adresses of the strings.

Any suggestions anyone?

>I have tried everything you have suggested
Did you try this?

std::wcout<< cs.GetBuffer() << '\n'; // cs is the CString object

>However the following line of code works:
Well, DUH! That line uses a narrow string literal with a narrow stream object. You didn't exactly (or at all) reproduce the problem in that case, and I would be utterly shocked if it failed to work as expected.

Hi Narue,

Thank you very much for the help and for your patients! The last line of code you gave me did the trick. Without CString::GetBuffer() it does not work.

With UNICODE defined or undefined, if I use cout and GetBuffer() i get the correct output. wcout gives me the same problem with UNICODE defined.

Could you maybe explain why GetBuffer() changes all this? Just for my understanding, my code is now doing what I want it to! So, GetBuffer() is returning a pointer to the internal character buffer for the CString object? So passing by pointer and not by value is what is doing the trick here?

>Could you maybe explain why GetBuffer() changes all this?
Without digging into the code for CString, I'd say that whatever implicit conversions are in place don't quite cut it for converting into the wchar_t* that wcout expects (or the char* that cout expects). It's probably some internal object without the right conversion instead of the character buffer itself.

>So, GetBuffer() is returning a pointer to the internal character buffer for the CString object?
Yes.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.