-
April 28th, 2011, 01:05 PM
#1
Correct way to truncate a std::string
A buffer gets filled with the path to a file:-
Code:
char tmpBuf[MAX_PATH+3];
sprintf(tmpBuf, "\"%s\"", strFileToImport.c_str());
Note that at this stage, the path is surrounded by double quote marks.
Later, I need to assign that path (without the quote marks) to a std::string
Code:
std::string strPathToNewProject = &tmpBuf[1];
// Remove the trailing double quote marks....
strPathToNewProject[strPathToNewProject.length()-1] = 0;
So far, this appears to go okay, but later I need to pass that string to Glib::filename_to_utf8:-
Code:
Glib::ustring ustr = Glib::filename_to_utf8(strPathToNewProject);
However, Glib::filename_to_utf8() throws an exception. I think it must have something to do with the length of the string because I don't get the exception if I don't strip off that trailing double-quote mark. How should I truncate the std::string safely?
"A problem well stated is a problem half solved.” - Charles F. Kettering
-
April 28th, 2011, 01:20 PM
#2
Re: Correct way to truncate a std::string
There is a resize() function you can use. Additionally, you can simply construct it smaller to begin with:
Code:
std::string strPathToNewProject(tmpBuf + 1, strlen(tmpBuf)-2);
-
April 28th, 2011, 01:41 PM
#3
Re: Correct way to truncate a std::string
resize() worked fine Lindley, thanks. I'll have to remember that in future. It was a complete surprise when my original approach caused this problem.
"A problem well stated is a problem half solved.” - Charles F. Kettering
-
April 28th, 2011, 02:04 PM
#4
Re: Correct way to truncate a std::string
Fundamentally, std::strings do not rely on NULL-termination to denote the end of the string. It is valid for a std::string to contain a 0 byte. However, apparently it is *not* valid to hand such a std::string into that Glib function, which is interesting. Is that limitation documented?
-
April 28th, 2011, 02:08 PM
#5
Re: Correct way to truncate a std::string
I'll see if I can find out.
"A problem well stated is a problem half solved.” - Charles F. Kettering
-
April 28th, 2011, 03:33 PM
#6
Re: Correct way to truncate a std::string
Originally Posted by John E
So far, this appears to go okay, but later I need to pass that string to Glib::filename_to_utf8:-
What is the prototype of this function? That is one thing you didn't post.
If that function's parameter is not std::string, you can't give it a std::string.
However, Glib::filename_to_utf8() throws an exception. I think it must have something to do with the length of the string because I don't get the exception if I don't strip off that trailing double-quote mark. How should I truncate the std::string safely?
Until you show how filename_to_utf8 is declared, no one can say really what is going on. There are std::string classes that have the buffer as the first member, and passing that to a function that takes char* may seem to work, when it's just pure luck that it did work.
Also, what was the exception that was thrown? Was it a glib exception? Is that function guaranteed to throw an exception on error? If so, you need to enclose your code in a try/catch block and get the real reason why the exception was thrown by inspecting the what() member function of the exception object (if the exception is derived from std::exception).
Regards,
Paul McKenzie
-
April 28th, 2011, 05:16 PM
#7
Re: Correct way to truncate a std::string
Another option if you have a C++0x compiler is using string::pop_back
http://www.cppreference.com/wiki/str...tring/pop_back
-
April 28th, 2011, 09:09 PM
#8
Re: Correct way to truncate a std::string
Originally Posted by SkyNetTo
Another option if you have a C++0x compiler is using string: op_back
I believe pop_back is a member function of std::basic_string in the current standard library.
-
April 29th, 2011, 01:50 AM
#9
Re: Correct way to truncate a std::string
Originally Posted by Paul McKenzie
Until you show how filename_to_utf8 is declared, no one can say really what is going on.
[...]
Also, what was the exception that was thrown? Was it a glib exception?
Paul - yes, it's a Glib exception. I stepped through the code this morning and it does make sense. Glib::filename_to_utf8() is a wrapper around g_filename_to_utf8() which actually detects the error. You can see here where (and why) the exception gets thrown:-
Code:
namespace Glib
{
Glib::ustring filename_to_utf8(const std::string& opsys_string)
{
gsize bytes_written = 0;
GError* error = 0;
char *const buf = g_filename_to_utf8(
opsys_string.data(), opsys_string.size(), 0, &bytes_written, &error);
if(error)
Error::throw_exception(error);
const ScopedPtr<char> scoped_buf (buf);
return Glib::ustring(scoped_buf.get(), scoped_buf.get() + bytes_written);
}
}
and here's the source code for g_filename_to_utf8()
Code:
gchar*
g_filename_to_utf8 (const gchar *opsysstring,
gssize len,
gsize *bytes_read,
gsize *bytes_written,
GError **error)
{
const gchar *charset;
if (get_filename_charset (&charset))
return strdup_len (opsysstring, len, bytes_read, bytes_written, error);
else
return g_convert (opsysstring, len,
"UTF-8", charset, bytes_read, bytes_written, error);
}
The red line detects the error which equates to:- "invalid byte sequence in conversion input". So it looks like the NULL terminator that I added to my std::string has been detected as an invalid byte for conversion. Seems sensible enough, given what Lindley said earlier.
"A problem well stated is a problem half solved.” - Charles F. Kettering
-
April 29th, 2011, 05:53 AM
#10
Re: Correct way to truncate a std::string
Originally Posted by John E
Paul - yes, it's a Glib exception. I stepped through the code this morning and it does make sense. Glib::filename_to_utf8() is a wrapper around g_filename_to_utf8() which actually detects the error. You can see here where (and why) the exception gets thrown:-
Ok. However you still need to wrap your code using a try/catch, if you haven't done so already.
The red line detects the error which equates to:- "invalid byte sequence in conversion input". So it looks like the NULL terminator that I added to my std::string has been detected as an invalid byte for conversion.
To be more exact, the thing that trips you up is the function's use of string::size() to determine the length of the string data, and not strlen().
That extra NULL byte you added changes everything when it comes to size(), but wouldn't have had any effect if the routine used strlen().
Regards,
Paul McKenzie
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|