how to fix "comparison between pointer and integer" error in C++? - c++

I am trying to write a program that takes in 2 string inputs and assigns a numeric value to each letter in the string input. The program then multiples the numeric values assigned to the letters in the string inputs and sees if the product of the values (mod 47) of both inputs are equal. If they are equal, then the program must output "yes" if not, then it must output "NO".
I am using a brute force method, so please feel free to suggest more efficient methods and also how to implement them. I have reached a point where my IDE only gives several warnings, but no errors. However when I run the program, I get an illegal instruction, which is essentially because of a particular function, which I will show later.
I WOULD PREFER THAT THE SOLUTIONS TO MY QUESTION DON'T INCLUDE ANY EXTRA CLASS LIBRARIES AND FILES.
THANK YOU ;)
I've tried using a brute force method e.g in this long function:
This takes in values from a function of return type int which assigns the numeric value to the 6 letter input, and returns them to a variable of return type bool, which finds and compares the final product of the two strings before returning a value of type bool. I've used the brute force method of comparing each individual letter of the string to a letter and assigning a value. I am quite sure that the first function isn't right, although I don't know how to fix it.
int parse(const char * x)
{
if (x == "A")
{
return 1;
}
if (x == "B")
{
return 2;
}
if (x == "C")
{
return 3;
}
if (x == "D")
{
return 4;
}
if (x == "E")
{
return 5;
}
if (x == "F")
{
return 6;
}
if (x == "G")
{
return 7;
}
if (x == "H")
{
return 8;
}
if (x == "I")
{
return 9;
}
if (x == "J")
{
return 10;
}
if (x == "K")
{
return 11;
}
if (x == "L")
{
return 12;
}
if (x == "M")
{
return 13;
}
if (x == "N")
{
return 14;
}
if (x == "O")
{
return 15;
}
if (x == "P")
{
return 16;
}
if (x == "Q")
{
return 17;
}
if (x == "R")
{
return 18;
}
if (x == "S")
{
return 19;
}
if (x == "T")
{
return 20;
}
if (x == "U")
{
return 21;
}
if (x == "V")
{
return 22;
}
if (x == "W")
{
return 23;
}
if (x == "X")
{
return 24;
}
if (x == "Y")
{
return 25;
}
if (x == "Z")
{
return 26;
}
}
bool returnfunc(std::string & GROUP, std::string & k)
{
const char A = GROUP[0];
const char B = GROUP[1];
const char C = GROUP[2];
const char D = GROUP[3];
const char E = GROUP[4];
const char F = GROUP[5];
int xet = parse(&A);
int r = parse(&B);
int m = parse(&C);
int z = parse(&D);
int h = parse(&E);
int j = parse(&F);
double mu = (xet * r * m * z * h * j) % 47;
const char G = k[0];
const char H = k[1];
const char I = k[2];
const char J = k[3];
const char K = k[4];
const char L = k[5];
int w = parse(&G);
int x = parse(&H);
int y = parse(&I);
int a = parse(&J);
int b = parse(&K);
int c = parse(&L);
double fin = (w * x * y * a * b * c) % 47;
{
if (mu == fin)
{
return true;
}
else
{
return false;
}
}
}
/*I expected the program to run but it didn't and I don't understand
why.*/

This is wrong
if (x=="A")
because it compares two pointers for pointer equality. It does not compare what those pointers are pointing at (which is what you want to do).
Here's a simpler version of your code that keeps the same structure but does not involve any pointers (for some reason newbies love pointers, given how difficult they are I've never understood why).
int parse(char x)
{
if (x == 'A')
return 1;
if (x == 'B')
return 2;
// etc etc
}
Then
int xet = parse(A);
int r = parse(B);
// etc etc
PS, the more consise way to write your parse function would be to use a lookup table and a loop
int parse(char x)
{
const char* table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i = 0; i < 26; ++i)
if (x == table[i])
return i + 1;
return 0; // error return
}

