Weird result with C strings - c++

I expect "match!" when the n2 tail is the same that the n1 tail, otherwise, "do not match!".
Example of "match!": n1 = 123456 and n2 = 3456.
The problem is when I enter, for example, n1 = "45" and n2 = "645". It should not match, but the output is "match!".
bool different_tail = false;
char n1[11], n2[11];
cin >> n1 >> n2;
for(int i = strlen(n1)-strlen(n2); i < strlen(n1); i++){
if(i < 0 || n1[i] != n2[i-(strlen(n1)-strlen(n2))]){
different_tail = true;
break;
}
}
if(different_tail)
cout << "does not match!" << endl;
else
cout << "match!" << endl;
I don't want to use other ways to solve the problem (like, strcmp, etc...), I want to understand what's happening.

What happens is that with n1 being 45 and n2 being 645, the loop variable i will start at -1, i.e. it is negative.
However, strlen yields an unsigned value (a value of type size_t). When comparing a signed with an unsigned value (as you do in the expression i < strlen(n1)), the signed value is converted to an unsigned value. Since it's negative, this causes an underflow, so i is a very large value -- larger than strlen(n1).
You can observe the same effect with e.g.
int i = -1;
size_t x = 5;
if (i < x) {
cout << "yes\n";
} else {
cout << "no\n";
}
This program prints no.
You can avoid your issue by casting the return value of strlen, i.e. change your loop condition to
i < static_cast<int>(strlen(n1))
This question (and the accompanying answers) provide a more in-depth discussion of this topic.

