I have this variable dirpath2 where I store the deepest directory name of a path:
typedef std::basic_string<TCHAR> tstring;
tstring dirPath = destPath;
tstring dirpath2 = dirPath.substr(destPathLenght - 7,destPathLenght - 1);
I want to be able to compare it it another string, something like:
if ( _tcscmp(dirpath2,failed) == 0 )
{
...
}
I've tried a lot of things but nothing seems to work. Can anyone tell me how to do this or what am I doing wrong?
Please bear in mind I know almost next to nothing about C++ and this whole thing is driving me insane.
thanx in advance
std::basic_string<T> have an overloaded operator==, try this:
if (dirpath2 == failed)
{
...
}
Alternatively you could do like this. As std::basic_string<T> doesn't have an implicit conversion operator to const T*, you need to use the c_str member function to convert to const T*:
if ( _tcscmp(dirpath2.c_str(), failed.c_str()) == 0 )
{
...
}
Why are you using _tcscmp with a C++ string? Just use it's builtin equality operator:
if(dirpath2==failed)
{
// ...
}
Have a look at the provided comparison operators and methods that can be used with the STL strings.
In general, if you use C++ strings you don't need to use the C string functions; however, if you need to pass C++ strings to functions that expect C-strings you can use the c_str() method to get a const C-string with the content of the specified C++ string instance.
By the way, if you know "almost next to nothing about C++", you should really get a C++ book and read it, even if you come from C.
std::basic_string has a == operator. Use the string classs template:
if (dirpath2 == failed)
{
...
}
Related
Hello I am trying to write a function that converts a string to lowercase by using a pointer instead of a return value.
void makeLowerCase(std::string* in){
//for loop tolower(char from *in);}
but I have no idea how to get each char out of my pointer to use tolower() with, or how to get how many chars are in the string as
*in.length()
and
sizeof(*in)/sizeof(char)
don't work for it. The former I get an error on the use of a pointer, the latter I get the same return value for sizeof(*in) so I don't even know how I would end my for loop.
C++ has a shortcut to get the member of an object pointed to by a pointer:
in->length()
For accessing characters, use parentheses:
(*in)[i]
Instead of passing by pointer and dealing with pointer syntax you can pass the string by reference and then you can use it just like a normal std::string. If you have to use a pointer then you can either use
in->length();
or
(*in).length();
The parentheses are required in the second case as . has a higher precedence then *.
As for transforming the string to lower case you can use the built in functions from <algorithm> and and that would give you
void makeLowerCase(std::string& in)
{
std::transform(in.begin(), in.end(), in.begin(), ::tolower);
}
*in.length()
does not work because . has a higher precedence than *. Use parantheses:
(*in).length()
sizeof(*in)/sizeof(char)
is the same as
sizeof(*in) / 1
because sizeof(char) == 1. sizeof(*in) == sizeof(std::string), so this yields the size of the std::string object itsself, not the string of characters, which is implemention-defined.
This information, in combination with iterators, for_each, and lambdas, make for a pretty three-liner without any functions:
#include <cctype>
...
for (char& c : str)
c = std::tolower(c);
Notes:
Use references instead. They look better and are easier usable. Pointers should only be used in C++ for low-level stuff or when there's no way to cut them out.
For pointers you would use the pointer operator. So that would be
in->length();
However a naked loop is not the ideal way (nor is using pointers to be honest).
A better way would be to use iterators to iterate through the string and convert it that way.
for (auto it=in->begin(); it!=in->end(); ++it) {
*it = std::tolower(*it);
}
I'm working with rapidxml, so I would like to have comparisons like this in the code:
if ( searchNode->first_attribute("name")->value() == "foo" )
This gives the following warning:
comparison with string literal results in unspecified behaviour [-Waddress]
Is it a good idea to substitute it with:
if ( !strcmp(searchNode->first_attribute("name")->value() , "foo") )
Which gives no warning?
The latter looks ugly to me, but is there anything else?
You cannot in general use == to compare strings in C, since that only compares the address of the first character which is not what you want.
You must use strcmp(), but I would endorse this style:
if( strcmp(searchNode->first_attribute("name")->value(), "foo") == 0) { }
rather than using !, since that operator is a boolean operator and strcmp()'s return value is not boolean. I realize it works and is well-defined, I just consider it ugly and confused.
Of course you can wrap it:
#include <stdbool.h>
static bool first_attrib_name_is(const Node *node, const char *string)
{
return strcmp(node->first_attribute("name")->value(), string) == 0;
}
then your code becomes the slightly more palatable:
if( first_attrib_name_is(searchNode, "foo") ) { }
Note: I use the bool return type, which is standard from C99.
If the value() returns char* or const char*, you have little choice - strcmp or one of its length-limiting alternatives is what you need. If value() can be changed to return std::string, you could go back to using ==.
When comparing char* types with "==" you just compare the pointers. Use the C++ string type if you want to do the comparison with "=="
You have a few options:
You can use strcmp, but I would recommend wrapping it. e.g.
bool equals(const char* a, const char* b) {
return strcmp(a, b) == 0;
}
then you could write: if (equals(searchNode->first_attribute("name")->value(), "foo"))
You can convert the return value to a std::string and use the == operator
if (std::string(searchNode->first_attribute("name")->value()) == "foo")
That will introduce a string copy operation which, depending on context, may be undesirable.
You can use a string reference class. The purpose of a string reference class is to provide a string-like object which does not own the actual string contents. I've seen a few of these and it's simple enough to write your own, but since Boost has a string reference class, I'll use that for an example.
#include <boost/utility/string_ref.hpp>
using namespace boost;
if (string_ref(searchNode->first_attribute("name")->value()) == string_ref("foo"))
I'm new to c++ (I'm a c# developer).
I have an SQLite wrapper class that requires you to pass in a database name as a const char* , however I only have it as a Platform::String (after doing a file search).
I cant seem to find a way to convert the Platform::String to const char*.
Ive seen another question on StackOverflow that explain why it isnt straight-forward, but no sample code or end-to-end solution.
Can anyone help me ?
Thanks
Disclaimer: I know little about C++/CX, and I'm basing the answer on the documentation here.
The String class contains 16-bit Unicode characters, so you can't directly get a pointer to 8-bit char-typed characters; you'll need to convert the contents.
If the string is known to only contain ASCII characters, then you can convert it directly:
String s = whatever();
std::string narrow(s.Begin(), s.End());
function_requiring_cstring(narrow.c_str());
Otherwise, the string will need translating, which gets rather hairy. The following might do the right thing, converting the wide characters to multi-byte sequences of narrow characters:
String s = whatever();
std::wstring wide(s.Begin(), s.End());
std::vector<char> buffer(s.Length()+1); // We'll need at least that much
for (;;) {
size_t length = std::wcstombs(buffer.data(), wide.c_str(), buffer.size());
if (length == buffer.size()) {
buffer.resize(buffer.size()*2);
} else {
buffer.resize(length+1);
break;
}
}
function_requiring_cstring(buffer.data());
Alternatively, you may find it easier to ignore Microsoft's ideas about how strings should be handled, and use std::string instead.
I was looking at some example C++ code for a hardware interface I'm working with and noticed a lot of statements along the following lines:
if ( NULL == pMsg ) return rv;
I'm sure I've heard people say that putting the constant first is a good idea, but why is that? Is it just so that if you have a large statement you can quickly see what you're comparing against or is there more to it?
So that you don't mix comparison (==) with assignment (=).
As you know, you can't assign to a constant. If you try, the compiler will give you an error.
Basically, it's one of defensive programming techniques. To protect yourself from yourself.
To stop you from writing:
if ( pMsg = NULL ) return rv;
by mistake. A good compiler will warn you about this however, so most people don't use the "constant first" way, as they find it difficult to read.
It stops the single = assignment bug.
Eg,
if ( NULL = pMsg ) return rv;
won't compile, where as
if ( pMsg = NULL) return rv;
will compile and give you headaches
To clarify what I wrote in some of the comments, here is a reason not to do this in C++ code.
Someone writes, say, a string class and decides to add a cast operator to const char*:
class BadString
{
public:
BadString(const char* s) : mStr(s) { }
operator const char*() const { return mStr.c_str(); }
bool operator==(const BadString& s) { return mStr == s.mStr; }
// Other stuff...
private:
std::string mStr;
};
Now someone blindly applies the constant == variable "defensive" programming pattern:
BadString s("foo");
if ("foo" == s) // Oops. This compares pointers and is never true.
{
// ...
}
This is, IMO, a more insidious problem than accidental assignment because you can't tell from the call site that anything is obviously wrong.
Of course, the real lessons are:
Don't write your own string classes.
Avoid implicit cast operators, especially when doing (1).
But sometimes you're dealing with third-party APIs you can't control. For example, the _bstr_t string class common in Windows COM programming suffers from this flaw.
When the constant is first, the compiler will warn you if you accidentally write = rather than == since it's illegal to assign a value to a constant.
Compilers outputting warnings is good, but some of us in the real world can't afford to treat warnings as errors. Reversing the order of variable and constant means this simple slip always shows up as an error and prevents compilation. You get used to this pattern very quickly, and the bug it protects against is a subtle one, which is often difficult to find once introduced.
They said, "to prevent mixing of assignment and comparison".
In reality I think it is nonsense: if you are so disciplined that you don't forget to put constant at the left side, you definitely won't mix up '=' with '==', would you? ;)
I forget the article, but the quote went something like:
Evidently it's easier remembering to put the constant first, than it is remembering to use ==" ;))
An answer to one of my questions included the following line of code:
label = std::safe_string(name); // label is a std::string
The intent seems to be a wrapper around a string literal (so presumably no allocation takes place). I've never heard of safe_string and neither, apparently, has google (nor could I find it in the 98 standard).
Does anyone know what this is about?
After searching google code search (I should have thought of this first...) I found this:
//tools-cgi.cpp
string safe_string (const char * s)
{
return (s != NULL) ? s : "";
}
Which converts NULLs to zero length strings. Although this is not standard it's probably some sort of extension in a specific STL implementation which was referred to in the answer.
There is no standard safe_string. The safe_string you're seeing in that answerer's response is from what looks like a private STL extensions utility library.
Google for "stlext/stringext.h" and you'll see the same library referenced in a post on another forum.
There is no such thing as std::safe_string
It is not part of C++ standard (but perhaps it should be?)
I have been using the same kind of helper function to avoid a std::string throw an exception with a NULL char * string. But it was more something like:
// defined somewhere else as ""
extern const char * const g_strEmptyString ;
inline const char * safe_string(const char * p)
{
return (p) ? (p) : (g_strEmptyString) ;
}
No overhead, and no crash of a std::string when I feed it a char * string that could be NULL but that, in that particular case, should behave as an empty string.