int parse(const char * x) {
if (x == "A")
x is a const char* and "A" is a const char* but they will not be equal even if they point at C strings with the same characters since the comparison compares the addresses of the C strings, not the contents.
Also, if your parse function does not find a match it will leave the function without returning a value which is Undefined Behaviour.
Try this instead:
int parse(char x) {
if(x >= 'A' && x <= 'Z') return x - 'A' + 1;
else return 0;
}
And call parse with the char itself as an argument (instead of a pointer to it):
const char A = GROUP[0];
int xet = parse(A);

It's hard to answer this mostly because of this part of your question:
I have reached a point where my IDE only gives several warnings, but no errors.
There may be a warning that we don't know about that might be part of your problem. However, I'm going to take a stab anyway at a couple of things that are wrong.
So, first is this line right here:
int parse ( const char * x)
Now in and of itself, this isn't bad, except it's coupled with something like this:
if(x=="A")
{
return 1;
}
That is all sort of bad. x is a pointer. That means that the value store in x is an address. That means you are comparing the c string "A" to an address. That's not usually a good thing to do.
What you want is probably this instead:
if(*x == "A")
That's much better.
Well, not quite, actually, because you probably want single quotes here instead of double quotes:
if(*x == 'A')
By the way, you could probably simplify your parse function as follows, and it'd do the same thing:
int parse ( const char * x) {
return (*x - 'A') + 1; // parenthesis for clarity. Not really needed here.
}

Related

How do I make this else if statement into a recursive statement?

I am trying to make this code recursive. It is supposed to print our "R" if int x is odd and "L" if int x is even.
public String findRL(int x){
s="";
while (x > 1){
if (x%2 ==0){
s = "L" + s;
}
else{
s = "R" + s;
x = x/2;
}
}
}
I am trying to make this code recursive
First step should be trying to make the code work. It's declared to return String but it never returns s. Also, it readily goes into an infinite loop once x becomes even. So let's replace it with this similar function:
public String findRL(int x) {
String s = "";
while (x > 1) {
if (x % 2 == 0) {
s += "L";
} else {
s += "R";
}
x /= 2;
}
return s;
}
This might not be equivalent to what you were trying to do, but should be good enough to see how we might convert your actual code to a recursive function:
public String findRL(int x) {
String s = "";
if (x > 1) {
if (x % 2 == 0) {
s = "L";
} else {
s = "R";
}
s += findRL(x / 2);
}
return s;
}
We don't change the if ... else statement into recursion but rather the while loop as recursion typically uses an implicit loop in place of an explicit loop in interation.

C++ Return is different if a Printf is in a function

I am experiencing a rather strange thing. I am currently working on a function that calculates the shape factor of a shape. The perimeter and area functions work perfectly fine however I have discovered something.
The code that out puts the right answer
double Shapefactor (char line [50][50]){
double sfactor;
double perimeter1= (Perimeter(line));
printf("peri = %f", perimeter1);
double area1=((double)Area(line));
sfactor = ((perimeter1 * perimeter1) /area1);
printf("----------------------------------------------------*Therefore the shape factor for the given shape is* %f \n", sfactor);
return (sfactor);
}
This provides me the correct output. However if I was to remove this line from the code
printf("peri = %f", perimeter1);
Then it gives me the wrong number. Do you have any idea why this is?
Area code
int Area (char line [50][50]){
int x;
int y;
int sum;
for (x = 0; x <= 50; x++) {
for (y = 0; y <= 50; y++) {
if (line[x][y] == '1')
sum++;
}
}
return (sum);
}
Perimeter
int Perimeter (char line [50][50]){
int x;
int y;
int sumup;
FILE * f_ptr;
char filename[20];
for (x = 0; x < 50; x++) {
for (y = 0; y < 50; y++) {
if (line[x][y + 1] == '0' & line[x][y] == '1')
sumup++;
else if (line[x][y] == '1' & line[x][y - 1] == '0')
sumup++;
else if (line[x + 1][y] == '0' & line[x][y] == '1')
sumup++;
else if (line[x][y] == '1' & line[x - 1][y] == '0')
sumup++;
}
}
return (sumup);
}
Thank you
The variable sum in Area() (EDIT: and also sumup in Perimeter(), as noted by #agbinfo) is uninitialized:
int Area (char line [50][50]){
//...
int sum;
for (x = 0; x <= 50; x++) {
for (y = 0; y <= 50; y++) {
if (line[x][y] == '1')
sum++;
//...
This is undefined behavior; this being an automatic variable, it's likely what you're reading there is garbage left on the stack by a previous function call, i.e. whether you invoke printf() or not makes the difference you're seeing.
I recommend enabling compiler warnings and linters which would usually catch these sort of errors.

Reverse Integer Catch overflow C++

Hello I am trying a simple reverse integer operation in c++. Code below:
#include <iostream>
#include <algorithm>
#include <climits>
using namespace std;
class RevInteger {
public:
int reverse(int x)
{
int result = 0;
bool isNeg = x > 0 ? false : true;
x = abs(x);
while (x != 0)
{
result = result * 10 + x % 10;
x = x / 10;
}
if (isNeg)
result *= -1;
if (result > INT_MAX || result < INT_MIN)
return 0;
else
return (int)result;
}
};
When I give it an input as 1534236469; I want it to return me 0, instead it returns me some junk values. What is wrong in my program. Also, I am trying to use the climits lib for the purpose, is there a simpler way of doing the same?
The simplest approach is to use long long in place of int for the result, and check for overflow at the end:
long long result = 0;
/* the rest of your code */
return (int)result; // Now the cast is necessary; in your code you could do without it
Another approach is to convert the int to string, reverse it, and then use the standard library to try converting it back, and catch the problems along the way (demo):
int rev(int n) {
auto s = to_string(n);
reverse(s.begin(), s.end());
try {
return stoi(s);
} catch (...) {
return 0;
}
}
If you must stay within integers, an approach would be to check intermediate result before multiplying it by ten, and also checking for overflow after the addition:
while (x != 0) {
if (result > INT_MAX/10) {
return 0;
}
result = result * 10 + x % 10;
if (result < 0) {
return 0;
}
x = x / 10;
}
class Solution {
public:
int reverse(int x) {
int reversed = 0;
while (x != 0) {
if (reversed > INT_MAX / 10 || reversed < INT_MIN / 10) return 0;
reversed = reversed * 10 + (x % 10);
x /= 10;
}
return reversed;
}
};
If reversed bigger than 8 digit INT_MAX (INT_MAX / 10), then if we add 1 digit to reversed, we will have an int overflow. And similar to INT_MIN.
As suggested by #daskblinkenlight; changing the result as long long and type casting at the end solves the problem.
Working class:
class intReverse {
public:
int reverse(int x) {
long long result = 0; // only change here
bool isNeg = x > 0 ? false : true;
x = abs(x);
while (x != 0) {
result = result * 10 + x % 10;
x = x / 10;
}
if (isNeg) {
result *= -1;
}
if (result > INT_MAX || result < INT_MIN)
{
return 0;
}
else
{
return (int) result;
}
}
};
int reverse(int x) {
int pop = 0;
int ans = 0;
while(x) {
// pop
pop = x % 10;
x /= 10;
// check overflow
if(ans > INT_MAX/10 || ans == INT_MAX/10 && pop > 7) return 0;
if(ans < INT_MIN/10 || ans == INT_MIN/10 && pop < -8) return 0;
// push
ans = ans * 10 + pop;
}
return ans;
}

convert any base to base 10 in C++

I have this code:
#include <stdio.h>
#include <ctype.h>
int validnumber(int b, char* p);
unsigned long base2dec(int b,char *p);
void dec2base (int b,unsigned long x);
char *number;
main() {
int base,temp=0,count;
unsigned long Decimal_number;
do {
printf ("Give the base of the number you want to tranform:");
scanf ("%d", &base);
if (base<2 || base>16)
printf("Not acceptable base number, numbers should be in range from 2 to 16\n\n");
} while (base<2 || base>16);
printf ("Give the number you want to tranform:");
scanf("%s", number);
for (count=0;count<32;count++) {
number [count]= toupper(number[count]);
}
temp=validnumber(base, number);
if (temp==0)
printf ("O arithmpos pou eisagatai periexei MH egkira symbola\n");
else
if (temp==1)
printf ("O arithmpos pou eisagatai periexei egkira symbola\n");
if (temp==1) {
Decimal_number = base2dec( base , number);
}
int validnumber(int b, char *p){
int count, a[32];
for (count=0;count<32;count++)
a[count]=p[count];
if (b>=2 && b<=10) {
for (count=0;count<32;count++) {
if (a[count]<48 || a[count]>48+b)
return 0;
break;
}
}
if (b>=11 && b<=16) {
for (count=0;count<32;count++) {
if ((a[count]>=48 && a[count]<=57) || (a[count]>=65 && a[count]<=70)) {
return 1;
}
}
}
}
From this point the main program must call the function:
unsigned long base2dec (int b, char * p)
which accepts as arguments the base b and a pointer p in character table that
corresponds to the imported string s and returns the number representing the s expressed in the decimal system.
Also, it should call the function:
void dec2base (int b, unsigned long x)
which accepts as arguments the base b and the value of the number x in the decimal system and displays the base value and the representation of the number x in this base. The main program calls this function for all of the base values from 2 to 16.
Are there any ideas on how to begin? Any guidance will be appreciated.
In your base2dec, you will simply call this method and pass in 'b' as it is and x which should be the converted string.
Here is an implementation of dec2base. It is implemented recursively.
void dec2base(int b, unsigned long x){
if (x == 0)
return;
int y = x % b;
x /= b;
if (y < 0)
x += 1;
dec2base(b, x);
//converted digits to hex after realizing this solution doesn't work
//for bases greater than 10. Credits to Trevor pointing this out.
cout<< hex << y < 0 ? y + (b * -1) : y;
return;
}
First of all please have a look at your formatting because the way your code is written makes it harder than it needs to be to follow.
Here is what I would do:
#include <stdexcept>
#include <iostream>
void dec2base(int b, long x)
{
// Quick check for zero
if (x == 0)
{
std::cout << '0';
return;
}
// Print the negative sign if present, also negate
if (x < 0)
{
std::cout << '-';
x = -x;
}
char buf[12];
int i = 0;
// Convert to a backwards BCD
do {
buf[i++] = static_cast<char>(x % b);
} while (x /= b);
// Print it starting from the last digit (really the first)
do {
if (buf[--i] <= 9) std::cout << static_cast<char>(buf[i] + '0');
else std::cout << static_cast<char>(buf[i] + ('a' - 10));
} while (i);
}
long base2dec(int b, char * p)
{
long digit; // Current digit
long mul = 1; // Current multiplier
char *pos = p; // Current position
bool neg = false; // Sign
long ret = 0; // The return value
// Find the last digit
while (*pos) pos++;
// Continue until the start of the string is reached
while (pos-- != p)
{
if (*pos < '0')
{
if (*pos == '-')
{
// Sign reached, save it an break out
neg = true;
break;
}
else // Shouldn't happen
{
throw std::invalid_argument("Not a number");
}
}
if (*pos > 'f')
throw std::invalid_argument("Not a number");
// Get a digit
if (*pos <= '9') digit = *pos - '0';
else if (*pos >= 'a') digit = *pos - ('a' - 10);
else if (*pos >= 'A' && *pos <= 'F')
digit = *pos - ('A' - 10);
else
throw std::invalid_argument("Not a number");
// Make sure it is not larger than or equal to the base
if (digit >= b)
throw std::invalid_argument("Not a number");
// Add the digit
ret += digit * mul;
// Increase the multiplier
mul *= b;
}
return neg ? -ret : ret;
}
int main()
{
long val = base2dec(16, "123f");
dec2base(16, val);
return 0;
}
I realize you didn't ask for a signed version but as it is very easy to implement I have done it. If you really don't need to deal with signed values it is simple to drop the relevant parts from the functions.
This is a very quick and dirty go at this and this could no doubt be improved both for readability and performance but is, I think, a good starting point.
Here is a slightly improved version of base2dec():
long base2dec(int b, char * p)
{
long digit; // Current digit
bool neg = false; // Sign
long ret = 0; // The return value
// Check for negative number
if (*p == '-')
{
neg = true;
p++;
}
// Continue until the end of the string is reached
for (; *p != 0; p++)
{
// Rough range check
if (*p < '0' || *p > 'f')
throw std::invalid_argument("Not a number");
// Get a digit
if (*p <= '9') digit = *p - '0';
else if (*p >= 'a') digit = *p - ('a' - 10);
else if (*p >= 'A' && *p <= 'F')
digit = *p - ('A' - 10);
else
throw std::invalid_argument("Not a number");
// Make sure it is not larger than or equal to the base
if (digit >= b)
throw std::invalid_argument("Not a number");
// Add the digit
ret = ret * b + digit;
}
return neg ? -ret : ret;
}
Regarding the validnumber() function. This check is best performed during the conversion both to avoid having to read the entire string twice and because base2dec() really ought to check for valid input anyway. If you still need a separate check then you need to fix validnumber(). There is no need to copy the string to an array and it is also better to use the same code for all bases. Here is a suggestion:
bool validnumber(int b, char *p)
{
// Check for valid base
if (b < 2 || b > 16) return false;
// Extract numeric and alpha parts of the base
int b_numeric = b <= 10 ? b : 10;
int b_alpha = b - 11;
// Ignore any sign
if (*p == '-') p++;
// Continue until the end of the string
for (; *p != 0; p++)
{
// Digits < 0 are always bad
if (*p < '0') return false;
// Check for valid numeric digits
if (*p > ('0' + b_numeric))
{
// Check for valid alpha digits
if (b <= 10) return false;
if (*p < 'A' || *p > ('a' + b_alpha)) return false;
if (*p > ('A' + b_alpha) && *p < 'a') return false;
}
}
return true;
}

Conver BCD Strings to Decimal

I am looking for better ways to optimize this function for better performance, speed its targeted towards embedded device. i welcome any pointers, suggestion thanks
function converts string BCD to Decimal
int ConvertBCDToDecimal(const std::string& str, int splitLength)
{
int NumSubstrings = str.length() / splitLength;
std::vector<std::string> ret;
int newvalue;
for (auto i = 0; i < NumSubstrings; i++)
{
ret.push_back(str.substr(i * splitLength, splitLength));
}
// If there are leftover characters, create a shorter item at the end.
if (str.length() % splitLength != 0)
{
ret.push_back(str.substr(splitLength * NumSubstrings));
}
string temp;
for (int i=0; i<(int)ret.size(); i++)
{
temp +=ReverseBCDFormat(ret[i]);
}
return newvalue =std::stoi(temp);
}
string ReverseBCDFormat(string num)
{
if( num == "0000")
{
return "0";
}
else if( num == "0001")
{
return "1";
}
else if( num == "0010")
{
return "2";
}
else if( num == "0011")
{
return "3";
}
else if( num == "0100")
{
return "4";
}
else if( num == "0101")
{
return "5";
}
else if( num == "0110")
{
return "6";
}
else if( num == "0111")
{
return "7";
}
else if( num == "1000")
{
return "8";
}
else if( num == "1001")
{
return "9";
}
else
{
return "0";
}
}
Update
this is what i plan to get, for a BCD Value::0010000000000000 Decimal Result 2000
BCD is a method of encoding decimal numbers, two to a byte.
For instance 0x12345678 is the BCD representation of the decimal number 12345678. But, that doesn't seem to be what you're processing. So, I'm not sure you mean BCD when you say BCD.
As for the code, you could speed it up quite a bit by iterating over each substring and directly calculating the value. At a minimum, change ReverseBCDFormat to return an integer instead of a string and calculate the string on the fly:
temp = temp * 10 + ReverseBCDFormat(...)
Something like that.
What you call BCD is not actually BCD.
With that out of the way, you can do this:
int ConvertBCDToDecimal(const std::string& str, int splitLength)
{
int ret = 0;
for (unsigned i = 0, n = unsigned(str.size()); i < n; )
{
int v = 0;
for (unsigned j = 0; j < splitLength && i < n; ++j, ++i)
v = 2*v + ('1' == str[i] ? 1 : 0); // or 2*v + (str[i]-'0')
ret = 10*ret + v;
}
return ret;
}
Get rid of all the useless vector making and string copying. You don't need any of those.
Also, I think your code has a bug when processing strings with lengths that aren't a multiple of splitLength. I think your code always considers them to be zero. In fact, now that I think about it, your code won't work with any splitLength other than 4.
BTW, if you provide some sample inputs along with their expected outputs, I would be able to actually verify my code against yours (given that your definition of BCD differs from that of most people, what your code does is not exactly clear.)
as soon as you're optimizing function, here is different variant:
int ConvertBCDToDecimal(const std::string& str) {
unsigned int result = 0;
const std::string::size_type l = str.length();
for (std::string::size_type i = 0; i < l; i += 4)
result = result * 10 + ((str[i] - '0') << 3) + ((str[i + 1] - '0') << 2) + ((str[i + 2] - '0') << 1) + (str[i + 3] - '0');
return result;
}
note: you don't need splitLength argument, as you know that every digit is 4 symbols