0

I am looking for the best way to remove the start of a string until the last occurrence of a character. For example. I have a char array that contains the following:

[Microsoft][ODBC SQL Server Driver][SQL Server]Option 'enable_debug_reports' requires a value of 0 or 1.

Basically, I am looking for the last occurrence of ']'. I would like my char array to be trimmed to:

Option 'enable_debug_reports' requires a value of 0 or 1.

I have found several ways to do this with the string data type. I am wondering if there is an effective way to manipulate a char array. My program requires several parameters to be char[] instead of strings. How would I use something like strcpy in my situation?

Kyle Williamson
  • 2,251
  • 6
  • 43
  • 75
  • If you want to work with `std::string`s but need to use some functions that take `const char *`, you can use `myString.c_str()`. – BoBTFish Mar 05 '15 at 15:34
  • I wish for my question to deal specifically with char[]. Thank you for your suggestion. I am, however, wondering if the same thing can be done without using `std::string` or any casting. – Kyle Williamson Mar 05 '15 at 15:37

3 Answers3

2

The below should work provided your string does contain the ']' character:

std::string trimIt(originalCStr);
std::string trimmed(trimIt.substr(trimIt.find_last_of("]")));
strcpy(originalCStr, trimmed.c_str());

For a pure C approach:

char *toPtr = originalCStr;
char *fromPtr = strchr(toPtr, ']');
++fromPtr;
while (*fromPtr != '\0') {
    *toPtr = *fromPtr;
    ++fromPtr;
    ++toPtr;
}
*toPtr = '\0';
Yoshiya
  • 452
  • 5
  • 17
2

you could use strrchr to find the last occurrence of ']' and then cut your char[] using memcpy as seen here

Community
  • 1
  • 1
Rod
  • 754
  • 11
  • 21
  • `memmove` if the copy is in the same buffer. and potentially (or actually) overlaps. Or just a plain-old `dst` and `src` pointer loop through the terminator. – WhozCraig Mar 05 '15 at 15:43
1

If you insist on not using std::string, for whatever reason, there is still a pure C++ approach using standard algorithms, which work just fine with raw arrays. The following is C++14 (it uses std::rbegin and std::rend), but you can adapt it to C++11 using std::reverse_iterator manually if necessary:

#include <algorithm>
#include <iostream>

template <class InputRange, class OutputIterator, class Value>
void CopyFrom(InputRange const& input, OutputIterator output_iter, Value const& value)
{
    using std::rbegin;
    using std::rend;
    using std::end;

    auto const iter_last = std::find(rbegin(input), rend(input), value);
    std::copy(iter_last.base(), end(input), output_iter);
}

int main()
{
    char const src[] = "[Microsoft][ODBC SQL Server Driver][SQL Server]Option 'enable_debug_reports' requires a value of 0 or 1.";
    char * dst = new char[sizeof(src) + 1](); // just for this toy program

    CopyFrom(src, dst, ']');

    std::cout << dst;
    delete[] dst;
}

Note that this solution assumes that you need the substring as a copy, and there is no error checking for input that does not contain the specified value.

And of course, you are probably better of switching to std::string and using c_str() for any C APIs.

Christian Hackl
  • 27,051
  • 3
  • 32
  • 62