I want to compare two strings. Is it possible with strcmp? (I tried and it does not seem to work). Is string::compare a solution?
Other than this, is there a way to compare a string to a char?
Thanks for the early comments. I was coding in C++ and yes it was std::string like some of you mentioned.
I didn't post the code because I wanted to learn the general knowledge and it is a pretty long code, so it was irrelevant for the question.
I think I learned the difference between C++ and C, thanks for pointing that out. And I will try to use overloaded operators now. And by the way string::compare worked too.
For C++, use std::string and compare using string::compare.
For C use strcmp. If your (i meant your programs) strings (for some weird reason) aren't nul terminated, use strncmp instead.
But why would someone not use something as simple as == for std::string
?
Assuming you mean std::string, why not use the overloaded operators: str1 == str2, str1 < str2?
See std::basic_string::compare and std::basic_string operators reference (in particular, there exists operator==, operator!=, operator<, etc.). What else do you need?
When using C++ use C++ functions viz. string::compare. When using C and you are forced to use char* for string, use strcmp
By your question, "is there a way to compare a string to a char?" do you mean "How do I find out if a particular char is contained in a string?" If so, the the C-library function:
char *strchr(const char *s, int c);
will do it for you.
-- pete
std::string can contain (and compare!) embedded null characters.
are*comp(...) will compare c-style strings, comparing up to the first null character (or the specified max nr of bytes/characters)
string::compare is actually implemented as a template basic_string so you can expect it to work for other types such as wstring
On the unclear phrase to "compare a string to a char" you can compare the char to *string.begin() or lookup the first occurrence (string::find_first_of and string::find_first_not_of)
Disclaimer: typed on my HTC, typos reserved :)
Related
As we all know, with C-style string comparisons, the value is dependent on the ASCII value of each character and just uses the strcmp function to compare. I'm confused that what the std::string compare depends on?
Although I have searched Google, I still didn't find the answer.
In addition, if strings are all base36 strings and they are all in lower case, could I compare their values by strings directly? Or I should convert them as a long variable using the strtol function? Which method is better?
Your outset "As we all know, with C-style string comparisons, the value is dependent on the ASCII value of each character..." is unfortunately wrong already. With e.g. UTF-8 strings and various forms of collation, that's simply untrue.
Then "...and just uses the strcmp function to compare." is also wrong, because C-style strings don't have an inherent way to compare but multiple ways that also depend on e.g. the encoding and locale. You could use strcmp() for bytewise equality comparisons though, but that won't always give you expected results.
To answer your question what std::string uses, that's simple. std::string is a specialization of the std::basic_string template and it delegates comparisons to its char_traits template parameter. This parameter typically uses memcmp(). It can not possibly use strcmp(), because other than a C-style string, std::string can include null chars, but strcmp() would stop at those.
std::string compare depends upon 'ASCII values' in exactly the same way that strcmp does.
For base36 comparisons, simple string comparison (either strcmp or std::string) doesn't work because "00123" and "123" are equal when representing base36 integers but they compare differently as strings. Neither does strtol work very well because of integer overflow. Instead you should probably write your own comparison routine that removes leading zeros, then compares length and finally for strings of equal length does a string comparison.
I am quite new to C++ programming and am getting to know the basics by reading books.
I came across two interesting functions strcmpi() and stricmp().
I know that both the functions compare strings lexicographically by ignoring the case of the strings.
So I just wanted to know the differences between them.
Any help would be appreciated.
Both functions do the exact same thing (as long as you stick to comparing plain ASCII strings).
The problem is, neither is part of the ANSI C standard, so you can't be sure any of these will be available for a given compiler.
You can have yet other names for the same functionality. _strcmpi() for instance.
There is no standard case-insensitive comparison primitive in C/C++, so each compiler provides its own version with varying names.
The best "standard" variant would be the ISO C++ _stricmp, but I would not bet every compiler on the planet currently supports it.
The reason behind it is that case sensitivity is not as trivial a problem as it might seem, what with all the diacritics of various languages and the extended character encodings.
While plain ASCII string will always be compared the same way, you can expect differences in implementation when trying to compare UTF16 strings or other extended character sets.
Judging by this article, some C++ geeks seem to get a big kick rewriting their own version of it too.
strcmpi and stricmp are case-insensitive versions of strcmp. They work identically in all other respects. _strcmpi and _stricmp are alternate names for strcmpi and stricmp. strcasecmp is an alias for strcmpi.
int strcmp (const char *string1, const char *string2);
int strcmpi (const char *string1, const char *string2);
int stricmp (const char *string1, const char *string2);
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ char* vs std::string
I'm new to C++ coming from C# but I really do like C++ much better.
I have an abstract class that defines two constant strings (not static). And I wondered if a const char* would be a better choice. I'm still getting the hang of the C++ standards, but I just figured that there really isn't any reason why I would need to use std::string in this particular case (no appending or editing the string, just writing to the console via printf).
Should I stick to std::string in every case?
Should I stick to std::string in every case?
Yes.
Except perhaps for a few edge cases where you writing a high performance multi-threaded logging lib and you really need to know when a memory allocation is going to take place, or perhaps in fiddling with individual bits in a packet header in some low level protocol/driver.
The problem is that you start with a simple char and then you need to print it, so you use printf(), then perhaps a sprintf() to parse it because std::stream would be a pain for just one int to string. And you end up with an unsafe and unmaintainable mix oc c/c++
I would stick to using std::string instead of const char*, simply because most of the built-in C++ libraries work with strings and not character arrays. std::string has a lot of built-in methods and facilities that give the programmer a lot of power when manipulating strings.
Should I stick to std::string in every case?
There are cases where std::string isn't needed and just a plain char const* will do. However you do get other functionality besides manipulation, you also get to do comparison with other strings and char arrays, and all the standard algorithms to operate on them.
I would say go with std::string by default (for members and variables), and then only change if you happen to see that is the cause of a performance drop (which it won't).
Use std::string when you need to store a value.
Use const char * when you want maximum flexibility, as almost everything can be easily converted to or from one.
This like comparing Apples to Oranges. std::string is a container class while char* is just a pointer to a character sequence.
It really all depends on what you want to do with the string.
Std::string on the other hand can give you a quick access for simple string calculation and manipulation function. Most of those are simple string manipulation functions, nothing fancy really.
So it basically depends on your needs and how your functions are declared. The only advantage for std::string over a char pointer is that it doesnt require a specific lenghth decleration.
So I have a dilemma. I need to compare two C-style strings and I searched for the functions that would be the most appropiate:
memcmp //Compare two blocks of memory (function)
strcmp //Compare two strings (function )
strcoll //Compare two strings using locale (function)
strncmp //Compare characters of two strings (function)
strxfrm //Transform string using locale (function)
The first one I think is for addresses, so the idea is out.
The second one sounds like the best choice to me, but I wanna hear feedback anyway.
The other three leave me clueless.
For general string comparisons, strcmp is the appropriate function. You should use strncmp to only compare some number of characters from a string (for example, a prefix), and memcmp to compare blocks of memory.
That said, since you're using C++, you should avoid this altogether and use the std::string class, which is much easier to use and generally safer than C-style strings. You can compare two std::strings for equality easily by just using the == operator.
Hope this helps!
Both memcmp and strcmp will work fine. To use the former, you'll need to know the length of the shorter string in advance.
This question already has answers here:
How to read and write a STL C++ string?
(3 answers)
Closed 4 years ago.
char filebuf[256];
path current = current_path();
std::cout<<"CurrentWorking "<<current<<endl;
string _UserDir = "TTiTraceLogs";
sprintf(filebuf,"%s/%s",current,_UserDir); ///crashing here
If I format only current, then it is ok.
sprintf(filebuf,"%s",current);
Output:
CurrentWorking D:/working/eclipse_projects/sadftp/CollectTTiTraceSept10_1009_174
_higher/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/Release
In the standard sprintf() function (and the other printf()-like functions), the %s specifier doesn't work with C++ stringss; it only works with C-style strings. Try _UserDir.c_str(), which gives you a const char * that points to the internal array of the string and can therefore be used with many C functions.
If current_path() returns something that is not a (possibly const) pointer to char or unsigned char, you need to convert that value too.
Is string actually std::string? And path a boost::filesystem::path? In that case, you should know that C library functions (like sprintf and printf) don't support C++ classes like std::string. That's only natural.
What you need to do is:
sprintf(filebuf, "%s%s", current.c_str(), _UserDir.c_str());
But a more elegant solution, if you're already using C++, is to either use std::stringstream or boost::format. As a bonus won't have to mess with allocating buffers on the stack and worrying that the result might be longer than the buffer (which may lead to buffer overruns and security exploits - sprintf() is probably the culprit behind many of those...).
std::stringstream
std::stringstream filebuf;
filebuf << current_path().c_str() << _UserDir;
std::string filename = filebuf.str();
boost::format
std::string filename = "%s%s" % current_path().c_str() % _UserDir;
By the way, if you just want to concatenate directories, the 'proper' way to do that with boost::filesystem::path would be:
boost::filesystem::path fullPath = current_path() / _UserDir;
Yes, the / operator is used for adding path components. They are separated by slashes after all, aren't they?
That being said, if you still choose, against all good advice, to use the old C library functions, please, for all that's good in the world, don't use sprintf(). Use the slightly-safer snprintf(), which takes the maximum buffer size as an argument.
Some of your code is unclear (e.g., what on earth is a path type?), but it looks like you're trying to print a std::string via a C-style string formatter (sprintf %s), which is totally invalid.
Look at std::stringstream. Also, for simple concatenation, std::string provides a + operator overload. So you could be doing simply:
current + "/" + whatever
sprintf only works with char*, you cannot use it with strings. Try _UserDir.c_str() and you should be fine.
What I don't understand is why your compiler doesn't complain. You can't pass non-POD types like std::string or boost::filepath as varargs; my compiler says that this will abort at runtime, and any compiler will know here that you're passing class types to a vararg. (Formally, it's undefined behavior, but unless the compiler defines it somehow as an extention, then there's no reason for it not to at least warn.)
current is not a char* pointer, it is a path so it might lead to complication
also, sprintf can't print to string variables like you are trying to do.
How long is current_path? Maybe strlen(current_path)+strlen(_UserDir)+2 > 256.
Since _UserDir is a C++ string, you'll need to get its C string to call sprintf(), which is a C function.
sprintf(filebuf,"%s/%s",current,_UserDir.c_str()); // gets C string
Also, what is a path? If it isn't like a typedef for char*, then you can't just sprintf() that either. It may be that operator<<() is overloaded for path, which is why the std::cout works.
%s indicates a C string. You have a C++ string. You need to call .c_str()
The reason of the crash has already been explained - I can only add one piece of advice - just ditch sprintf if possible and use string streams. It will make your code better. You will not have to worry about the length of the buffer or other errors like the one you encountered.