char * compare with std string wrong result - c++

case 1:
std::string dd = "5A"
char checkSum[9]
checkSum[0] = '5';
checkSum[1] = 'A';
if(strcmp(dd.c_str(),checkSum) == 1){
return 1;
}
else {return 0;}
RESULT: returns 1 //Correct!
case 2:
std::string dd = "0A"
char checkSum[9];
checkSum[0] = '5';
checkSum[1] = 'A';
if(strcmp(dd.c_str(),checkSum) == 1){
return 1;
}
else {return 0;}
RESULT: returns 0 //Correct!
case 3:
std::string dd = "5A"
char checkSum[9]
checkSum[0] = '0';
checkSum[1] = 'A';
if(strcmp(dd.c_str(),checkSum) == 1){
return 1;
}
else {return 0;}
RESULT: returns 1 //Not Correct!
Anyone knows whats wrong? thx!

strcmp requires two null-terminated strings, but you are not adding a null-terminator to checkSum.
This is why case 1 returns 1 when in fact it should return 0. Note that your expected values are incorrect. In case 1, once you have added in the null-terminator, the two strings should compare as equal. And so strcmp will return 0 and your code should also return 0.
For case 2, strcmp("0A", "5A") returns a negative value since '0'<'5' and so your code should return 0.
For case 3, strcmp("5A", "0A") returns a positive value, and it just so happens that the positive value is 1 which you are mistakenly testing for by equality.
In all cases testing for a value of 1 is incorrect since strcmp never promises to return 1. It promises to return either:
a value of 0 to indicate that the two strings are equal, or,
a positive value to indicate that str1 compares greater than str2, or,
a negative value to indicate that str1 compares less than str2.
The only valid comparisons on the return value of strcmp are therefore ==0, >0 or <0.
You need to revisit the documentation for strcmp and correct your understanding of how to interpret the return value.

Your checksum contain undefined data you don't add a '\0' termination character in it. It is unexpected behavior if you call the strcmp. You could declare your checksum as:
char checkSum[9] = {0};
but better solution is to avoid unsafe character arrays, use std::string instead.

