here is what my function looks like:
signed char INTtoCHAR(int INT)
{
signed char CHAR = (signed char)INT;
return CHAR;
}
int CHARtoINT(signed char CHAR)
{
int INT = (int)CHAR;
return INT;
}
It works properly that it assigns the int value to the char, but when I want to cout that char then it gives me some weired signs. It compiles without errors.
My testing code is:
int main()
{
int x = 5;
signed char after;
char compare = '5';
after = INTtoCHAR(5);
if(after == 5)
{
std::cout << "after:" << after << "/ compare: " << compare << std::endl;
}
return 0;
}
After is indeed 5 but it doesn't print 5. Any ideas?
Adding to the above answer using the unary operator +, there is another way as well: typecasting.
std::cout << "after:" << (int)after << "/ compare: " << compare << std::endl;
Correct output
Use +after while printing, instead of after. This will promote after to a type printable as a number, regardless of type.
So change this:
std::cout << "after:" << after << ", compare: " << compare << std::endl;
to this:
std::cout << "after:" << +after << ", compare: " << compare << std::endl;
For more, see this answer.
Related
I am using the GMP library functions in order to implement the RSA algorithm.
Here is my code:
const char* random_String() {
srand (time(NULL));
const char * tab[] = {"Alice", "Bob", "encryption", "decryption"};
std::cout << sizeof(tab)/sizeof(tab[0]) << std::endl;
int indice = rand() % (sizeof(tab)/sizeof(tab[0]));
return tab[indice];
}
int main()
{
mpz_init(d);
mpz_init(e);
mpz_init(n);
mpz_init(M);
mpz_init(c);
/* This function creates the keys. The basic algorithm is...
*
* 1. Generate two large distinct primes p and q randomly
* 2. Calculate n = pq and x = (p-1)(q-1)
* 3. Select a random integer e (1<e<x) such that gcd(e,x) = 1
* 4. Calculate the unique d such that ed = 1(mod x)
* 5. Public key pair : (e,n), Private key pair : (d,n)
*
*/
mpz_t p,q,op;
mpz_init(p);
mpz_init(q);
mpz_init(op);
char p_str[1000];
char q_str[1000];
mpz_init_set_str(op, "7060", 10);
mpz_nextprime(p, op);
mpz_get_str(p_str,10,p);
mpz_init_set_str(op, "7874", 10);
mpz_nextprime(q, op);
mpz_get_str(q_str, 10, q);
std::cout << "Random Prime 'p' = " << p_str << std::endl;
std::cout << "Random Prime 'q' = " << q_str << std::endl;
char n_str[1000];
mpz_t x;
mpz_init(x);
mpz_mul(n,p,q);
mpz_get_str(n_str,10,n);
std::cout << "\t n = " << n_str << std::endl;
mpz_t p_minus_1,q_minus_1;
mpz_init(p_minus_1);
mpz_init(q_minus_1);
mpz_sub_ui(p_minus_1,p,(unsigned long int)1);
mpz_sub_ui(q_minus_1,q,(unsigned long int)1);
mpz_mul(x,p_minus_1,q_minus_1);
char phi_str[1000];
mpz_get_str(phi_str,10,x);
std::cout << "\t phi(n) = " << phi_str << std::endl;
mpz_init_set_str(e, "79", 0);
char e_str[1000];
mpz_get_str(e_str,10,e);
std::cout << "\t e = " << e_str << std::endl;
mpz_invert(d, e, x);
char d_str[1000];
mpz_get_str(d_str,10,d);
std::cout << "\t d = " << d_str << std::endl << std::endl;
std::cout << "Public Keys (e,n): ( " << e_str <<" , " << n_str << " )" << std::endl;
std::cout << "Private Keys (d,n): ( " << d_str <<" , " << n_str << " )" << std::endl;
const char* mess = random_String();
char c_str[1000];
std::cout << "The message: : " << mess << std::endl;
mpz_set_str(M, mess, 10);
mpz_powm(c, M, e, n);
mpz_get_str(c_str, 10, c);
std::cout << "The encrypted message: " << c_str << std::endl;
}
During the last 5 lines of the code, I encrypt the message with the values that were previously computed and by following the RSA formulas of encryption.
The result of the encrypted message is 0, which means that the result of c_str is 0. How comes that it is 0?
This code
mpz_set_str(M, mess, 10);
converts the random string mess to an integer. For this to work the string must consist of decimal digits, but this is not true for any of your random strings. So the function fails and M is unchanged.
If you check the return value of mpz_set_str you will see that it is -1 meaning the function failed.
Basically your conversion to and from your message to an integer will only work if the message is a decimal number. To convert arbitrary strings you should be using the mpz_import and mpz_export functions instead of mpz_set_str and mpz_get_str.
if x > INT_MAX or if x > INT_MIN the function will return 0... or that's what i'm trying to do :)
in my test case i pass in a value that is INT_MAX + 1... 2147483648 ... to introduce integer overflow to see how the program handles it.
i step through... my IDE debugger says that the value immediately goes to -2147483648 upon overflow and for some reason the program executes beyond both of these statements:
if (x > INT_MAX)
if (x < INT_MIN)
and keeps crashes at int revInt = std::stoi(strNum);
saying out of range
Must be something simple, but it's got me stumped. Why isn't the program returning before it ever gets to that std::stoi() given x > INT_MAX? Any help appreciated. Thanks! Full listing of function and test bed below: (sorry having trouble with the code insertion formatting..)
#include <iostream>
#include <algorithm>
#include <string> //using namespace std;
class Solution {
public: int reverse(int x)
{
// check special cases for int and set flags:
// is x > max int, need to return 0 now
if(x > INT_MAX)
return 0;
// is x < min int, need to return 0 now
if(x < INT_MIN)
return 0;
// is x < 0, need negative sign handled at end
// does x end with 0, need to not start new int with 0 if it's ploy numeric and the functions used handle that for us
// do conversion, reversal, output:
// convert int to string
std::string strNum = std::to_string(x);
// reverse string
std::reverse(strNum.begin(), strNum.end());
// convert reversed string to int
int revInt = std::stoi(strNum);
// multiply by -1 if x was negative
if (x < 0)
revInt = revInt * -1;
// output reversed integer
return revInt;
}
};
Main:
#include <iostream>
int main(int argc, const char * argv[]) {
// test cases
// instance Solution and call it's method
Solution sol;
int answer = sol.reverse(0); // 0
std::cout << "in " << 0 << ", out " << answer << "\n";
answer = sol.reverse(-1); // -1
std::cout << "in " << -1 << ", out " << answer << "\n";
answer = sol.reverse(10); // 1
std::cout << "in " << 10 << ", out " << answer << "\n";
answer = sol.reverse(12); // 21
std::cout << "in " << 12 << ", out " << answer << "\n";
answer = sol.reverse(100); // 1
std::cout << "in " << 100 << ", out " << answer << "\n";
answer = sol.reverse(123); // 321
std::cout << "in " << 123 << ", out " << answer << "\n";
answer = sol.reverse(-123); // -321
std::cout << "in " << -123 << ", out " << answer << "\n";
answer = sol.reverse(1024); // 4201
std::cout << "in " << 1024 << ", out " << answer << "\n";
answer = sol.reverse(-1024); // -4201
std::cout << "in " << -1024 << ", out " << answer << "\n";
answer = sol.reverse(2147483648); // 0
std::cout << "in " << 2147483648 << ", out " << answer << "\n";
answer = sol.reverse(-2147483648); // 0
std::cout << "in " << -2147483648 << ", out " << answer << "\n";
return 0;
}
Any test like (x > INT_MAX) with x being of type int will never evaluate to true, since the value of x cannot exceed INT_MAX.
Anyway, even if 2147483647 would be a valid range, its reverse 7463847412 is not.
So I think its better to let stoi "try" to convert the values and "catch" any out_of_range-exception`. The following code illustrates this approach:
int convert() {
const char* num = "12345678890123424542";
try {
int x = std::stoi(num);
return x;
} catch (std::out_of_range &e) {
cout << "invalid." << endl;
return 0;
}
}
Here's the code:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int keyArray[7] = {1,2,3,4,5,6,7};
int breakPoint;
int counter;
for (counter = 0; counter < 7; counter++)
{
// keyArray[counter] = (rand() % 9) + 1; later
keyArray[counter] = counter; //testing
}
cout << keyArray[0] + "\n";
cout << keyArray[1] + "\n";
cout << keyArray[2] + "\n";
cout << keyArray[3] + "\n";
cout << keyArray[4] + "\n";
cout << keyArray[5] + "\n";
cout << keyArray[6] + "\n";
cin >> breakPoint; //so I can see what the hell is going on before it disappears
return 0;
}
The only reason I gave values to keyArray was that I read in answer to a similar question that you have to initialize an array with data before you use it. But it made no difference. The output is just junk symbols whether you initialize or not.
The compiler is Visual Studio Community 2017. Thanks for any help.
The error is not in your logic but rather in your debugging output. Since the other answers focus on how to fix it, I'll rather explain what happens instead. There seems to be a misunderstanding about the way strings work in C++.
The failure is in this operation:
keyArray[0] + "\n"
Internally, string literals are arrays of characters, in this case const char[2], consisting of the newline and a terminating '\0' null terminator. When you then try to add the integer and this array together, the array will be represented by a pointer to its first element, i.e. it will decay to const char* in order to be used as the second argument to the plus operator used in your code.
So for the compiler, this line will need operator+(int, const char*). But the result of that will be const char*, the input pointer offset by the integer, as that is the operation that happens when adding integers to pointers.
So instead of printing the number and then the string, it will try to access a string that does not exist as the pointer now pointer behind the string "\n" and thus into some arbitrary memory.
Instead of doing
cout << keyArray[0] + "\n"
do:
cout << keyArray[0] << "\n"
or
cout << keyArray[0] << endl
You can't concatanate an integer with a string. That's why you got garbage output
Try this first:
cout << keyArray[0] << "\n";
If you are using compilers that support C++ 11 then try using std::to_string(...) to make a string from an integer before doing the addition:
cout << (std::to_string(keyArray[0]) + "\n");
you cannot concatenate int with string.
change
cout << keyArray[0] + "\n";
cout << keyArray[1] + "\n";
cout << keyArray[2] + "\n";
cout << keyArray[3] + "\n";
cout << keyArray[4] + "\n";
cout << keyArray[5] + "\n";
cout << keyArray[6] + "\n";
to
cout << keyArray[0] << "\n"
<< keyArray[1] << "\n"
<< keyArray[2] << "\n"
<< keyArray[3] << "\n"
<< keyArray[4] << "\n"
<< keyArray[5] << "\n"
<< keyArray[6] << endl;
You need to convert the integers into a string. Using a relatively recent version of C++:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int keyArray[7] = {1,2,3,4,5,6,7};
int breakPoint;
int counter;
for (counter = 0; counter < 7; counter++)
{
// keyArray[counter] = (rand() % 9) + 1; later
keyArray[counter] = counter; //testing
}
cout << std::to_string(keyArray[0]) + "\n";
cout << std::to_string(keyArray[1]) + "\n";
cout << std::to_string(keyArray[2]) + "\n";
cout << std::to_string(keyArray[3]) + "\n";
cout << std::to_string(keyArray[4]) + "\n";
cout << std::to_string(keyArray[5]) + "\n";
cout << std::to_string(keyArray[6]) + "\n";
cin >> breakPoint; //so I can see what the hell is going on before it disappears
return 0;
}
I have a program with one structnamed sample, it contains 2 int members and one char *. when creating 2 objects called a and b, I try assign a new dynamic string to a with the pointer and then copy all the values to b. so b = a. But later on when try to make changes to a like this : a.ptr[1] = 'X'; the pointer in b also changes. I want to know why, and how can I solve this.
struct Sample{
int one;
int two;
char* sPtr = nullptr;
};
int _tmain(int argc, _TCHAR* argv[])
{
Sample a;
Sample b;
char *s = "Hello, World";
a.sPtr = new char[strlen(s) + 1];
strcpy_s(a.sPtr, strlen(s) + 1, s);
a.one = 1;
a.two = 2;
b.one = b.two = 9999;
b = a;
cout << "After assigning a to b:" << endl;
cout << "b=(" << b.one << "," << b.two << "," << b.sPtr << ")" << endl << endl;
a.sPtr[1] = 'X' ;
cout << "After changing sPtr[1] with 'x', b also changed value : " << endl;
cout << "a=(" << a.one << "," << a.two << "," << a.sPtr << ")" << endl;
cout << "b=(" << b.one << "," << b.two << "," << b.sPtr << ")" << endl;
cout << endl << "testing adresses for a and b: " << &a.sPtr << " & b is: " << &b.sPtr << endl;
return 0;
}
Your struct contains a char*. When you assign all values in a to b, the pointer is also copied.
This means that a and b now point to the same char array. Therefore changing a value in this char array changes it for both structs.
If you do not want this, make a new char array for b and use strcpy.
You are copying the pointer not the value. To solve this you could override your assignment operator in the structure:
struct Sample{
int one;
int two;
char* sPtr = nullptr;
Sample& operator=(const Sample& inputSample)
{
one = inputSample.one;
two = inputSample.two;
sPtr = new char[strlen(inputSample.sPtr) + 1];
strcpy (sPtr, inputSample.sPtr);
return *this;
}
};
I have done a simple program testing pointers, references, and recursion.
Here is the code to overlook (the problem is complained to come from PassAddresses' function):
#include <iostream>
using namespace std;
long RecRecur(short &caps);
void PassAddresses(short &address, short &address2, const char *nosey);
int main(int args, char **LOC)
{
short test = 15;
const char rosey = 0;
short myLick = 500;
short PersonalWhim = 250;
const char *LOG = &rosey;
RecRecur(test);
PassAddresses(myLick, PersonalWhim, LOG);
}
void PassAddresses(short &address, short &address2, const char *nosey)
{
address = address + address;
address2 += address;
for(short i = 100; i < 1000; i++)
{
for(short c = 50; c != 120; c++)
{
cout << "These are just for-loop tests...." << /n;
}
}
cout << address << /n << address2 << /n << nosey << /n << &rosey;
}
long RecRecur(short &caps)
{
caps--;
if(caps > 0x7CDE)
{
RecRecur();
}
else return;
}
Basically the compiler is complaining that a "primary-expression" is expected before the "/" character, and I am clueless on what the issue could be. The expressions/operators on the "address" value are perfectly interchangeable.
1. The escape character is '\', not '/'.
cout << address << /n << address2 << /n << nosey << /n << &rosey;
change above line with
cout << address << "\n" << address2 << "\n" << nosey << "\n" << &nosey;
or
cout << address << endl << address2 << endl << nosey << endl << &nosey;
2. Notice that you have a type in the same line. You may want to write nosey not rosey :)
3. RecRecur(); takes an argument please give one.
4. RecRecur() has to return a long
The escape character '\', not '/'. It also needs to be inside quotes:
cout << "hello world" << '\n';
It's a simple syntax error - a newline is endl, not \n.