C++ How string::compare work - c++

Possible Duplicate:
"compare" definition
Differences between C++ string == and compare()?
As the pages said "compare" simply compares two strings and returns an integer 0,1,-1
but in my test cases (when a=100 and b=1) it returns 2 also.
#include<iostream>
#include<string>
#include<sstream>
#include<vector>
#include<stdlib.h>
using namespace std;
int main()
{
string a,b,ans;
//for(;;)
{cin>>a>>b;
cout<<a.compare(b)<<"\n\n";}
return 0;
}
Also I am not able to understand how the function is comparing two strings (is it only number of digits)
for test cases like a=10^n b=1 it returns n.

It's impossible to speak for "the pages". You can probably find a Youtube video that will make any claim about anything, so that's not a good basis to go on.
Instead, let's turn to the language standard. It says, in [string::compare]:
basic_string::compare: int compare(const basic_string& str) const noexcept;
Effects: [...] compares the two strings by calling traits::compare(data(), str.data(), rlen).
Returns: The nonzero result if the result of the comparison is nonzero. [...]
(There's an additional rule about first comparing the string lengths, which I'm omitting here.)
So then, traits::compare is what we need. The traits need to satisfy the "Character trait requirements", which say:
yields: 0 if for each i in [0,n), X::eq(p[i],q[i]) is true; else, a negative value if, for some j in [0,n), X::lt(p[j],q[j]) is true and for each i in [0,j)
X::eq(p[i],q[i]) is true; else a positive value.
In other words, string::compare returns a negative value, zero, or a positive value respectively to represent lexicographic less-than, equal or greater-than. No actual result values are prescribed, only their sign.
A decent web reference should get this right, though, so you if you know how to find a good source of information, you don't always have to dig through the standard yourself.

Related

Correct way of using isDigit() function in c++

I am new to C++ and I have studied some basics of C language. Here's my code snippet.
#include "iostream"
using namespace std;
int main() {
int a=108;
if(!isdigit(a)) {
cout<<"The number is not a digit";
}
else
cout<<"It's a Number!";
}
}
I dont know why, but it satisfies the condition. It should have outputted, It's a Number! Please correct me and also if u have a better solution to this, do suggest! (To make it more clear) I want to check whether the entered int is actually composed of digits. Thank you
First of all, I'm not sure if you realise that there is a difference between a digit and a number. A digit is a single character from 0 to 9, a number is composed of digits.
Second, std::isigit has a lousy, confusing legacy interface. As documentation will tell you, it takes an int but requires its argument to be representable as unsigned char or EOF to avoid undefined behaviour. The int you pass to the function represents a single character; whether the mapping is according to ASCII or not is not mandated by C++ and thus implementation-defined.
Nevertheless, your C++ implementation very likely uses ASCII or a superset thereof. In ASCII, 108 is the lower-case letter 'l'. isdigit therefore returns false.
I can see where your confusion comes from. The prototype of isdigit says it takes a single int parameter; however, all parameters of type int are digits, so that would be pointless to check!
Here's when you can see the big difference between cplusplus.com and cppreference.com. The former shows little information, while the latter explains a lot more. cppreference gives you the real hint:
The behavior is undefined if the value of ch is not representable as unsigned char and is not equal to EOF
The function is expecting a value between [0,127] and you can see on the page linked that the digits 0123456789 are represented by the numbers [48,57]. As others have pointed out, 108 is actually the ASCII character l.
for (unsigned int i = 0; i < 128; ++i)
{
if (std::isdigit(i))
{
std::cout << i << " is a digit";
}
}
You can't check a number like 108, you would have to check each digit.
isdigit uses the character representation of the int value 108, which is ASCII for l, which is not a digit.
Function Prototype of isdigit()
int isdigit(int argument);
if you pass a=108 to the function it will convert the value to it's equivalent ASCII Value and return the result false. Because 108 is equivalent to 'l' and 'l' is not a digit.
Now pass a = 48 to the function because 48 equivalent to char '0' now the function will return true.
You can also read this and this tutorial for more.
you are using isdigit wrong, as you were told in the answers above it's meant to be used with character representations, to check whether a certain char is a digit or not. you can check this page for more help on isdigit: http://www.tutorialspoint.com/c_standard_library/c_function_isdigit.htm
to your question - I guess you are trying to check if the number you are sending is a single digit number. for this you can simply do:
if (a >= 0 && a <= 9){
// a is a single digit...
}

