Do While loop doesn't repeat loop even if conditions where true - c++

size_t pos = 0;
int n;
char c;
string temp("x^3+4*x^)8");
do
{
pos = temp.find('^',pos);
/*code*/
pos++;
}while(pos <= temp.npos +1);
//if temp.find didn't find '^' it will return npos (2^32)
What it is supposed to do is find ^ in temp and return it's position to pos, do abit of code and increment pos, repeat the loop if the condition is true. Condition is true if pos <= temp.npos+1, i.e it will break from the loop if temp.find() didn't find any ^ in the string.
But when I debug, the debugger goes the the do loop once before exiting, even if the condition is true.
Edit1
What I know is npos = -1 but on my code, when I debug it, it gives me something else.

npos + 1 probably overflows (because I believe it should be something like MAX_UINT) and then it is (of course) smaller than anything.

npos is defined as size_t npos = -1;
npos + 1 causes overflow, and instead of 2^64 it will be zero.
I would suggest checking for pos < temp.length() instead if you want to go this way.
Fix:
Also, you should check for pos = temp.npos immediately after find and call break from cycle to prevent processing position when nothing is found.

npos is the biggest unsigned integer. npos + 1 is zero and pos >= 0. The loop will repeat if temp.find() returns index 0.
You can change your loop to
do {
pos = temp.find('^',pos);
/*code*/
pos++;
} while(pos != temp.npos);
since pos > temp.npos is never possible.

Related

C++ time limit exceeded when it doesn't even execute the function

