0

how would i convert this to return char* an not use std::string just want to learn other ways to do this without std::string

string getName(DWORD Address)
{
    DWORD BaseDword = ReadBaseDword(Address);

    int size = ReadCharSize();

    string name = "";

    for (int i = 0; i < size - 1; i++)
    {
        char c = ReadCharArrayChar(i);
        name += c;
    }

    return name;
}
Nathan
  • 209
  • 1
  • 9
  • By looking at the documentation for `std:string`. Hint: .`c_str()` - you'll likely want the use of `strdup`, too – enhzflep Jun 02 '14 at 20:03
  • why you want to do that? If you're up to return a `char*` you have to allocate and later deallocate memory. Plus you have to keep in mind that C strings end up with `\0` null character. There's no reason to do this really. – 101010 Jun 02 '14 at 20:03
  • what's with `ReadCharArrayChar[i]();`? – Iosif Murariu Jun 02 '14 at 20:03
  • i didnt wanted to see other ways without std::string. I just through this together its like something im doing so ReadCharArrayChar[i](); was just a example – Nathan Jun 02 '14 at 20:07

3 Answers3

4

The other ways are ugly, which is one of the reasons std::string exists :). But for educational purposes, here is how you could return char* (as asked):

// caller is responsible for deleting the return value
char* getEntityName(DWORD Address)
{
    DWORD BaseDword = ReadBaseDword(Address); // (not sure what this achieves)

    int size = ReadCharSize();

    char* name = new char[size];
    name[size - 1] = '\0';

    for (int i = 0; i < size - 1; i++)
    {
        char c = ReadCharArrayChar[i](); // odd looking, but I'll assume this works
        name[i] = c;
    }

    return name;
}

A similar option still uses a raw pointer for the buffer, but has the caller pass it in (along with its size):

// returns: true iff the buffer was successfully populated with the name
// exceptions might be a better choice, but let's keep things simple here
bool getEntityName(DWORD Address, char* buffer, int maxSize)
{
    DWORD BaseDword = ReadBaseDword(Address); // (not sure what this achieves?)

    int size = ReadCharSize();
    if(size > maxSize)
       return false;

    buffer[size - 1] = '\0';

    for (int i = 0; i < size - 1; i++)
    {
        char c = ReadCharArrayChar[i](); // odd looking, but I'll assume this works
        buffer[i] = c;
    }

    return true;
}

The latter option would allow, for example:

char buffer[100];
getEntityName(getAddress(), buffer, 100);
dlf
  • 9,045
  • 4
  • 32
  • 58
  • dont you have to delete the new char[size]? – Nathan Jun 02 '14 at 20:03
  • 2
    @Nathan The calling code will need to do that eventually. – dlf Jun 02 '14 at 20:03
  • Is that the best way to do it with std::string then? – Nathan Jun 02 '14 at 20:13
  • @Nathan do you mean with*out* `std::string`? "Best" always depends on context, but it's probably what I'd do if I were forbidden from using any sort of string object. Another option would be to have the caller pass in a buffer and a max size. That would give you more flexibility in how and where the characters were stored. – dlf Jun 02 '14 at 20:16
2
char * getEntityName(DWORD Address)
{
    DWORD BaseDword = ReadBaseDword(Address);

    int size = ReadCharSize();

    char* name = malloc (size);

    for (int i = 0; i < size - 1; i++)
    {
        name[i] = ReadCharArrayChar[i]();
    }

    name[size - 1] = 0;

    return name;
}

Note that the caller should free the returned value when they're done with it. This assumes size includes the terminating zero byte, which it seems to given the example code.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • Upvoted, but the result of the `malloc` will need to be explicitly cast to `char*`, if I recall correctly. – dlf Jun 02 '14 at 20:12
  • @dlf `malloc` returns a `void *`, so no cast is necessary. – Fiddling Bits Jun 02 '14 at 20:37
  • @FiddlingBits my compiler (VC2012) will not perform that cast implicitly. However, I've learned (here) that what my compiler will or won't do is not always the best barometer of correctness... :) – dlf Jun 02 '14 at 20:42
  • @FiddlingBits But maybe [this time it's right](http://coliru.stacked-crooked.com/a/e85764f44b394b2c) – dlf Jun 02 '14 at 20:46
  • @dlf Should have stopped being necessary when C99 was published... I think. :-D – Fiddling Bits Jun 02 '14 at 20:48
  • @FiddlingBits From a quick survey of SO questions ([this](http://stackoverflow.com/questions/15118990/typecasting-malloc-c), for example), it seems that it is necessary in C++, but not in C. The question is tagged with both languages (despite using `std::string` in the original), so I suppose there's no reason for me to complain. – dlf Jun 02 '14 at 20:52
  • @dlf You may be correct. I must admit, I'm a dunce when it comes to C++. – Fiddling Bits Jun 02 '14 at 20:55
1

If I absolutely could not use std::string, I would either use std::vector<char> for this:

std::vector<char> getName(DWORD Address)
{
    DWORD BaseDword = ReadBaseDword(Address);

    const int size = ReadCharSize();

    std::vector<char> name(size);

    for (int i = 0; i < size - 1; i++)
    {
        name[i] = ReadCharArrayChar(i);
    }

    name[size - 1] = '\0';

    return name;
}

or std::unique_ptr<char[]> if I knew the caller would never need to modify the result:

std::unique_ptr<char[]> getName(DWORD Address)
{
    DWORD BaseDword = ReadBaseDword(Address);

    const int size = ReadCharSize();

    std::unique_ptr<char[]> name(new char[size]);

    for (int i = 0; i < size - 1; i++)
    {
        name[i] = ReadCharArrayChar(i);
    }

    name[size - 1] = '\0';

    return name;
}
Casey
  • 41,449
  • 7
  • 95
  • 125