Actual significance of the int that string comparison returns?

String comparison is a staple of most languages it seems, they all have a function that resembles C's strcmp to some extent. Its return value is usually described as such:
The strcmp() and strncmp() functions return an integer less than, equal to, or greater than zero if s1 (or the first n bytes thereof) is found, respectively, to be less than, to match, or be greater than s2.
Pretty much all there is to take away from that is that if the result is 0 then the strings are equal (sharing identical contents) and if it's nonzero then no.
However, where does the nonzero int value come from if the strings are unequal? What does it mean? And what precisely does it mean for one string to be "greater than" or "less than" another, since they're not numeric values?
Thank you for your time, I've never quite seen an explanation to string comparison functions other than explaining that 0 implies equality and nonzero implies inequality.
Think of the simplest possible C implementation of the function:
int strcmp(char *p1, char *p2)
{
int diff;
do
diff = *p1 - *p2;
while (*p1++ && *p2++ && diff);
return diff;
}
The returned value happens to have the proper sign, but the value itself is just an artifact of the comparison process. That's why the value is left unspecified, to give implementors the widest possible latitude for an efficient implementation.
Strings are compared using lexicographical order, which at its simplest is what you would think of as “dictionary ordering”: the string apple is less than the string banana because the character a precedes the character b according to my English locale; but apple follows abacus because p follows b—you simply compare each character in turn.
strcmp doesn’t make any particular guarantees about its nonzero return values beyond the sign. Typically they’re simply -1, 0, and +1, but you can’t rely on this. The standard could just as well have specified strcmp to return a more specific enumeration:
enum Ordering {
LT,
EQ,
GT
};
But many C standard library functions accept and return “magical” int values as a matter of historical accident.

While scanf with boolean operator