Look at this line:
for(int i = strlen(n1)-strlen(n2); i < strlen(n1); i++){
here i is an int whereas strlen(n1) is an size_t(an unsigned integer type). Performing "less than" operator between signed and unsigned type will convert all operands to unsigned types, in this case unsigned(i) becomes a very large integer, so the for loop is never executed.
BTW, it's not a good practice to use strlen in for loop, since strlen is an expensive function and will be called at every iteration. You can store strlen result in an variable and use the variable instead.

Related

Why logical operation is not working properly if i use string::size()

string s;
cin >>s ; //input string is: a
int i=1;
if(i < s.size()-3 ) cout <<"Yes"<<endl;
else cout << "No"<<endl;
If the input string is a then output should be No but compiler is showing Yes.
int i = 1;
int len = s.size()-3;
if(i < len ) cout <<"Yes"<<endl;
else cout << "No"<<endl;
If I use the len variable then it is working fine. Now the output is showing No.
s.size() returns an unsigned type.
Since s.size() is 1 in your example, unsigned(1)-3 will wrap to a very large positive value. Thus:
int i=1;
if(i < s.size()-3)
compares a signed i to an unsigned value, and so will implicitly convert the value of i to unsigned and evaluate the if as true since 1 is less than that large positive value.
Whereas:
int len = s.size()-3;
will convert the large unsigned positive value into a signed negative value, thus:
int i=1;
if(i < len)
compares two signed values, and will evaluate the if as false since 1 is not less than a negative value.
s.size() returns an unsigned int, so if s.size() < 3 then s.size() - 3 becomes very big positive integer. So it can be possible.

Why does results are different when relational operators means the same?

For clarification, let's consider the following program:
#include <iostream>
int main(void) {
short int i; // declaration
short int value;
short int sum;
i = value = sum = 0; // initialization
std::cout << "Enter a value: ";
std::cin >> value;
while (i != value) { // ### here's the confusion ###
sum += i;
i++;
}
std::cout << "Total sum: " << sum << std::endl;
return 0;
}
Look at the while (i != value), when this expression is given, the results shows Total sum: 45 whereas if we put while (i <= value), it shows Total sum: 55. (Input's given 10 for example)
Here, the confusion is, when should we use != and <= or >= operations in loops, any specific condition?
According to TutorialsPoint's Operators Reference
it tells that != (returns true used when two operands are unequal).
<= (returns true when used when we need to ensure if the first operand is lesser than or equal to second).
It was expected to get no difference in output, but something's misunderstood.
This while loop
while (i != value)
does not include the iteration when i is equal to value because in this case the condition i != value evaluates to false.
This while loop
while (i <= value)
includes the iteration when i is equal to value because in this case the condition i <= value evaluates to true.
In fact the first condition can be rewritten the following way (provided that initially i is less than value)
while ( i < value )
Now compare it with the condition in the second loop that in turn can be rewritten like
while ( i < value || i == value )
That is you have two different conditions.
With
while( i <= value)
the last iteration is with i == value. With
while ( i != value)
The body of the loop will not be executed when i == value. That is the reason you observe the difference.
This is a good chance to learn how to use a debugger. And/Or realize that your example is already too complicated to directly see what is going on. You would have spotted the difference more easily with
int i = 0;
int value = 5;
while ( i != value) {
std::cout << i << " ";
}
i = 0;
while ( i <= value) {
std::cout << i << " ";
}

C++ - Digitwise addition with carryover for arbitrary unsigned ints - running into memory problems [duplicate]

I have made some research on Stackoverflow about reverse for loops in C++ that use an unsigned integer instead of a signed one. But I still do NOT understand why there is a problem (see Unsigned int reverse iteration with for loops). Why the following code will yield a segmentation fault?
#include <vector>
#include <iostream>
using namespace std;
int main(void)
{
vector<double> x(10);
for (unsigned int i = 9; i >= 0; i--)
{
cout << "i= " << i << endl;
x[i] = 1.0;
}
cout << "x0= " << x[0] << endl;
return 0;
}
I understand that the problem is when the index i will be equal to zero, because there is something like an overflow. But I think an unsigned integer is allowed to take the zero value, isn't it? Now if I replace it with a signed integer, there is absolutely no problem.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
Thank you very much!
The problem here is that an unsigned integer is never negative.
Therefore, the loop-test:
i >= 0
will always be true. Thus you get an infinite loop.
When it drops below zero, it wraps around to the largest value unsigned value.
Thus, you will also be accessing x[i] out-of-bounds.
This is not a problem for signed integers because it will simply go negative and thus fail i >= 0.
Thus, if you want to use unsigned integers, you can try one of the following possibilities:
for (unsigned int i = 9; i-- != 0; )
and
for (unsigned int i = 9; i != -1; i--)
These two were suggested by GManNickG and AndreyT from the comments.
And here's my original 3 versions:
for (unsigned int i = 9; i != (unsigned)0 - 1; i--)
or
for (unsigned int i = 9; i != ~(unsigned)0; i--)
or
for (unsigned int i = 9; i != UINT_MAX; i--)
The problem is, your loop allows i to be as low as zero and only expects to exit the loop if i is less than 0. Since i is unsigned, it can never be less than 0. It rolls over to 2^32-1. That is greater than the size of your vector and so results in a segfault.
Whatever the value of unsigned int i it is always true that i >= 0 so your for loop never ends.
In other words, if at some point i is 0 and you decrement it, it still stays non-negative, because it contains then a huge number, probably 4294967295 (that is 232-1).
The problem is here:
for (unsigned int i = 9; i >= 0; i--)
You are starting with a value of 9 for an unsigned int and your exit definition is i >= 0 and this will be always true. (unsigned int will never be negative!!!). Because of this your loop will start over (endless loop, because i=0 then -1 goes max uint).
As you said a decrease of an unsigned below zero, which happens right after the last step of the loop, creates an overflow, the number wraps around to its maximum value and thus we end up with an infinite loop.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
My preferred method for a reverse loop with an index is this:
for (unsigned int i = 9; i > 0; --i) {
cout << "i= " << x[i - 1] << endl;
}
and that is why because it maps most closely to the normal loop equivalent:
for (unsigned int i = 0; i < 9; ++i) {
cout << "i= " << x[i] << endl;
}
If then you need to access the indexed element multiple times and you don't want to continuously write [i - 1], you can add something like this as the first line in the loop:
auto& my_element = my_vector[i - 1];

What is the use of "and N" in this code?

C++ Code:
#include<iostream>
using namespace std;
int main()
{
int N;
cin>>N;
int *A = new int[N];
int i=0;
for(i=0;i<N;i++)
cin>>A[i];
while(cout<<A[--N]<<' ' and N);
delete[] A;
return 0;
}
Print the integers of the array in the reverse order in a single line separated by a space.
Does anyone know what is "and N" do in cout statement?
It's a cryptic way of writing:
while( (cout<<A[--N]<<' ') and (N != 0) );
// output is successful and N is not equal to zero.
It could be written more clearly as:
for ( ; N != 0; --N)
{
cout << A[N-1] << ' ';
}
Since it's theoretically possible for N to be negative, it will be better to use:
for ( ; N > 0; --N)
{
cout << A[N-1] << ' ';
}
N is an integer variable, value of type int can be implicitly converted to bool (non zero becomes true and zero becomes false). So the expression basically sais execute when result of operator<< converted to bool is true and N is not equal to zero. Logically this code
while(cout<<A[--N]<<' ' and N);
is equal to:
do {
bool b1 = cout<<A[--N]<<' ';
bool b2 = N;
} while( b1 and b2 );
actual code is a little different due to short circuit but that differences are unimportant in this case.
The part and N that can be also written like && N of the while statement
while(cout<<A[--N]<<' ' and N);
that as it has been pointed out can be rewritten like
while(cout<<A[--N]<<' ' && N != 0);
checks that N that is being decreased (A[--N]) in each iteration of the loop is not equal to 0.
So the loop outputs elements okf the array in the reverse order.
The word and is a so-called alternative token for the primary token &&.
It is just a way of writing the code by some programmers.
It is actually written as
while( (cout<<A[--N]<<' ') and (N != 0) );
Basically 'and' operator returns true when both operands are non zero values.
So cout will give number of characters it printed which will be non zero in this case and until the value of N becomes zero your loop will be execute.

Unsigned integers in C++ for loops

I have made some research on Stackoverflow about reverse for loops in C++ that use an unsigned integer instead of a signed one. But I still do NOT understand why there is a problem (see Unsigned int reverse iteration with for loops). Why the following code will yield a segmentation fault?
#include <vector>
#include <iostream>
using namespace std;
int main(void)
{
vector<double> x(10);
for (unsigned int i = 9; i >= 0; i--)
{
cout << "i= " << i << endl;
x[i] = 1.0;
}
cout << "x0= " << x[0] << endl;
return 0;
}
I understand that the problem is when the index i will be equal to zero, because there is something like an overflow. But I think an unsigned integer is allowed to take the zero value, isn't it? Now if I replace it with a signed integer, there is absolutely no problem.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
Thank you very much!
The problem here is that an unsigned integer is never negative.
Therefore, the loop-test:
i >= 0
will always be true. Thus you get an infinite loop.
When it drops below zero, it wraps around to the largest value unsigned value.
Thus, you will also be accessing x[i] out-of-bounds.
This is not a problem for signed integers because it will simply go negative and thus fail i >= 0.
Thus, if you want to use unsigned integers, you can try one of the following possibilities:
for (unsigned int i = 9; i-- != 0; )
and
for (unsigned int i = 9; i != -1; i--)
These two were suggested by GManNickG and AndreyT from the comments.
And here's my original 3 versions:
for (unsigned int i = 9; i != (unsigned)0 - 1; i--)
or
for (unsigned int i = 9; i != ~(unsigned)0; i--)
or
for (unsigned int i = 9; i != UINT_MAX; i--)
The problem is, your loop allows i to be as low as zero and only expects to exit the loop if i is less than 0. Since i is unsigned, it can never be less than 0. It rolls over to 2^32-1. That is greater than the size of your vector and so results in a segfault.
Whatever the value of unsigned int i it is always true that i >= 0 so your for loop never ends.
In other words, if at some point i is 0 and you decrement it, it still stays non-negative, because it contains then a huge number, probably 4294967295 (that is 232-1).
The problem is here:
for (unsigned int i = 9; i >= 0; i--)
You are starting with a value of 9 for an unsigned int and your exit definition is i >= 0 and this will be always true. (unsigned int will never be negative!!!). Because of this your loop will start over (endless loop, because i=0 then -1 goes max uint).
As you said a decrease of an unsigned below zero, which happens right after the last step of the loop, creates an overflow, the number wraps around to its maximum value and thus we end up with an infinite loop.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
My preferred method for a reverse loop with an index is this:
for (unsigned int i = 9; i > 0; --i) {
cout << "i= " << x[i - 1] << endl;
}
and that is why because it maps most closely to the normal loop equivalent:
for (unsigned int i = 0; i < 9; ++i) {
cout << "i= " << x[i] << endl;
}
If then you need to access the indexed element multiple times and you don't want to continuously write [i - 1], you can add something like this as the first line in the loop:
auto& my_element = my_vector[i - 1];