strcmp return value:
A zero value indicates that both strings are equal. A value greater
than zero indicates that the first character that does not match has a
greater value in str1 than in str2; And a value less than zero
indicates the opposite.
(Extract from http://www.cplusplus.com/reference/clibrary/cstring/strcmp/)

Also you should never compare the result of strcmp with anything else then zero as in
strcmp(s1, s2) == 0
strcmp(s1, s2) > 0
strcmp(s1, s2) < 0
strcmp(s1, s2) != 0
as the standard does not guerantee a 1 (or -1) in the case of difference.

Related

c++ std::string '==' operator and Compare method is return Not equal value to equal string

motion->bone_frames[0].name == model->bones[0].bone_name//it return 0 . it should be 1
motion->bone_frames[0].name.Compare(model->bones[0].bone_name)//it return 1 . it should be 0
wcscmp(motion->bone_frames[0].name.c_str(), model->bones[0].bone_name.c_str()) //it return 0 it should be 0 correct
I cant understand std::string compare functions why have different result to wcscmp.
Can i know why these results are different?
Is it cause of different is length?
Because they are not equal. Check the size of your strings in the image that you've attached. In the first there are '\0' at the end of the string, that are characters as well.
wcscmp stops comparing when it hits L'\0'. A std::wstring will consider the size() of the strings.
The string == and compare will return "different" results as the first returns true and the second returns 0 for equal strings. See Differences between C++ string == and compare()?
The standard operator== returns lhs.compare(rhs) == 0.

Separating every second digit in an integer C++

I am currently finishing up an assignment I have to complete for my OOP class and I am struggling with 1 part in particular. Keep in mind I am still a beginner. The question is as followed:
If the string contains 13 characters, all of characters are digits and the check digit is modulo 10, this function returns true; false otherwise.
This is in regards to a EAN. I basically have to separate every second digit from the rest digits. for example 9780003194876 I need to do calculations with 7,0,0,1,4,7. I have no clue about doing this.
Any help would be greatly appreciated!
bool isValid(const char* str){
if (atoi(str) == 13){
}
return false;
}
You can start with a for loop which increments itself by 2 for each execution:
for (int i = 1, len = strlen(str); i < len; i += 2)
{
int digit = str[i] - '0';
// do something with digit
}
The above is just an example though...
Since the question was tagged as C++ (Not C, so I suggest other answerers to not solve this using C libraries, please. Let us getting OP's C++ knoweledge in the right way since the beggining), and is an OOP class I'm going to solve this with the C++ way: Use the std::string class:
bool is_valid( const std::string& str )
{
if( str.size() == 13 )
{
for( std::size_t i = 0 ; i < 13 ; i += 2 )
{
int digit = str[i] - '0';
//Do what you wan't with the digit
}
}
else
return false;
}
First, if it's EAN, you have to process every digit, not just
every other one. In fact, all you need to do is a weighted sum
of the digits; for EAN-13, the weigths alternate between 1 and
3, starting with three. The simplest solution is probably to
put them in a table (i.e. int weigt[] = { 1, 3, 1, 3... };,
and iterate over the string (in this case, using an index rather
than iterators, since you want to be able to index into
weight as well), converting each digit into a numerical value
(str[i] - '0', if isdigit(static_cast<unsigned char>(str[i])
is true; if it's false, you haven't got a digi.), then
multiplying it by the running total. When you're finished, if
the total, modulo 10, is 0, it's correct. Otherwise, it isn't.
You certainly don't want to use atoi, since you don't want the
numerical value of the string; you want to treat each digit
separately.
Just for the record, professionally, I'd write something like:
bool
isValidEAN13( std::string const& value )
{
return value.size() == 13
&& std::find_if(
value.begin(),
value.end(),
[]( unsigned char ch ){ return !isdigit( ch ); } )
== value.end()
&& calculateEAN13( value ) == value.back() - '0';
}
where calculateEAN13 does the actual calculations (and can be
used for both generation and checking). I suspect that this
goes beyond the goal of the assignment, however, and that all
your teacher is looking for is the calculateEAN13 function,
with the last check (which is why I'm not giving it in full).

If statement with negative values

In an if statement like this:
if(strcmp(str1,str2))
strcmp() can return a negative value, and if it does, does the if statement consider it to be TRUE or FALSE.
In C++, the if statement treats any nonzero value as true. A negative value is not zero, so it will be considered true. The following two statements are equivalent:
if (strcmp(str1, str2))
if (strcmp(str1, str2) != 0)
The strcmp function when used with an if statement can lead to some very unreadable code. The following statement says to call foo if and only if str1 is different than str2.
if (strcmp(str1, str2)) foo();
Some would argue this is somewhat unexpected and unreadable, but it's due to the fact that strcmp is not really meant to be used this way as it does not return a bool. If you check out this great reference you'll see that it returns an integral value which is meant to indicate the relationship between the strings. strcmp can tell you much more than simply whether or not two strings are the same. According to the reference strcmp returns:
0 if both strings are equal
A positive value if the first character that does not match has a greater value in str1 than in str2
A negative value if the first character that does not match has a greater value in str2 than in str1
Because an if statement will coerce any non-zero integer value into a boolean value of true the if statement if (strcmp(str1, str2)) foo() will always interpret true and execute foo, except when str1 and str2 are equal (in which case the if statement will interpret false and foo will not be executed).
The more common way to use strcmp with an if statement is to combine your call to strcmp with a binary comparison within the if statement, testing against an integral value:
if (strcmp(str1, str2) == 0) foo(); // foo executed iff str1 and str2 are equal
if (strcmp(str1, str2) != 0) foo(); // foo executed iff str1 and str2 are not equal
You might also use strcmp with an if statement to sort strings, strcmp is ideal for this because it returns based on the first unmatching character of the string. You could use it with something like the following (untested code):
bool swapped = false;
do {
for (i = 1; i < numStrings; i++) {
if (strcmp(str[i-1], str[i]) > 0) {
swap(i-1, i);
swapped = true;
}
}
} while (swapped);
When an integer value is converted to a Boolean value, 0 is false and any other value is true.
C converts any non-zero value to true and only zero is false.
Note that if(strcmp(str1, str2)) is NEARLY always "wrong". You either want one of:
if (strcmp(str1, str2) == 0) to detect that two strings are equal
if (strcmp(str1, str2) > 0) to detect that str1 > str2
if (strcmp(str1, str2) < 0) to detect that str1 < str2
The only reason for if(strcmp(str1, str2)) is for detecting that str1 is different from str2 - which is nearly always not what you want.
And of coruse, in C++, you probably shouldn't be using strcmp at all - since you have std::string that you can just write what you want as a comparison, e.g. if (str1 > str2) or if (str1 != str2), and it's immediately obvious to most people what it means without further questions.

strcmp always true

Why is the if statment always true?
char dot[] = ".";
char twoDots[] = "..";
cout << "d_name is " << ent->d_name << endl;
if(strcmp(ent->d_name, dot) || strcmp(ent->d_name, twoDots))
Am I using strcmp wrong?
strcmp() returns 0 when strings equal and a string cannot be both "." and "..". meaning one side of the || will always be non-zero and therefore the condition is always true.
To correct:
if(0 == strcmp(ent->d_name, dot) || 0 == strcmp(ent->d_name, twoDots))
An alternative would be to use std::string to store the dot variables and use ==:
#include <string>
const std::string dot(".");
const std::string twoDots("..");
if (ent->d_name == dot || ent->d_name == twoDots)
strcmp() returns nonzero in case of a difference (and thus evaluates to true).
Also have a look at the docs (links below). Also have a look on std::string which provides an operator==() for tasks like this. See this answer for the how.
Returns an integral value indicating the relationship between the strings:
A zero value indicates that both strings are equal.
A value greater than zero indicates that the first character that does not match has a greater value in str1 than in str2; And a value less than zero indicates the opposite.
http://www.cplusplus.com/reference/clibrary/cstring/strcmp/
The return value for each of these functions indicates the lexicographic relation of string1 to string2.
Value Relationship of string1 to string2
< 0 string1 less than string2
0 string1 identical to string2
> 0 string1 greater than string2
http://msdn.microsoft.com/en-us/library/e0z9k731%28v=vs.80%29.aspx
strcmp returns -1, 0, or 1 if the strings are lexicographically prior, equal, or later respectively.
To check whether strings are equal, use strcmp(s1, s2) == 0.
Because strcmp returns 0 when equal and 1 or -1 when different, at least one of the two strcmp is returning 1 or -1, the || will return true when any condition is something different of 0, you should do this...
if(strcmp(ent->d_name, dot) == 0 || strcmp(ent->d_name, twoDots) == 0)
I added == 0 after every strcmp
strcmp by itself does not return a boolean. Instead, it returns an int. 0 if match, other if no match. So this should help:
if(0 == strcmp(d_name, dot) || 0 == strcmp(d_name, twoDots)) {
// Other code here
}

isalpha(<mychar>) == true evaluates to false?

string temp is equal to "ZERO:\t.WORD\t1" from my debugger. (the first line of my file)
string temp = RemoveWhiteSpace(data);
int i = 0;
if ( temp.length() > 0 && isalpha(temp[0]) )
cout << "without true worked" << endl;
if ( temp.length() > 0 && isalpha(temp[0]) == true )
cout << "with true worked" << endl;
This is my code to check if first character of temp is a a-z,A-Z. The first if statement will evaluate to true and the 2nd to false. WHY?!?!?! I have tried this even without the "temp.length() > 0 &&" and it still evaluates false. It just hates the "== true". The only thing I can think of is that isalpha() returns != 0 and true == 1. Then, you could get isalpha() == 2 != 1. But, I have no idea if C++ is that ... weird.
BTW, I dont need to know that the "== true" is logically pointless. I know.
output was
without true worked
Compiled with CodeBlock using GNU GCC on Ubuntu 9.10 (if this matters any)
The is* functions are only guaranteed to return a non-zero value if true, NOT necessarily a 1. A typical implementation is table based, with one entry in the table for each character value, and a set of bits defining which bit means what. The is* function will just AND the right bitmask with the table value, and return that, which will only be the value 1 for whichever type happens to have been given bit position 0.
E.g.:
#define __digit 1
#define __lower 2
#define __upper 4
extern int __type_table[];
int isdigit(int c) {
return __type_table[c+1] & __digit;
}
int isalpha(int c) {
return __type_table[c+1] & (__lower | __upper);
}
int islower(int c) {
return __type_table[c+1] & __lower;
}
int isupper(int c) {
return __type_table[c+1] & __upper;
}
Where __type_table is defined as something like int __type_table[UINT_MAX+1]; and would be initialized so (for example) __type_table['0'+1] == __digit and __type_table['A'+1] == __upper.
In case you care, the '+1' part is to leave a spot at the beginning of the table for EOF (which is typically defined as -1).
isalpha doesn't return true, it returns non-zero. This is quite common for API designed for C.
Note that in the expression isalpha(ch) == true, the subexpression true is promoted to type int with value 1.
Well, the documentation suggests that it returns either zero or non-zero, not necessarily just false or true. So you'd better check (isalpha(temp[0]) != 0).
Do not isalpha(ch) == true, but !!isalpha(ch) == true