I saw this piece of code today:
while(scanf("%d %d",&x,&y),x||y)
{
....
From what I've understand, it enters the loop if some of the values (x or y) is true.
Since the scanf docs says:
On success, the function returns the number of items of the argument
list successfully filled. This count can match the expected number of
items or be less (even zero) due to a matching failure, a reading
error, or the reach of the end-of-file.
I have rewritten the code to:
while(scanf("%d %d",&x,&y) >= 1)
{
....
But on an online programming challenge site the first while works, the second fails.
Am I right on my assumptions ? What are the differences between this two pieces of code?
(I am tagging as C++, because I have tested in C++ 4.8.2 - GNU C++ Compiler)
scanf returns the number of arguments it matches, but the first code fragment throws out that result and just checks to see if either x or y is true. The second fragment returns that you matched at least one integer, regardless of value.
Consider the input "0 0". In the first case, scanf() returns 2, but x || y returns false. In the second case, your conditional is true.
The first code gives while the result of x||y, this is correct
However, the second code compares the return value of scanf and 1, and then gives while the comparing result.
run this code and you'll be clear.
#include<stdlib.h>
#include<iostream>
using namespace std;
int main()
{
int x, y;
cout<<(scanf("%d %d", &x, &y), x||y)<<endl;
cout<<(scanf("%d %d", &x, &y))<<endl;
return 0;
}

Non-Integer numbers in an String and using atoi

If there are non-number characters in a string and you call atoi [I'm assuming wtoi will do the same]. How will atoi treat the string?
Lets say for an example I have the following strings:
"20234543"
"232B"
"B"
I'm sure that 1 will return the integer 20234543. What I'm curious is if 2 will return "232." [Thats what I need to solve my problem]. Also 3 should not return a value. Are these beliefs false? Also... if 2 does act as I believe, how does it handle the e character at the end of the string? [Thats typically used in exponential notation]
You can test this sort of thing yourself. I copied the code from the Cplusplus reference site. It looks like your intuition about the first two examples are correct, but the third example returns '0'. 'E' and 'e' are treated just like 'B' is in the second example also.
So the rules are
On success, the function returns the converted integral number as an int value.
If no valid conversion could be performed, a zero value is returned.
If the correct value is out of the range of representable values, INT_MAX or INT_MIN is returned.
According to the standard, "The functions atof, atoi, atol, and atoll need not affect the value of the integer expression errno on an error. If the value of the result cannot be represented, the behavior is undefined." (7.20.1, Numeric conversion functions in C99).
So, technically, anything could happen. Even for the first case, since INT_MAX is guaranteed to be at least 32767, and since 20234543 is greater than that, it could fail as well.
For better error checking, use strtol:
const char *s = "232B";
char *eptr;
long value = strtol(s, &eptr, 10); /* 10 is the base */
/* now, value is 232, eptr points to "B" */
s = "20234543";
value = strtol(s, &eptr, 10);
s = "123456789012345";
value = strtol(s, &eptr, 10);
/* If there was no overflow, value will contain 123456789012345,
otherwise, value will contain LONG_MAX and errno will be ERANGE */
If you need to parse numbers with "e" in them (exponential notation), then you should use strtod. Of course, such numbers are floating-point, and strtod returns double. If you want to make an integer out of it, you can do a conversion after checking for the correct range.
atoi reads digits from the buffer until it can't any more. It stops when it encounters any character that isn't a digit, except whitespace (which it skips) or a '+' or a '-' before it has seen any digits (which it uses to select the appropriate sign for the result). It returns 0 if it saw no digits.
So to answer your specific questions: 1 returns 20234543. 2 returns 232. 3 returns 0. The character 'e' is not whitespace, a digit, '+' or '-' so atoi stops and returns if it encounters that character.
See also here.
If atoi encounters a non-number character, it returns the number formed up until that point.
I tried using atoi() in a project, but it wouldn't work if there were any non-digit characters in the mix and they came before the digit characters - it'll return zero. It seems to not mind if they come after the digits, for whatever reason.
Here's a pretty bare bones string to int converter I wrote up that doesn't seem to have that problem (bare bones in that it doesn't work with negative numbers and it doesn't incorporate any error handling, but it might be helpful in specific instances). Hopefully it might be helpful.
int stringToInt(std::string newIntString)
{
unsigned int dataElement = 0;
unsigned int i = 0;
while ( i < newIntString.length())
{
if (newIntString[i]>=48 && newIntString[i]<=57)
{
dataElement += static_cast<unsigned int>(newIntString[i]-'0')*(pow(10,newIntString.length()-(i+1)));
}
i++;
}
return dataElement;
}
I blamed myself up to this atoi-function behaviour when I was learning-approached coding program with function calculating integer factorial result given input parameter by launching command line parameter.
atoi-function returns 0 if value is something else than numeral value and "3asdf" returns 3. C -language handles command line input parameters in char -array pointer variable as we all already know.
I was told that down at the book "Linux Hater's Handbook" there's some discussion appealing for computer geeks doesn't really like atoi-function, it's kind of foolish in reason that there's no way to check validity of given input type.
Some guy asked me why I don't brother to use strtol -function located on stdlib.h -library and he gave me an example attached to my factorial-calculating recursive method but I don't care about factorial result is bigger than integer primary type value -range, out of ranged (too large base number). It will result in negative values in my program.
I solved my problem with atoi-function first checking if given user's input parameter is truly numerical value and if that matches, after then I calculate the factorial value.
Using isdigit() -function located on chtype.h -library is following:
int checkInput(char *str[]) {
for (int x = 0; x < strlen(*str); ++x)
{
if (!isdigit(*str[x])) return 1;
}
return 0;
}
My forum-pal down in other Linux programming forum told me that if I would use strtol I could handle the situations with out of ranged values or even parse signed int to unsigned long -type meaning -0 and other negative values are not accepted.
It's important upper on my code check if charachter is not numerical value. Negotation way to check this one the function returns failed results when first numerical value comes next to check in string. (or char array in C)
Writing simple code and looking to see what it does is magical and illuminating.
On point #3, it won't return "nothing." It can't. It'll return something, but that something won't be useful to you.
http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/
On success, the function returns the converted integral number as an int value.
If no valid conversion could be performed, a zero value is returned.
If the correct value is out of the range of representable values, INT_MAX or INT_MIN is returned.

Strange C++ boolean casting behaviour (true!=true)

Just read on an internal university thread:
#include <iostream>
using namespace std;
union zt
{
bool b;
int i;
};
int main()
{
zt w;
bool a,b;
a=1;
b=2;
cerr<<(bool)2<<static_cast<bool>(2)<<endl; //11
cerr<<a<<b<<(a==b)<<endl; //111
w.i=2;
int q=w.b;
cerr<<(bool)q<<q<<w.b<<((bool)((int)w.b))<<w.i<<(w.b==a)<<endl; //122220
cerr<<((w.b==a)?'T':'F')<<endl; //F
}
So a,b and w.b are all declared as bool. a is assigned 1, b is assigned 2, and the internal representation of w.b is changed to 2 (using a union).
This way all of a,b and w.b will be true, but a and w.b won't be equal, so this might mean that the universe is broken (true!=true)
I know this problem is more theoretical than practical (a sake programmer doesn't want to change the internal representation of a bool), but here are the questions:
Is this okay? (this was tested with g++ 4.3.3) I mean, should the compiler be aware that during boolean comparison any non-zero value might mean true?
Do you know any case where this corner case might become a real issue? (For example while loading binary data from a stream)
EDIT:
Three things:
bool and int have different sizes, that's okay. But what if I use char instead of int. Or when sizeof(bool)==sizeof(int)?
Please give answer to the two questions I asked if possible. I'm actually interested in answers to the second questions too, because in my honest opinion, in embedded systems (which might be 8bit systems) this might be a real problem (or not).
New question: Is this really undefined behavior? If yes, why? If not, why? Aren't there any assumptions on the boolean comparison operators in the specs?
If you read a member of a union that is a different member than the last member which was written then you get undefined behaviour. Writing an int member and then reading the union's bool member could cause anything to happen at any subsequent point in the program.
The only exception is where the unions is a union of structs and all the structs contain a common initial sequence, in which case the common sequence may be read.
Is this okay? (this was tested with g++ 4.3.3) I mean, should the compiler be aware that during boolean comparison any non-zero value might mean true?
Any integer value that is non zero (or pointer that is non NULL) represents true.
But when comparing integers and bool the bool is converted to int before comparison.
Do you know any case where this corner case might become a real issue? (For example while binary loading of data from a stream)
It is always a real issue.
Is this okay?
I don't know whether the specs specify anything about this. A compiler might always create a code like this: ((a!=0) && (b!=0)) || ((a==0) && (b==0)) when comparing two booleans, although this might decrease performance.
In my opinion this is not a bug, but an undefined behaviour. Although I think that every implementor should tell the users how boolean comparisons are made in their implementation.
If we go by your last code sample both a and b are bool and set to true by assigning 1 and 2 respectfully (Noe the 1 and 2 disappear they are now just true).
So breaking down your expression:
a!=0 // true (a converted to 1 because of auto-type conversion)
b!=0 // true (b converted to 1 because of auto-type conversion)
((a!=0) && (b!=0)) => (true && true) // true ( no conversion done)
a==0 // false (a converted to 1 because of auto-type conversion)
b==0 // false (b converted to 1 because of auto-type conversion)
((a==0) && (b==0)) => (false && false) // false ( no conversion done)
((a!=0) && (b!=0)) || ((a==0) && (b==0)) => (true || false) => true
So I would always expect the above expression to be well defined and always true.
But I am not sure how this applies to your original question. When assigning an integer to a bool the integer is converted to bool (as described several times). The actual representation of true is not defined by the standard and could be any bit pattern that fits in an bool (You may not assume any particular bit pattern).
When comparing the bool to int the bool is converted into an int first then compared.
Any real-world case
The only thing that pops in my mind, if someone reads binary data from a file into a struct, that have bool members. The problem might rise, if the file was made with an other program that has written 2 instead of 1 into the place of the bool (maybe because it was written in another programming language).
But this might mean bad programming practice.
Writing data in a binary format is non portable without knowledge.
There are problems with the size of each object.
There are problems with representation:
Integers (have endianess)
Float (Representation undefined ((usually depends on the underlying hardware))
Bool (Binary representation is undefined by the standard)
Struct (Padding between members may differ)
With all these you need to know the underlying hardware and the compiler. Different compilers or different versions of the compiler or even a compiler with different optimization flags may have different behaviors for all the above.
The problem with Union
struct X
{
int a;
bool b;
};
As people mention writing to 'a' and then reading from 'b' is undefined.
Why: because we do not know how 'a' or 'b' is represented on this hardware. Writing to 'a' will fill out the bits in 'a' but how does that reflect on the bits in 'b'. If your system used 1 byte bool and 4 byte int with lowest byte in low memory highest byte in the high memory then writing 1 to 'a' will put 1 in 'b'. But then how does your implementation represent a bool? Is true represented by 1 or 255? What happens if you put a 1 in 'b' and for all other uses of true it is using 255?
So unless you understand both your hardware and your compiler the behavior will be unexpected.
Thus these uses are undefined but not disallowed by the standard. The reason they are allowed is that you may have done the research and found that on your system with this particular compiler you can do some freeky optimization by making these assumptions. But be warned any changes in the assumptions will break your code.
Also when comparing two types the compiler will do some auto-conversions before comparison, remember the two types are converted into the same type before comparison. For comparison between integers and bool the bool is converted into an integer and then compared against the other integer (the conversion converts false to 0 and true to 1). If the objects being converted are both bool then no conversion is required and the comparison is done using boolean logic.
Normally, when assigning an arbitrary value to a bool the compiler will convert it for you:
int x = 5;
bool z = x; // automatic conversion here
The equivalent code generated by the compiler will look more like:
bool z = (x != 0) ? true : false;
However, the compiler will only do this conversion once. It would be unreasonable for it to assume that any nonzero bit pattern in a bool variable is equivalent to true, especially for doing logical operations like and. The resulting assembly code would be unwieldy.
Suffice to say that if you're using union data structures, you know what you're doing and you have the ability to confuse the compiler.
The boolean is one byte, and the integer is four bytes. When you assign 2 to the integer, the fourth byte has a value of 2, but the first byte has a value of 0. If you read the boolean out of the union, it's going to grab the first byte.
Edit: D'oh. As Oleg Zhylin points out, this only applies to a big-endian CPU. Thanks for the correction.
I believe what you're doing is called type punning:
http://en.wikipedia.org/wiki/Type_punning
Hmm strange, I am getting different output from codepad:
11
111
122222
T
The code also seems right to me, maybe it's a compiler bug?
See here
Just to write down my points of view:
Is this okay?
I don't know whether the specs specify anything about this. A compiler might always create a code like this: ((a!=0) && (b!=0)) || ((a==0) && (b==0)) when comparing two booleans, although this might decrease performance.
In my opinion this is not a bug, but an undefined behaviour. Although I think that every implementor should tell the users how boolean comparisons are made in their implementation.
Any real-world case
The only thing that pops in my mind, if someone reads binary data from a file into a struct, that have bool members. The problem might rise, if the file was made with an other program that has written 2 instead of 1 into the place of the bool (maybe because it was written in another programming language).
But this might mean bad programming practice.
One more: in embedded systems this bug might be a bigger problem, than on a "normal" system, because the programmers usually do more "bit-magic" to get the job done.
Addressing the questions posed, I think the behavior is ok and shouldn't be a problem in real world. As we don't have ^^ in C++ I would suggest !bool == !bool as a safe bool comparison technique.
This way every non-zero value in bool variable will be converted to zero and every zero is converted to some non-zero value, but most probably one and the same for any negation operation.