Why my function isn't executing i++? - c++

I am writing a get function within a class of an object oriented program, but the i++ in my code is not executing for some reason.
This is what is used in my .cpp file:
char MyString::Get(int i)
{
if( i = '\0')
{
exit(1);
}
else
{
return String[i];
}
}
This is what is called in the main.cpp file:
for(int i=0; i < String1.Length()+1; i++)
{
cout<< String1.Get(i)<<" ";
}
cout << endl;
This is the length method in the .cpp file for reference purposes:
int MyString::Length()
{
int counter(0);
while(String[counter] != '\0')
{
counter ++;
}
return (counter);
}
Also: String1 = Jello World
The output:
J J J J J J J J J J J J J

Well - probably cause of this. You assigned instead of compared. You assigned zero to i. That failed the 'if' test (it's zero), so exit did not get called and the rest of your routine ran with i == to zero.
if( i = '\0')
{
exit(1);
}

You haven't really shown enough code for someone to be able to figure out what your code is doing, but this looks incorrect:
if( i = '\0')
a single = symbol causes i to be assigned the value on the right-hand-side of the expression.
if( '\0' ) evaluates to if(false).

As others have pointed out, you're doing an assignment instead of a comparison, so the "comparison" will always be treated as false -- the result of a comparison is the assigned value, which in this case is 0.
Though it has never become overwhelmingly popular, there is a fairly simple technique to avoid this problem: when you're comparing to a constant, always put the constant on the left. This way, if you mis-type == as =, the code won't compile:
if ('\0' = i) // error: lvalue required (or something on that order).

Related

How can I iterate through the last element of the vector without going out of bounds?

The expected output is 1a1b1c but I only get 1a1b If I try putting '-1' next to input.size() in the for loop but that will just ignore the bug. What I'm looking for is that I want to be able to iterate through the last member of the string without going out of bounds.
std::string input = "abc";
for (unsigned int i = 0; i < input.size(); i++){
int counter = 1;
while(input.at(i) == input.at(i+1) && i < input.size()-1){
counter++;
i++;
}
number.push_back(counter);
character.push_back(input.at(i));
}
Few points for you to consdier:
1: for (unsigned int i = 0; i < input.size(); i++) specifically i++. This is a postfix operation meaning it returns i then increments the value of i. Not as big a deal here with integers but with iterators this can get very expensive as you create a copy of the iterator each time. Prefer to say what you mean / what you actually want, which is to increment i, not get a copy of i and increment i afterwards. So prefer ++i which only increments i and does not make a copy.
2: unsigned int i = 0 Firstly its better than using an int which has a signed -> unsigned conversaion every comparison with input.size() which returns a size_t. Secondly unsigned int is not guaranteed to be big enough to hold the size of the string and requires a promotion from (probably) 32 bit -> 64 bit unsigned to compare with size_t
3: cognitive complexity, nested loops which both mutate the same invariant (in this case i) makes the code more difficult to reason about and will ultimately lead to more bugs as code evolves over time. where possible only have one place where a loop invariant is mutated.
4: As pointed out by others the while loop while(input.at(i) == input.at(i+1) && i < input.size()-1) can exceed the size of the string and using the .at member function of string will throw for an out of bounds access. This can be simply resolved with point 3 by refactoring ther nested loop into a single loop.
5: Avoid so many calls to .at, we are in complete control of the index we use to index the string so you can use operator[] safely as long as we can guarantee i will always be a valid index which in this case i think you can.
6: i < input.size() using < when its not the check you want and its much more expensive than the check you actually want which is i != input.size(). Check out this trivial comparison in compiler explorer
Thankfully the fix from shadowranger Fixes your problem completely ie: while(i < s.size()-1 && s.at(i) == s.at(i+1)) However i would like to offer an alternitive with no nested loops to show you how to avoid my points 3,4, 5 and 6 :
void do_the_thing(std::string const& s) {
std::cout << "Considering: \"" + s + "\"\n";
if(s.empty()) {
return;
}
size_t const length = s.length(); // avoiding repeated calls to length which never changes in this case
if(length == 1) {
std::cout << "1" << s[0] << "\n";
return;
}
std::vector<unsigned> number;
std::vector<char> character;
// do the stuff your example did
char last = s[0];
unsigned same_count = 1;
for(size_t ii = 1; ii != length; ++ii) {
char const cur = s[ii];
if(cur == last) {
++same_count;
} else {
number.push_back(same_count);
character.push_back(last);
last = cur;
same_count = 1;
}
}
if(*s.rbegin() == last) {
number.push_back(same_count);
character.push_back(last);
}
// print the things or use them in some way
assert(number.size() == character.size());
size_t const out_len = character.size();
for(size_t ii = 0; ii != out_len; ++ii) {
std::cout << number[ii] << character[ii];
}
std::cout << "\n";
}

C++ trying multiple conditions in if statement with loop

I'm currently trying to create a sudoku solver in C++, but I have run into a slight problem. Instead of starting out with a 9x9 sudoku, I've started with a 4x4 one. For every square that can contain a number I am trying to get the possible numbers that square can hold into an array, e.g. if the possibilities in square 3 are 1 and 4,
for ( int i; i < 4; i++ ) {
cout << candidates[3][i];
}
would give me 1004. It is easily accessible when I need to code hard solving methods or a brute force solving method.
Here is the problem: I need to check whether a number occurs in any row, column or (2x2 or 3x3) box, and if it does not, add it to the candidates array. Here's what I thought of:
for ( int i = 0; i < 16; i++ ) {
for ( int j = 1; j < 5; j++ ) {
if ( for ( int k = 0; k < 4; k++ ) { allRows[getRow(i)][k] != j || allCols[getCol(i)] [k] != j || allBoxs[getBox(i)][k] != j}) {
candidates[i][j-1] = j;
}
}
}
The arrays allRows, allCols, allBoxs all contain the sudoku, only in such an order that they are easily accessible when they are needed. The functions getRow(), getCol() and getBox() return the number of the row, column or box (respectively, of course) the input number is in.
I tried to make it loop though everything in the same row, column or box as the number, to get all twelve checked by the if, and if they all passed, then I would add the number to the candidates array.
It came to me as no surprise that it returned an error when I tried to compile this. But I really don't want to write out twelve AND conditions in the if statement, or 27 when I upgrade to 9x9 sudoku, because:
I don't learn anything and
Where's the fun in that?
Can anyone help me / suggest another idea to do this without typing everything out?
I apologize if my inability to be concise hinders an answer to this question, I was only trying to provide all the details I thought maybe were necessary...
Condition of if should be an expression convertible to bool. it is not the case of for-statement.
You might do instead (assuming I correctly understood your condition):
for ( int i = 0; i < 16; i++ ) {
for ( int j = 1; j < 5; j++ ) {
bool b = false;
for ( int k = 0; k < 4; k++ ) {
if (allRows[getRow(i)][k] != j || allCols[getCol(i)][k] != j || allBoxs[getBox(i)][k] != j) {
b = true;
break;
}
}
if (b) {
candidates[i][j-1] = j;
}
}
}
or with helper function
template <typename Range, typename T>
bool contains(const Range& range, constT& value)
{
using std::begin;
using std::end;
return std::find(begin(range), end(range), value) != end(range);
}
// ...
for ( int i = 0; i < 16; i++ ) {
for ( int j = 1; j < 5; j++ ) {
if (!contains(allRows[getRow(i)], j)
|| !contains(allCols[getCol(i)], j)
|| !contains(allBoxs[getBox(i)], j)) {
candidates[i][j-1] = j;
}
}
}
Like you already noticed, adding an for-statement inside of the condition of the if doesn't work. There are several reasons for it, however, let me point out a few that cause confusion:
What if the for-loop wouldn't iterate? Would this result in true or false?
What if you have multiple iterations? Would we && or || the boolean values into it? And how about short cutting of those operators?
Long story short: Even if this would be considered to ever add to the standard, I expect it to be blocked thanks to the many edge cases.
So what does this mean? Is this impossible? Off course not, it's C++. Like already mentioned in the answer of #Jarod42 you can calculate a boolean and than do the if-statement. Or like both of us mentioned (me in the comments), you could move this into a function.
Personally, I've stepped away from remembering state about my for-loop like with this boolean. The main reason: This is hard to read. Every single time you read that code, you need to check what's actually happening.
Hence, I suggest to move this to a function. A function has a clear name and could even be tested separately to ensure it's behavior is correct.
So in this case, I would write something like:
template<typename T1, typename T2, typename T3>
auto checkForExistanceOf(int shouldExist, int locator, T1 &&allRows, T2 &&allCols, T3 &&allBoxs)
{
for ( int k = 0; k < 4; k++ )
{
if (allRows[getRow(locator)][k] != shouldExist)
return true;
if (allCols[getCol(locator)] [k] != shouldExist)
return true;
if (allBoxs[getBox(locator)][k] != shouldExist)
return true;
}
return false;
}
The code on caller side than becomes:
for ( int i = 0; i < 16; i++ )
{
for ( int j = 1; j < 5; j++ )
{
if (checkForExistanceOf(j, i, allRows, allCols, allBoxs))
{
candidates[i][j-1] = j;
}
}
}
For sure, my names ain't that good, as I don't know the exact purpose, nor would I suggest using a template as you know the actual types, though, this is the idea behind it.

Why does this code output different results for the same inputs?

I wrote a simple program to find the longest sub-string with distinct characters in a given string in C++. My code works for certain inputs, but doesn't for others. Moreover, it gives me different outputs for the same inputs. Where am I going wrong?
int main() {
int t;
cin >>t;
while(t--){
string s;
cin >> s;
int n = s.length();
int maxlen = 0;
for(int i = 0; i < n; i++){
int count = 0;
int arr[26] = {0};
bool isDist = true;
int j = i;
while(isDist){
if(arr[(int)s[j] - (int)'a'] == 0){
count++;
arr[(int)s[j] - (int)'a'] = 1;
j++;
} else {
isDist = false;
}
}
if(count > maxlen) maxlen = count;
}
cout << maxlen << endl;
}
return 0;
}
for the following input:
3
aewergrththy
aewergrththy
aewergrththy
My code outputs:
5
4
4
Any help is appreciated, Thank you!
The problem is that there is no check that j remains less than n, so you start checking characters beyond the end of your string, leading to in unpredictable results. Try
while (isDist && j < n)
That should help but I haven't checked the rest of your code for errors.
You could also consider using s.at(j) instead of s[j]. That at least results in predictable behaviour when going out of bounds, at throws an exception in that case.
The program has undefined behavior because you do not bounds-test when iterating over the string with j. You should modify the inner loop to test for j in addition to isDist:
while(isDist && j < n)
Without this, it's very easy for j to shoot past the end of the string as soon as all remaining characters in the string have not yet been encountered.
In this case, it will be when you process the character 'y' at the end of the string. After dealing with 'y', you'll advance j such that s[j] returns the string terminator. Now, you'll be accessing the array with arr[0 - 'y'] which of course is undefined behavior due to being a negative index.

My array is gettting an error because it's being defined as a singular integer

The point of this program is to output whether a series of digits (the number of digits undefined) is sorted or not (largest to smallest or smallest to largest).
I have defined my array in my function parameter, and I am trying to use a for loop to store the user's input, as long as it is above 0, in said array.
However, I am getting the error argument of type int is incompatible with parameter of type int*.
The exact error is the argument of type int is incompatible with parameter of type int*.
It is referring to line 22 and 23, these two;
isSorted(list[2000]); and
bool is = isSorted(list[2000]);.
I know this means my for loop is assigning a single value to my variable repeatedly from reading similar questions however I can not figure out how to fix this.
#include <iostream>
using namespace std;
bool isSorted(int list[]);
int main()
{
int i;
int list[2000];
int k = 0;
for (i = 0; i < 2000; i++)
{
int j;
while (j > 0)
{
cin >> j;
list[i] = j;
}
}
isSorted(list[2000]);
bool is = isSorted(list[2000]);
if (is == true)
cout << "sorted";
else
cout << "unsorted";
return 0;
}
bool isSorted(int list[])
{
int i = 0;
for (i = 0; i < 2000; i++)
{
if (list[i] > list[i + 1] || list[i] < list[i - 1])
{
return false;
}
else
return true;
}
}
I removed unused variable k.
Made 2000 parameterized (and set to 5 for testing).
In isSorted you are not allowed to return
true in the else as if your first element test would end in else you would return true immediately not testing other elements. But those later elements can be unsorted as well.
In isSorted you are not allowed to run the loop as for(i = 0; i < 2000; i++), because you add inside the for loop 1 to i and end up querying for i == 1999 list[2000], which is element number 2001 and not inside your array. This is correct instead: for (i = 0; i < 1999; i++). You also do not need to check into both directions.
You cannot call isSorted(list[2000]) as this would call is sorted with an int and not an int array as parameter.
You write int j without initializing it and then query while j > 0 before you cin << j. This is undefined behaviour, while most likely j will be zero, there is no guarantee. But most likely you never enter the while loop and never do cin
I renamed the isSorted as you just check in your example for ascending order. If you want to check for descending order you are welcome to train your programming skills and implementing this yourself.
Here is the code with the fixes:
#include <iostream>
using namespace std;
bool isSortedInAscendingOrder(int list[]);
const int size = 5; // Set this to 2000 again if you want
int main()
{
int i;
int list[size];
for (i = 0; i < size; i++)
{
int j = 0;
while(j <= 0)
{
cin >> j;
if(j <= 0)
cout << "rejected as equal or smaller zero" << endl;
}
list[i] = j;
}
if (isSortedInAscendingOrder(list))
cout << "sorted" << endl;
else
cout << "unsorted" << endl;
return 0;
}
bool isSortedInAscendingOrder(int list[])
{
for (int i = 0; i < size -1; i++)
{
if (list[i] > list[i + 1])
{
return false;
}
}
return true;
}
This is a definition of an array of 2000 integers.
int list[2000];
This is reading the 2000th entry in that array and undefined, because the highest legal index to access is 1999. Remember that the first legal index is 0.
list[2000]
So yes, from point of view of the compiler, the following only gives a single integer on top of being undefined behaviour (i.e. "evil").
isSorted(list[2000]);
You probably should change to this, in order to fix the immediate problem - and get quite close to what you probably want. It names the whole array as parameter. It will decay to a pointer to int (among other things loosing the information of size, but you hardcoded that inside the function; better change that by the way).
isSorted(list);
Delete the ignored first occurence (the one alone on a line), keep the second (the one assigning to a bool variable).
On the other hand, the logic of a your sorting check is flawed, it will often access outside the array, for indexes 0 and 1999. I.e. at the start and end of your loop. You need to loop over slightly less than the whole array and only use one of the two conditions.
I.e. do
for (i = 1; i < 2000; i++)
{
if (list[i] < list[i - 1])
/* ... */
The logic for checking ascending or descending sorting would have to be more complex. The question is not asking to fix that logic, so I stick with fixing the issues according to the original version (which did not mention two-way-sorting).
You actually did not ask about fixing the logic for that. But here is a hint:
Either use two loops, which you can break from as soon as you find a conflict, but do not return from the fuction immediatly.
Or use one loop and keep a flag of whether ascending or descending order has been broken. Then return true if either flag is still clear (or both, in case of all identical values) or return false if both are set.

Pointer Array Sorting Algorithm in C++

hoping I can get a little advice on a sorting method I made.
This is just a test for another program i am making and this test has a bug I can't figure out. The purpose of this code is to create a int pointer array and sort the pointers in that array by the contents of regular int array.
The bug is for my second for loop which doesn't allow me to use a j!=-1 therefore not allowing me to sort the first element of the array. Please help. Thanks!!
//create array
int c[8] = {3,1,5,7,8,2,6,4};
//create pointer array
int *newptr[8];
for(int k = 0; k<8; k++)
{
newptr[k] = &c[k];
}
//sort pointer array
for(int j = 0; j<8; j++)
{
cout << "test1\n\n";
cout << *newptr[j] << "and" << *newptr[j+1];
for(;*newptr[j] < *newptr[j+1] && j!=0; j--)
//using j!=-1 doesn't work which causes me to not be able to sort the first element
//in the array properly
{
cout<< "test2";
int *temp;
temp = newptr[j+1];
newptr[j+1] = newptr[j];
newptr[j] = temp;
}
}**
Order matters.
Change
for(;*newptr[j] < *newptr[j+1] && j!=0; j--)
to:
for(; j != -1 && *newptr[j] < *newptr[j+1]; j--)
Presumably the bug is something that causes the code to crash. This happens because the expression in the for loop is evaluated left-to-right. So *newptr[j] is evaluated before checking if j != -1. So it's conceivable that, at some point, j is equal to -1 when *newptr[j] is evaluated, which is illegal.
Changing the order does make a difference for a second reason: short-circuit evaluation.
When evaluating two an expression made of two conditions A and B, C++ does not always need to evaluate both conditions.
For example in the statement
if (A && B) {
//do something
}
if A is evaluated to be false, then obviously A && B cannot evaluate to true regardless of what B evaluates to. So B's value is never even checked. So in your case, in the expression
j != -1 && *newptr[j] < *newptr[j+1]
if j != -1 is false, C++ will not need to evaluate the rest of the expression in order to know that the whole expression is false. So *newptr[j] never happens and you don't get the bug.
As pointed out by maditya the problem is that the expression tries to access an invalid index before checking the index itself but I see the question is tagged C++. Do you have any explicit reason to not use STL?
struct sorter {
bool operator() (const int* i, const int* j) { return (*i<*j);}
};
int c[8] = {3,1,5,7,8,2,6,4};
int *newptr[8];
for(int k = 0; k<8; k++)
newptr[k] = &c[k];
std::sort(newptr, newptr+8, sorter());
or even shorter in C++11:
int c[8] = {3,1,5,7,8,2,6,4};
int *newptr[8];
for(int k = 0; k<8; k++)
newptr[k] = &c[k];
std::sort(newptr, newptr+8, [](const int *i, const int *j){return *i < *j;});