While I was solving a problem in LeetCode, I found something very strange.
I have this line which I assume gives me a time limit exceeded error:
s.erase(i-k, k);
when I comment(//) this line, it doesn't show me time exceed error, but the strange part was, it has never executed even when i didn't comment it.
below is the entire code.
and Here is the problem link.
class Solution {
public:
string removeDuplicates(string s, int k) {
char prev = s[0];
int cnt = 1;
cnt = 1;
for(int i = 1; i < s.size() + 1; i++){
if(s[i] == prev){
cnt++;
} else {
if(cnt == k){
// when input is "abcd" it never comes to this scope
// which is impossible to run erase function.
s.erase(i-k, k);
i = 0;
}
if(i >= s.size()) break;
cnt = 1;
prev = s[i];
}
}
return s;
}
};
When Input is "abcd", it never even go to the if scope where 'erase' function is in.
Although 'erase' function never run, it still affect on the time complexity, and I can't get the reason.
Does anyone can explain this? or is this just problem of LeetCode?
Many online contest servers report Time Exceeding when program encounters critical error (coding bug) and/or crashes.
For example error of reading out of bounds of array. Or dereferencing bad (junk) pointers.
Why Time Exceeded. Because with critical error program can hang up and/or crash. Meaning it also doesn't deliver result in time.
So I think you have to debug your program to find all coding errors, not spending your time optimizing algorithm.
Regarding this line s.erase(i-k, k); - it may crash/hang-up when i < k, then you have negative value, which is not allowed by .erase() method. When you get for example i - k equal to -1 then size_t type (type of first argument of erase) will overflow (wrap around) to value 18446744073709551615 which is defnitely out of bounds, and out of memory border, hence your program may crash and/or hang. Also erase crashes when there is too many chars deleted, i.e. for erase s.erase(a, b) you have to watch that a + b <= s.size(), it is not controlled by erase function.
See documentation of erase method, and don't put negative values as arguments to this method. Check that your algorithm never has negative value i.e. never i < k when calling s.erase(i-k, k);, also never i-k + k > s.size(). To make sure there is no program crash you may do following:
int start = std::min(std::max(0, i-k), int(s.size()));
int num = std::min(k, std::max(0, int(s.size()) - start));
s.erase(start, num);

while greater than negative number not working

I have a very trivial piece of code that basically needs to count down from a certain number, and use that count as an index to an array.
auto bigSize = BigArray.size() - 1;
while(bigSize > -1) {
auto thing = arr[bigSize ];
bigSize--;
}
However the code never seems to hit anything inside the loop. I've also tried with a for loop:
auto bigSize = BigArray.size() - 1;
for(int i = bigSize ; i >= 0 && i < bigSize ; --i) {
auto thing = arr[i];
}
I feel like I'm doing something incorrect, but I can't seem to find it.
while(bigSize > -1) {
auto thing = arr[bigSize ];
bigSize--;
}
This will never stop. bigSize is unsigned which means it can't contain negative values. The moment bigSize is 0 and you try to decrement it it becomes std::numeric_limits<type>::max(). (underflow, not negative) So it'll keep on looping.
Either change your condition or make bigSize explicitly an int.
std::Container.size() always returns an unsigned number. An unsigned number will always be greater than a negative number, even if you underflow.

member function erase() not working in a loop

I'm programming a little game; but stringname.erase() seems to be not working in a 'for-loop' , I want to understand why, I have other alternatives, but I don't understand what's going on in the following code.
More explications of my situation (Important!):
guess is a char.
'tmgword' and 'word' are of type string, and: tmgword = word ;
what I understand from my code:
in the first time,the 'while'-loop verifies if there is 'guess' in the string 'tmpgword'.
That is true and the for-loop is working fine, the right character(guess) that verifies the if-condition is erased.
in the second time: the 'while'-loop verifies again if there is 'guess' in the string 'tmpgword'.
that is true, and hence we go into the 'for-loop' again; and then into the 'if'-block ( the right char is found ) but here erase() don't work, and we enter in an infinite loop.
when the program finds the right index using 'for-loop', I break, and I start the search from the beginning in case there are more occurrences of guess.
the problem is: the program finds 'guess' again but erase() won't delete it!
can someone explain please. Here is my code:
while (tmpgword.find(guess,0) != string::npos )
{
for (i = 0; i < word.size(); i++) // verify the input;
{
if (word[i] == guess)
{
encword[i] = word[i];//I don't think this line is important
tmpgword.erase(tmpgword.begin() + i);
break;
}
}
}
After you do the first erase, the character positions in tmpgword are not the same as in word.
string::find() returns the position of the element when it's found, so you can use that instead of looping through word.
size_t pos = 0;
while ((pos = tmpgword.find(guess, pos)) != string::npos) {
tmpgword.erase(pos, 1);
}
I've used pos as the starting position for each call to find() so it starts from where it just erased, rather than searching from the beginning each time through (there can't be any occurrences before that, because they've all been erased).

How to make a conditional comparing two values by their position in a vector

sort(stor);
for (int i = 0; i < stor.size(); ++i){
if (i != 0 && stor[i] == stor[i - 1]){ // is stor[i] a repeat?
if (repCheck[repCheck.size() - 1] == stor[i]){ // do we already know about this repeat? *program crashes when reaching this line*
++repCount[repCount.size() - 1]; // increment the last value in repCount
}
else {
repCheck.push_back(stor[i]); // store this new repeat at the end of repCheck
repCount.push_back(1); // start a new count for repetitions at the end of repCount
}
}
}
Program crashes upon reaching the second if statement, is there something inherently wrong about trying to compare values this way? Edited: for confusion about error messages.
The second if can fail if repCheck.size() is 0. Is this your case ?
You will probably want to change if (repCheck[repCheck.size() - 1] == stor[i]) into if (repCheck.size() > 0 && repCheck[repCheck.size() - 1] == stor[i])
Note that you can start your loop from i = 1 and then avoid the test i !=0 in the first if.

Finding all occurrences using rfind, flow challenges?

Following a c++ tutorial and teaching about find() the following code was implemented to search for all the "cat" occurrences in a string:
std::string input;
std::size_t i = 0, x_appearances = 0;
std::getline(std::cin,input);
for(i = input.find("cat",0); i != std::string::npos; i=input.find("cat", i))
{
++x_appearances;
++i; //Move past the last discovered instance to avoid finding the same string
}
Then the tutorial challenges the apprentice to change find() for rfind(), and that's where the problems came in, first I tried what seemed to be the obvious approach:
for(i = input.rfind("cat",input.length()); i != std::string::npos; i=input.rfind("cat", i))
{
++x_appearances;
--i; //Move past the last discovered instance to avoid finding the same string
}
but with this solution I fell into an infinite loop. Then I discovered that it was happening because the increment is performed before the condition check, and that the increment rfind() was always finding a match even with i==std::string::npos (if the match is on the beginning of the string, for example "cats"). My final solution came to be:
int n=input.length();
for(i = input.rfind("cat",input.length()); n>0 && i!=std::string::npos; i=input.rfind("cat", i))
{
++x_appearances;
n=i;
--i; //Move past the last discovered instance to avoid finding the same string
}
With n I can keep the track of the position in the string, and with it exit the for loop when the entire string had been searched.
So my question is: Is my approach correct? Did I need an extra variable or is there any other simpler way of doing this?
for(i = input.rfind("cat",input.length()); i != std::string::npos; i=input.rfind("cat", i))
{
++x_appearances;
--i; //Move past the last discovered instance to avoid finding the same string
}
The problem with the above is the --i inside the loop. Suppose the input string starts with "cat". Your algorithm will eventually find that "cat" with i being 0. Since you've declared i as a std::size_t, subtracting 1 from 0 results in the largest possible std::size_t. There's no warning, no overflow, no undefined behavior. This is exactly how unsigned integers must work, per the standard.
Somehow you need to handle this special case. You could use an auxiliary variable and a more convoluted test in your loop. An alternative is to keep your code simple and at the same time make it blatantly obvious you are explicitly handling this special case:
for (i = input.rfind("cat"); i != std::string::npos; i=input.rfind("cat", i-1))
{
++x_appearances;
// Finding "cat" at the start means we're done.
if (i == 0) {
break;
}
}
Note also that I've changed the loop statement a bit. The default value for pos is std::string::npos, which means search from the end of the string. There's no need for that second argument with the initializer. I also moved the --i into the update part of the for loop, changing input.rfind("cat",i) to input.rfind("cat",i-1). Since i is always positive at this point, there's no danger in subtracting one.