I have the following for each loop which compares several guids with each other.
stringc flanking_id = *flanking_it;
if (abzug) {
if (AppFrame::isValidPointer(&flanking_id)) {
if (AppFrame::isValidPointer(&abzug->guid)) {
if (flanking_id.size() > 0 && abzug->guid.size() > 0) {
if (flanking_id.size() >= abzug->guid.size()) {
if (flanking_id.equalsn(abzug->guid, abzug->guid.size())) {
return bauteil;
}
}
}
}
}
}
abzug-guid is an core::stringw which is an Irrlicht-Engine datatype.
isValidPointer calls a method which is containing the following two lines
BOOL result = somePointer != 0 && somePointer != NULL && somePointer != nullptr && somePointer != nil;
return result;
So it shouldn't be possible, that one of my guids is broken. But Xcode says there is a possible null pointer dereference in this line.
if (flanking_id.equalsn(abzug->guid, abzug->guid.size())) {
This is the warning...
Array access (via field 'array') results in a null pointer dereference (within a call to 'equalsn')
How to solve this hint?
EDIT: equalsn() from irrString.h by Irrlicht-Engine
bool equalsn(const string<T,TAlloc>& other, u32 n) const
{
u32 i;
for(i=0; i < n && array[i] && other[i]; ++i)
if (array[i] != other[i])
return false;
// if one (or both) of the strings was smaller then they
// are only equal if they have the same length
return (i == n) || (used == other.used);
}
Example on Ideone.com
int * p1 = 0;
int p2 = *p1;
cout << "&p2 != 0: " << (&p2 != 0) << endl;
cout << "*p1 = 1 : " << flush;
*p1 = 1;
cout << "ok" << endl;
Output:
Runtime error time: 0 memory: 3096 signal:11
&p2 != 0: 1
*p1 = 1 :
So, the check for valid pointer after the last one was dereferenced is useless. It should be
if (abzug) {
if (AppFrame::isValidPointer(flanking_it)) {
stringc flanking_id = *flanking_it;
//...
Concerning warning, I'm not sure what Xcode dislikes, but I suspect this lines
for(i=0; i < n && array[i] && other[i]; ++i) // line 1
if (array[i] != other[i]) // line 2
There is should be check in line 1 that index i is less then size of array. In case of n greater than source string length there will be error.
BTW, instead of 7 enclosed if-statements you can use
if (!abzug ||
!AppFrame::isValidPointer(&flanking_id) ||
!AppFrame::isValidPointer(&abzug->guid) ||
... {
return ...;
}
if (flanking_id.equalsn(abzug->guid, abzug->guid.size())) {
return bauteil;
}
Or if a return statement can not be used then
do {
if (!abzug ||
!AppFrame::isValidPointer(&flanking_id) ||
!AppFrame::isValidPointer(&abzug->guid) ||
... {
break;
}
if (flanking_id.equalsn(abzug->guid, abzug->guid.size())) {
return bauteil;
}
} while (0);
Related
I need to know if a number has a repeating digit using recursion and return 'yes' or 'no'. I am not allowed to use loops or arrays. This is what I've done untill now with 10 global variables and it works, but I think there is a better way.
#include <iostream>
using namespace std;
int counter0 = 0;
int counter1 = 0;
int counter2 = 0;
int counter3 = 0;
int counter4 = 0;
int counter5 = 0;
int counter6 = 0;
int counter7 = 0;
int counter8 = 0;
int counter9 = 0;
bool check(int k) {
int p = k % 10;;
if (k < 10) {
return false;
} else {
if (p == 0) {
counter0++;
} else if (p == 1) {
counter1++;
} else if (p == 2) {
counter2++;
} else if (p == 3) {
counter3++;
} else if (p == 4) {
counter4++;
} else if (p == 5) {
counter5++;
} else if (p == 6) {
counter6++;
} else if (p == 7) {
counter7++;
} else if (p == 8) {
counter8++;
} else if (p == 9) {
counter9++;
}
if(counter1>1 || counter2>1 || counter3>1 || counter4>1 || counter5>1 || counter6>1 || counter7>1 || counter8>1 || counter9>1)
{
return true;
}
k=k/10;
check(k);
}
}
int main() {
//cout << "Hello, World!" << std::endl;
int n;
cin >> n;
cout << (check(n) ? "yes" : "no") << endl;
//cout << n/10;
return 0;
}
#include <iostream>
using namespace std;
bool hasRepeatingDigit(int n, int mask)
{
// base case: if we have checked all the digits and didn't find any duplicates, return false
if (n == 0)
return false;
/*
p is the place of the last digit in n (n%10).
A digit can range from 0 to 9.
The place of 0 will be 1 << 0 which is 1.
The place of 1 will be 1 << 1 which is 2.
The place of 2 will be 1 << 2 which is 4.
...
...
The place of 9 will be 1 << 9 which is 512.
*/
int p = 1 << (n % 10);
// if place of p has already been marked then it's a duplicate
if (mask&p)
return true;
// otherwise scrap the last digit (n/10), mark place p and recurse on the remaining digits
return hasRepeatingDigit(n / 10, mask|p);
}
int main()
{
int n;
cin >> n;
cout << hasRepeatingDigit(n, 0) << endl;
}
Recursion problems always have a base case and an recursive case.
The base case is simple: k<11 has no repeated digits.
For the recursive case, k has repeated digits if either:
the lower two digits of k are equal, or
k/10 has repeated digits.
So:
bool check(int k) {
if (k < 11)
return false;
int digit = k % 10;
int next = k / 10;
int digit2 = next % 10;
if (digit == digit2)
return true;
else
return check(next);
// Or in one expression:
// return (digit == digit2) || check(next);
}
first, the code is incorrect...
if you enter n=11 it says 'no' but 1 repeated twice. you can fix it by changing the if statement from if(k < 10) to if(k == 0)
you can get down to the bits level but I can't see how much is useful...
in conclusion, this is the best you can do without arrays...
BUT: if you need to find if a digit repeated twice or more in a row the other answer is perfect
I have a string that needs to be check for a valid postfix expression.
A valid postfix string is 1 2 + but not 1 2+ since each character needs a space. Also, since it's a string, you can enter words, but they should return -1 for this function.
I have tried using vector array with strings and checking for valid ints, but when the user enters letters this obviously creates a problem.
string postfix = "1 2 +"; // valid
string postfix = "soemthing"; // error
string postfix = "1 2+" ; // error since there is no space.
if (!isdigit(postfix[0]))
return -1;
int t;
string line = "55 124 4 5";
std::vector <int> ints;
std::istringstream iss ( line, std::istringstream::in);
int main() {
while (iss >> t )
{
ints.push_back(t);
}
if (!digit(ints[0]) || !digit(ints[0]))
return -1;
}
~
From this post you can get the algorithm to check. In c++:
int isValid(string postfix) {
int l = postfix.size();
char c;
bool numStarted = false;
int counter = 0;
for (int i = 0; i < l; i++) {
c = postfix.at(i);
if (numStarted == true && c == ' ') {
numStarted = false;
} else if (numStarted == false && c == ' ') {
return -1;
} else if (c == '-' || c == '+' || c == '*' || c == '/') {
if (counter < 2 || numStarted) {
return -1;
}
counter--;
numStarted = true;
} else if (!isdigit(c)) {
return -1;
} else if (!numStarted && isdigit(c)) {
counter++;
numStarted = true;
}
}
return (counter == 1 ? 1 : -1);
}
To test this:
int main(int argc, char** argv) {
string postfix1 = "1 2 +"; // valid
string postfix2 = "soemthing"; // error
string postfix3 = "1 2+"; // error since there is no space.
cout << isValid(postfix1) << endl;
cout << isValid(postfix2) << endl;
cout << isValid(postfix3) << endl;
return 0;
}
output:
1
-1
-1
This problem which is similar to another that I solved here is giving me a wrong answer even though the algorithm works on the sample case.I have initialized all the variables this time and it works on a modified version of my previous algorithm.
#include <iostream>
int main() {
int n;
std::cin >> n;
int arr[n];
for (int i = 0; i <n ;++i) {
std::cin >> arr[i];
}
int four_count = 0, two_count = 0, three_long=0, one_long = 0 , max1_long = 0 ,max3_long = 0,a_depth = 0,max_depth = 0;
for (int i = 0; i < n; ++i) {
if (arr[i] == 3) {
if (arr[i+1] == 1) {
++a_depth;
if (a_depth > max_depth) {
max_depth = a_depth;
}
}
++four_count;
three_long += 2;
}
if (arr[i] == 1) {
if (arr[i+1] == 3) {
++a_depth;
if (a_depth > max_depth) {
max_depth = a_depth;
}
}
++two_count;
one_long += 2 ;
}
if (arr[i] == 2) {
if (arr[i+1] == 4 && i < n-1) {
--a_depth;
}
--two_count;
}
if (arr[i] == 4) {
if (arr[i+1] == 2 && i < n-1){
--a_depth;
}
--four_count;
}
if (four_count == 0 && two_count == 0) {
if (three_long >= one_long) {
if (three_long > max3_long) {
max3_long = three_long+one_long;
}
three_long = 0;
one_long = 0;
}
else {
if (one_long > max1_long) {
max1_long = one_long+three_long;
}
one_long = 0;
three_long = 0;
}
}
}
std::cout << max_depth*2 << " " << max1_long << " " << max3_long;
std::cout << "\n";
return 0;
}
Here is a link to the problem:
https://www.codechef.com/ZCOPRAC/problems/ZCO12003
In the below code:
for (int i = 0; i < n; ++i) {
if (arr[i] == 3) {
if (arr[i+1] == 1) {
when i reaches n-1, arr[i+1] becomes arr[n] resulting in an out-of-bounds memory access which will lead to undefined behaviour.
Let's say n is equal to 5. That means the array arr has the maximum index 4, because the first one is 0.
In your loop
for (int i = 0; i < n; ++i)
{ if (arr[i] == 3) {
if (arr[i+1] == 1) {
at some point i becomes n-1, so i == 4, then you try arr[i+1] meaning arr[5], which is out of bound.
Note that in the comment to P.Ws post, you tried if (arr[i+1] == 1 && i < n-1) to fix this. That won't work because there still is an arr[i+1] being executed. You could fix this by using
if(i < n-1) {
if(arr[i+1]) {
but that would mean an even deeper nesting of your ifs. You should probably rethink your approach to the given problem.
Edit: Are you sure you mean ++i and not i++?
I come from Python/Java land and I'm trying to tinker with making my own hashmap now in c++.
When I try to check to compare the locations of positions in the hash table to NULL (lines 6 and 11), I get the error:
invalid operands to binary expression ('value_type' (aka 'HashEntry') and 'long')"
I'm hoping someone can steer me in the direction of what I'm doing wrong and how I can fix it.
void CustomHash::insert(HashEntry entry) {
int k = entry.getKey();
int i = 0;
int hashVal = hash_One(k);
int temp = hashVal;
while (i < size && hashArray[temp] != NULL) {
i++;
temp = (hashVal + i*hash_Two(k)) % size;
}
if (hashArray[temp] == NULL) {
hashArray[temp] = entry;
}
else {
cout << "Failure" << endl;
}
}
Edit 1: hashArray declaration
CustomHash::CustomHash(int m) {
this->size = m;
this->hashArray = vector<HashEntry>();
}
Given,
hashArray is a vector<HashEntry> Object
hashArray[temp] evaluates to a HashEntry. You cannot compare a HashEntry with NULL.
Use a different strategy to check whether hasArray has any items whose key is equal to temp. I suggest using std::count_if.
while (i < size && std::count_if(hashArray.begin(), hashArray.end(),
[=temp](HashEntry const& e)
{ return (temp == e.getKey());}) > 0 )
{
i++;
temp = (hashVal + i*hash_Two(k)) % size;
}
A better solution, as suggested by #cdhowie, is to use std::any_of.
while (i < size && std::any_of(hashArray.begin(), hashArray.end(),
[=temp](HashEntry const& e)
{ return (temp == e.getKey());}) )
{
i++;
temp = (hashVal + i*hash_Two(k)) % size;
}
I have been running this and typing "12+" as the expression. When it gets to the while loop it gets stuck as if the condition is never met. I dont see why this is because right before the while loop "it" is equal to 2 so the loop should not even be used.
//array based stack implementation
class Stack
{
private:
int capacity; //max size of stack
int top; //index for top element
char *listArray; //array holding stack elements
public:
Stack (int size = 50){ //constructor
capacity = size;
top = 0;
listArray = new char[size];
}
~Stack() { delete [] listArray; } //destructor
void push(char it) { //Put "it" on stack
listArray[top++] = it;
}
char pop() { //pop top element
return listArray [--top];
}
char& topValue() const { //return top element
return listArray[top-1];
}
char& nextValue() const {//return second to top element
return listArray[top-2];
}
int length() const { return top; } //return length
};
int main()
{
string exp;
char it = ' ';
int count;
int push_length;
cout << "Enter an expression in postfix notation:\n";
cin >> exp;
cout << "The number of characters in your expression is " << exp.length() << ".\n";
Stack STK;
for(count= 0; count < exp.length() ;count++)
{
if (exp[count] == '+')
{
it = exp[count - 1];
cout << it << "\n";
while (it != 1 || it != 2 || it != 3 || it != 4 || it != 5 || it != 6 || it != 7 || it != 8 || it != 9 || it != 0)
{
cout << it << "\n";
it = exp[count--];
}
STK.push(it);
//cout << STK.topValue() << "\n";
it = exp[count --];
if (it == 1 || it == 2 || it == 3 || it == 4 || it == 5 || it == 6 || it == 7 || it == 8 || it == 9 || it == 0){
STK.push(it);
cout << it;
}
cout << STK.topValue() << "\n";
it = STK.topValue() + STK.nextValue();
STK.pop();
STK.pop();
STK.push(it);
cout << STK.topValue() << "\n";
}
}
cout << "The number of characters pushed into the stack is " << STK.length() << ".\n";
push_length = STK.length();
return(0);
}
As you mention, your while clause is always true.
while (it != 1 || it != 2 || it != 3 || it != 4 || it != 5 || it != 6 || it != 7 || it != 8 || it != 9 || it != 0)
it will always not be some of those numbers.
You could change every || to && in that statement, since that is likely what you meant.
And change 1 to '1', 2 to '2', and so on...
A clearer approach would be:
while ( !std::isdigit(it) )
http://en.cppreference.com/w/cpp/string/byte/isdigit