i'am writing some encryption program in c++, and when i start it then console print only one char, and decryption don't work, when i do encryption / decryption then program not doing that with numeric numbers of nn, he do that with hes adress. sorry for my english.
// Var
std::string text = "string";
const char *nn = text.c_str();
// Encryption
int x = (int(nn));
x = x * 3 - 100 * 2;
cout << "Numerical numbers: " << x << endl;
cout << "String: " << (char(x)) << endl;
// Decryption
x = (x - 100 * 2) / 3;
cout << "Numerical numbers: " << x << endl;
cout << "String: " << (char(x));
I suppose you would like to encrypt every characters of this:
std::string text = "string";
In this case you will need a vector of integers instead of a single int, to store every encoded character:
std::vector<int> encrypted;
Since you know what will be the final size of the vector, you can prepare the vector beforehand to allocate the necessary space, but this is optional:
encrypted.reserve(text.size());
Than you have to go through the characters one by one, encode them and put them to the vector:
for(auto &ch : text) {
int x = ch * 3 - 100 * 2;
encrypted.push_back(x);
}
The resulting vector can be printed this way:
cout << "Numerical numbers: ";
for(auto x : encrypted) { cout << x << ", "; }
cout << endl;
The decryption is analogous:
std::string decrypted;
decrypted.reserve(encrypted.size());
for(auto &x : encrypted) {
char ch = (x + 100 * 2) / 3;
decrypted += ch;
}
Unless you have restrictions that you have to use the formula x * 3 - 100 * 2 for encryption/decryption, I suggest you to use XOR.
#include <iostream>
#include <string>
int main()
{
// Var
std::string text = "string", encrypt, decrypt;
// Encryption
for (int i = 0; i < text.length(); i++)
{
encrypt += text[i] ^ '1';
}
// Decryption
for (int i = 0; i < encrypt.length(); i++)
{
decrypt += encrypt[i] ^ '1';
}
std::cout << "original text: " << text << std::endl << "encrypted text: " << encrypt << std::endl << "decrypted text: " << decrypt;
}
The output of the above code would be:
original text: string
encrypted text: BECX_V
decrypted text: string
Here is an working example of the above code.
Related
I wrote the following code:
#include <iostream>
#include <time.h>
#include <string.h>
int main()
{
std::string alphabet = "abcdefghijklmnopqrstuvwxyz";
std::string word;
unsigned long long int i = 0;
srand(time(NULL));
while(true)
{
int randomIndex = rand() % 27;
word += alphabet[randomIndex];
// If the word might be the desired word, "hi"
if (word.size() == 2)
{
// The word should only be printed if its length is equal to 2
std::cout << i << " : " << word << word.size() << std::endl;
if (word == "hi")
{
break;
}
else // The word isn't "hi". We reset the variable word and continue looping
{
word = "";
}
i += 1;
}
}
return 0;
}
It is supposed to put together random letters until word is equal to "hi".
Until that, only 2-character words should be printed, but for some reason the program seems to be thinking that 1-character words have a length of 2. Therefore it also prints 1-character words.
Can anyone please help me?
Let's change the print debug line as follows.
std::cout << randomIndex << '\t' << i << " : " << word << " --> " << word.size() << std::endl;
Here, when we check the strings that look like a single character but 2 characters, we come across them in a random number of 26.
The length of the string "abcdefghijklmnopqrstuvwxyz" is 26. Since the indices of the arrays start from 0, they must be in the range of random numbers [0, 25] we produce.
Then let's update the line of code where we generate the random number as follows.
int randomIndex = rand() % 26
In the wrong code, the 26th character corresponds to the memory cell at the end of the string. Let's take a different example to understand.
int main()
{
char arr[5];
std::string a = "a";
a+=arr[1];
std::cout << a << " " << a.size() << '\n'; // 2
a+=arr[5];
std::cout << a << " " << a.size() << '\n'; // 3
a+=arr[6];
std::cout << a << " " << a.size() << '\n'; // 4
return 0;
}
I'm making a program that converts bytes from a string into a binary system and then store them into a vector. I need to use bitset to convert them. My question is: how can i store the results in a vector b? I thought about saving them one number by one number, but how the loop would look like?
string key = "codekeys";
char text;
vector<int> k;
vector<int> b;
void f() {
for(char& text : key) {
k.push_back(text);
}
cout << "k size: " << k.size() << endl;
for(int i=0; i<k.size(); i++) {
cout << k[i] << " in binary " << bitset<8> (k[i]) << endl;
}
}
If you make b a vector of bitsets then you can store them easily.
string key = "codekeys";
char text;
vector<int> k;
vector<bitset<8>> b;
void f() {
for(char& text : key) {
k.push_back(text);
b.push_back(bitset<8>(text)); // convert to bitset and store in b
}
cout << "k size: " << k.size() << endl;
for(int i=0; i<k.size(); i++) {
cout << k[i] << " in binary " << b[i] << endl; // print b
}
}
I wrote a text cipher program. It seems to works on text strings a few characters long but does not work on a longer ones. It gets the input text by reading from a text file. On longer text strings, it still runs without crashing, but it doesn’t seem to work properly.
Below I have isolated the code that performs that text scrambling. In case it is useful, I am running this in a virtual machine running Ubuntu 19.04. When running the code, enter in auto when prompted. I removed the rest of code so it wasn't too long.
#include <iostream>
#include <string>
#include <sstream>
#include <random>
#include <cmath>
#include <cctype>
#include <chrono>
#include <fstream>
#include <new>
bool run_cypher(char (&a)[27],char (&b)[27],char (&c)[11],char (&aa)[27],char (&bb)[27],char (&cc)[11]) {
//lowercase cypher, uppercase cypher, number cypher, lowercase original sequence, uppercase original sequence, number original sequence
std::ifstream out_buffer("text.txt",std::ios::in);
std::ofstream file_buffer("text_out.txt",std::ios::out);
//out_buffer.open();
out_buffer.seekg(0,out_buffer.end);
std::cout << "size of text: " << out_buffer.tellg() << std::endl;//debug
const int size = out_buffer.tellg();
std::cout << "size: " << size << std::endl;//debug
out_buffer.seekg(0,out_buffer.beg);
char *out_array = new char[size + 1];
std::cout << "size of out array: " << sizeof(out_array) << std::endl;//debug
for (int u = 0;u <= size;u = u + 1) {
out_array[u] = 0;
}
out_buffer.read(out_array,size);
out_buffer.close();
char original[size + 1];//debug
for (int bn = 0;bn <= size;bn = bn + 1) {//debug
original[bn] = out_array[bn];//debug
}//debug
for (int y = 0;y <= size - 1;y = y + 1) {
std::cout << "- - - - - - - -" << std::endl;
std::cout << "out_array[" << y << "]: " << out_array[y] << std::endl;//debug
int match;
int case_n; //0 = lowercase, 1 = uppercase
if (isalpha(out_array[y])) {
if (islower(out_array[y])) {
//std::cout << "out_array[" << y << "]: " << out_array[y] << std::endl;//debug
//int match;
for (int ab = 0;ab <= size - 1;ab = ab + 1) {
if (out_array[y] == aa[ab]) {
match = ab;
case_n = 0;
std::cout << "matched letter: " << aa[match] << std::endl;//debug
std::cout << "letter index: " << match << std::endl;//debug
std::cout << "case_n: " << case_n << std::endl;//debug
}
}
}
if (isupper(out_array[y])) {
for (int cv = 0;cv <= size - 1;cv = cv + 1) {
if (out_array[y] == bb[cv]) {
case_n = 1;
match = cv;
std::cout << "matched letter: " << bb[match] << std::endl;//debug
std::cout << "letter index: " << match << std::endl;//debug
std::cout << "case_n: " << case_n << std::endl;//debug
}
}
}
if (case_n == 0) {
out_array[y] = a[match];
std::cout << "replacement letter: " << a[match] << " | new character: " << out_array[y] << std::endl;//debug
}
if (case_n == 1) {
std::cout << "replacement letter: " << b[match] << " | new character: " << out_array[y] << std::endl;//debug
out_array[y] = b[match];
}
}
if (isdigit(out_array[y])) {
for (int o = 0;o <= size - 1;o = o + 1) {
if (out_array[y] == cc[o]) {
match = o;
std::cout << "matched letter: " << cc[match] << std::endl;//debug
std::cout << "letter index: " << match << std::endl;//debug
}
}
out_array[y] = c[match];
std::cout << "replacement number: " << c[match] << " | new character: " << out_array[y] << std::endl;//debug
}
std::cout << "- - - - - - - -" << std::endl;
}
std::cout << "original text: " << "\n" << original << "\n" << std::endl;
std::cout << "encrypted text: " << "\n" << out_array << std::endl;
delete[] out_array;
return 0;
}
int main() {
const int alpha_size = 27;
const int num_size = 11;
char l_a_set[] = "abcdefghijklmnopqrstuvwxyz";
char cap_a_set[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char n_a_set[] = "0123456789";
std::cout << "sizeof alpha_set: " << std::endl;//debug
char lower[alpha_size] = "mnbvcxzasdfghjklpoiuytrewq";
char upper[alpha_size] = "POIUYTREWQASDFGHJKLMNBVCXZ";
char num[num_size] = "9876543210";
int p_run; //control variable. 1 == running, 0 == not running
int b[alpha_size]; //array with values expressed as index numbers
std::string mode;
int m_set = 1;
while (m_set == 1) {
std::cout << "Enter 'auto' for automatic cypher generation." << std::endl;
std::cout << "Enter 'manual' to manually enter in a cypher. " << std::endl;
std::cin >> mode;
std::cin.ignore(1);
std::cin.clear();
if (mode == "auto") {
p_run = 2;
m_set = 0;
}
if (mode == "manual") {
p_run = 3;
m_set = 0;
}
}
if (p_run == 2) { //automatic mode
std::cout <<"lower cypher: " << lower << "\n" << "upper cypher: " << upper << "\n" << "number cypher: " << num << std::endl;//debug
run_cypher(lower,upper,num,l_a_set,cap_a_set,n_a_set);
return 0;//debug
}
while (p_run == 3) {//manual mode
return 0;//debug
}
return 0;
}
For example, using an array containing “mnbvcxzasdfghjklpoiuytrewq” as the cipher for lower case letters, I get “mnbv” if the input is “abcd”. This is correct.
If the input is “a long word”, I get “m gggz zzzv” as the output when it should be “m gkjz rkov”. Sort of correct but still wrong. If I use “this is a very very long sentence that will result in the program failing” as the input, I get "uas” as the output, which is completely wrong. The program still runs but it fails to function as intended. So as you can see, it does work, but not on any text strings that are remotely long. Is this a memory problem or did I make horrible mistake somewhere?
For your specific code, you should run it through a memory checking tool such as valgrind, or compile with an address sanitizer.
Here are some examples of memory problems that most likely won't crash your program:
Forgetting to delete a small object, which is allocated only once in the program. A memory leak can remain undetected for decades, if it does not make the program run out of memory.
Reading from allocated uninitialized memory. May still crash if the system allocates objects lazily at the first write.
Writing out of bounds slightly after an object that sits on heap, whose size is sizeof(obj) % 8 != 0. This is so, since heap allocation is usually done in multiples of 8 or 16. You can read about it at answers of this SO question.
Dereferencing a nullptr does not crash on some systems. For example AIX used to put zeros at and near address 0x0. Newer AIX might still do it.
On many systems without memory management, address zero is either a regular memory address, or a memory mapped register. This memory can be accessed without crashing.
On any system I have tried (POSIX based), it was possible to allocate valid memory at address zero through memory mapping. Doing so can even make writing through nullptr work without crashing.
This is only a partial list.
Note: these memory problems are undefined behavior. This means that even if the program does not crash in debug mode, the compiler might assume wrong things during optimization. If the compiler assumes wrong things, it might create an optimized code that crashes after optimization.
For example, most compilers will optimize this:
int a = *p; // implies that p != nullptr
if (p)
boom(p);
Into this:
int a = *p;
boom(p);
If a system allows dereferencing nullptr, then this code might crash after optimization. It will not crash due to the dereferencing, but because the optimization did something the programmer did not foresee.
In the below program, when I add one more character to string, its size still remains the same (as evident from str1.size() function). Why is that?
#include <iostream>
#include <cstring>
using std::cout;
using std::endl;
int main() {
std::string str1 = "hello";
cout << "std::string str1 = \"hello\""<< endl;
cout << "string is " << str1 << " with length " << str1.size() << endl;
str1[5] = 'a';
cout << "string is " << str1 << " with length " << str1.size() << endl;
for (int i = 0 ; i < 7; i++) {
cout << "str["<<i<<"] = " << str1[i] << " (int)(str[i])" << (int)str1[i] << endl;
}
}
Output
std::string str1 = "hello"
string is hello with length 5
string is hello with length 5 //expected 6
str[0] = h (int)(str[i])104
str[1] = e (int)(str[i])101
str[2] = l (int)(str[i])108
str[3] = l (int)(str[i])108
str[4] = o (int)(str[i])111
str[5] = a (int)(str[i])97
str[6] = (int)(str[i])0
Operaton str1[5] = 'a'; does not "add" something to a string; it sets the value at a particular position, and the position must be in the range 0..(length()-1); Otherwise, the behaviour is undefined.
To append something to a string, use
str1 += "a";
or
str1.push_back('a');
Note that an std::string - in contrast to plain "C"-style strings - maintains the length in a separate property (and does not calculate it purely relying on a string terminating character '\0').
So in this program I'm trying to go through word by word and make it only lowercase letters, no whitespace or anything else. However, my string "temp" isn't holding anything in it. Is it because of the way I'm trying to modify it? Maybe I should try using a char * instead? Sorry if this is a stupid question, I'm brand new to c++, but I've been trying to debug it for hours and can't find much searching for this.
#include <string>
#include <iostream>
#include <fstream>
#include <ctype.h>
using namespace std;
int main(int argc, char* argv[]) {
/*if (argc != 3) {
cout << "Error: wrong number of arguments." << endl;
}*/
ifstream infile(argv[1]);
//infile.open(argv[1]);
string content((std::istreambuf_iterator<char>(infile)),
(std::istreambuf_iterator<char>()));
string final;
string temp;
string distinct[5000];
int distinctnum[5000] = { 0 };
int numdist = 0;
int wordcount = 0;
int i = 0;
int j = 0;
int k = 0;
int isdistinct = 0;
int len = content.length();
//cout << "test 1" << endl;
cout << "length of string: " << len << endl;
cout << "content entered: " << content << endl;
while (i < len) {
temp.clear();
//cout << "test 2" << endl;
if (isalpha(content[i])) {
//cout << "test 3" << endl;
if (isupper(content[i])) {
//cout << "test 4" << endl;
temp[j] = tolower(content[i]);
++j;
}
else {
//cout << "test 5" << endl;
temp[j] = content[i];
++j;
}
}
else {
cout << temp << endl;
//cout << "test 6" << endl;
++wordcount;
final = final + temp;
j = 0;
for (k = 0;k < numdist;k++) {
//cout << "test 7" << endl;
if (distinct[k] == temp) {
++distinctnum[k];
isdistinct = 1;
break;
}
}
if (isdistinct == 0) {
//cout << "test 8" << endl;
distinct[numdist] = temp;
++numdist;
}
}
//cout << temp << endl;
++i;
}
cout << wordcount+1 << " words total." << endl << numdist << " distinct words." << endl;
cout << "New output: " << final << endl;
return 0;
}
You can't add to a string with operator[]. You can only modify what's already there. Since temp is created empty and routinely cleared, using [] is undefined. The string length is zero, so any indexing is out of bounds. There may be nothing there at all. Even if the program manages to survive this abuse, the string length is likely to still be zero, and operations on the string will result in nothing happening.
In keeping with what OP currently has, I see two easy options:
Treat the string the same way you would a std::vector and push_back
temp.push_back(tolower(content[i]));
or
Build up a std::stringstream
stream << tolower(content[i])
and convert the result into a string when finished
string temp = stream.str();
Either approach eliminates the need for a j counter as strings know how long they are.
However, OP can pull and endrun around this whole problem and use std::transform
std::transform(content.begin(), content.end(), content.begin(), ::tolower);
to convert the whole string in one shot and then concentrate on splitting the lower case string with substring. The colons in front of ::tolower are there to prevent confusion with other tolowers since proper namespacing of the standard library has been switched off with using namespace std;
Off topic, it looks like OP is performing a frequency count on words. Look into std::map<string, int> distinct;. You can reduce the gathering and comparison testing to
distinct[temp]++;