How do I get alphabet from the user - c++

I have a trouble with this. I writing a code for the "vigenere cipher".
I have text and key. But i want to get alphabet from the user. what the user wants etc:"abcdfgh" or "sdgfjdgkfdsgs" just what the user wants.
So but i can't do it.
How do I get alphabet from the user?
Firstly, i want to do get alphabet from the user.
After, I want it to enter the word and encrypt it. But the words alphabet is user's alphabet.
Here is the codes:
#include <iostream>
#include <string>
using namespace std;
// Bu fonksiyon bir key oluşturur.
string generateKey(string str, string key)
{
int x = str.size();
for (int i = 0; ; i++)
{
if (x == i)
i = 0;
if (key.size() == str.size()) // eğer oluşturulan key boyutu girilen
metnin boyutuna eşitse fonksiyonu durdur.
break;
key.push_back(key[i]);
}
return key;
}
string cipherText(string str, string key) // "/Bu fonksiyon orjinal metni şifreler \"
{
string cipher_text;
for (int i = 0; i < str.size(); i++)
{
// converting in range 0-25
int x = (str[i] + key[i]) % 26;
// alfabeyi ASCII kodlarina dönüştür:
x += 'A';
cipher_text.push_back(x);
}
return cipher_text;
}
// "/Bu fonksiyon şifreli metni orjinal hale getirir\"
string originalText(string cipher_text, string key)
{
string orig_text;
for (int i = 0; i < cipher_text.size(); i++)
{
// converting in range 0-25
int x = (cipher_text[i] - key[i] + 26) % 26;
// convert into alphabets(ASCII)
x += 'A';
orig_text.push_back(x);
}
return orig_text;
}
int main()
{
cout << " Sifrelenmesini istediginiz kelimeyi/cumleyi giriniz" << endl;
string str;
getline(cin, str);
//string str = "METINBUGRA";
cout << "Anahtar kelimeyi giriniz." << endl;
string keyword;
getline(cin, keyword);
//string keyword = "ABC";
string key = generateKey(str, keyword);
string cipher_text = cipherText(str, key);
cout << "Sifrelenmis Kelime : "
<< cipher_text << "\n";
cout << "Cozumlenmis kelime : "
<< originalText(cipher_text, key);
system("pause");
return 0;
}

If I correctly understood your question, you want to use a custom alphabet instead of English alphabet. For instance you may add digits.
Instead of actual letters you must operate on numbers: 0, 1, 2, ... N-1, where N is the size of the alphabet. For English alphabet this means you must use 0 instead of A (0x41), 1 instead of B (0x42), ... 25 instead of Z.
If the size of the key is M, the encryption algorithm for letter at position i is:
( L[i] + K[i mod M] ) mod N
Once you have a functional algorithm that operates on numbers, all you have to do is map your input from letters to numbers and your output from numbers to letters.
Mapping numbers to letters is easy; you just have to store the alphabet into a string – this answers your question:
string n_to_letter; // alphabet
//...
int main()
{
//...
cin >> n_to_letter; // read the alphabet
//...
Mapping letters to numbers is probably beyond your current knowledge; you must use a map:
#include <map>
//...
string n_to_letter; // alphabet
map< char, int > letter_to_n;
void init_letter_to_n() //...
If you do not know how to use a map, there is a workaround: just search for the letter in the alphabet string, or use a 256 characters vector/string.
DEMO

Related

find the maximum number of words in a sentence from a paragraph with C++

I am trying to find out the maximum number of words in a sentence (Separated by a dot) from a paragraph. and I am completely stuck into how to sort and output to stdout.
Eg:
Given a string S: {"Program to split strings. By using custom split function. In C++"};
The expected output should be : 5
#define max 8 // define the max string
string strings[max]; // define max string
string words[max];
int count = 0;
void split (string str, char seperator) // custom split() function
{
int currIndex = 0, i = 0;
int startIndex = 0, endIndex = 0;
while (i <= str.size())
{
if (str[i] == seperator || i == str.size())
{
endIndex = i;
string subStr = "";
subStr.append(str, startIndex, endIndex - startIndex);
strings[currIndex] = subStr;
currIndex += 1;
startIndex = endIndex + 1;
}
i++;
}
}
void countWords(string str) // Count The words
{
int count = 0, i;
for (i = 0; str[i] != '\0';i++)
{
if (str[i] == ' ')
count++;
}
cout << "\n- Number of words in the string are: " << count +1 <<" -";
}
//Sort the array in descending order by the number of words
void sortByWordNumber(int num[30])
{
/* CODE str::sort? std::*/
}
int main()
{
string str = "Program to split strings. By using custom split function. In C++";
char seperator = '.'; // dot
int numberOfWords;
split(str, seperator);
cout <<" The split string is: ";
for (int i = 0; i < max; i++)
{
cout << "\n initial array index: " << i << " " << strings[i];
countWords(strings[i]);
}
return 0;
}
Count + 1 in countWords() is giving the numbers correctly only on the first result then it adds the " " whitespace to the word count.
Please take into consideration answering with the easiest solution to understand first. (std::sort, making a new function, lambda)
Your code does not make a sense. For example the meaning of this declaration
string strings[max];
is unclear.
And to find the maximum number of words in sentences of a paragraph there is no need to sort the sentences themselves by the number of words.
If I have understood correctly what you need is something like the following.
#include <iostream>
#include <sstream>
#include <iterator>
int main()
{
std::string s;
std::cout << "Enter a paragraph of sentences: ";
std::getline( std::cin, s );
size_t max_words = 0;
std::istringstream is( s );
std::string sentence;
while ( std::getline( is, sentence, '.' ) )
{
std::istringstream iss( sentence );
auto n = std::distance( std::istream_iterator<std::string>( iss ),
std::istream_iterator<std::string>() );
if ( max_words < n ) max_words = n;
}
std::cout << "The maximum number of words in sentences is "
<< max_words << '\n';
return 0;
}
If to enter the paragraph
Here is a paragraph. It contains several sentences. For example, how to use string streams.
then the output will be
The maximum number of words in sentences is 7
If you are not yet familiar with string streams then you could use member functions find, find_first_of, find_first_not_of with objects of the type std::string to split a string into sentences and to count words in a sentence.
Your use case sounds like a reduction. Essentially you can have a state machine (parser) that goes through the string and updates some state (e.g. counters) when it encounters the word and sentence delimiters. Special care should be given for corner cases, e.g. when having continuous multiple white-spaces or >1 continous full stops (.). A reduction handling these cases is shown below:
int max_words_in(std::string const& str)
{
// p is the current and max word count.
auto parser = [in_space = false] (std::pair<int, int> p, char c) mutable {
switch (c) {
case '.': // Sentence ends.
if (!in_space && p.second <= p.first) p.second = p.first + 1;
p.first = 0;
in_space = true;
break;
case ' ': // Word ends.
if (!in_space) ++p.first;
in_space = true;
break;
default: // Other character encountered.
in_space = false;
}
return p; // Return the updated accumulation value.
};
return std::accumulate(
str.begin(), str.end(), std::make_pair(0, 0), parser).second;
}
Demo
The tricky part is deciding how to handle degenerate cases, e.g. what should the output be for "This is a , ,tricky .. .. string to count" where different types of delimiters alternate in arbitrary ways. Having a state machine implementation of the parsing logic allows you to easily adjust your solution (e.g. you can pass an "ignore list" to the parser and update the default case to not reset the in_space variable when c belongs to that list).
vector<string> split(string str, char seperator) // custom split() function
{
size_t i = 0;
size_t seperator_pos = 0;
vector<string> sentences;
int word_count = 0;
for (; i < str.size(); i++)
{
if (str[i] == seperator)
{
i++;
sentences.push_back(str.substr(seperator_pos, i - seperator_pos));
seperator_pos = i;
}
}
if (str[str.size() - 1] != seperator)
{
sentences.push_back(str.substr(seperator_pos + 1, str.size() - seperator_pos));
}
return sentences;
}

Running Key cipher decryption knowing key?

I'm working on this assignment where I'm taking a user input string, a key of the same or greater length, and using that to perform a Running Key cipher to encrypt and decrypt the text. Encryption is working, but decryption is not.
Looking manually at the Running Key table, I found that "ice" with a key of "did" would encrypt to "lkh" and that checks out. Looking back at the table, I found that for "lkh" to be turned into "ice", the key would have to change to "xsx" and for a moment, thought it'd be easy because I mistakenly thought it was "sxs" which is "did" with each letter shifted forward 15 letters. It's actually more arbitrary than that with the "d"'s shifting 20 letters and the "i" shifting only 10 letters to make "xsx".
I'm not sure what to put in my decrypt(), getDecryptedText(), or decryptionKey() functions to make this work, or if I was even on the right track trying to shift the letters. I imagine I must be, but my current thinking is that it may take some sort of loop to determine how many letters each character in the key should shift forward to.
#include <iostream>
#include <bits/stdc++.h>
#include <algorithm>
#include <cctype>
// Running Key Cipher Explanation
// http://practicalcryptography.com/ciphers/classical-era/running-key/
void encrypt(std::string&, std::string&, std::string&);
void decrypt(std::string&, std::string&, std::string&);
char getEncryptedText(char p, char k);
char getDecryptedText(char p, char k);
std::string decryptionKey(std::string&);
void getKeyIndex(int &i, std::string &key);
int main() {
// Initialization
std::string input;
std::string key;
std::string encryptedText;
std::string decryptedText;
// Assignment
std::cout << "Enter secret message: ";
std::getline(std::cin, input);
std::cout << "Enter key (longer than message): ";
std::getline(std::cin, key);
// Remove spaces
input.erase(remove_if(input.begin(), input.end(), isspace), input.end());
key.erase(remove_if(key.begin(), key.end(), isspace), key.end());
// Exit if key length < secret text
if (key.length() < input.length()) {
std::cout << "The encryption key must be longer than the message."
<< std::endl;
return 1;
}
// Encrypt the text
encrypt(input, key, encryptedText);
// Display encrypted text to user
std::cout << "\nThe encrypted text is:" << std::endl;
std::cout << encryptedText << std::endl;
// Decrypt the text
decrypt(encryptedText, key, decryptedText);
// Display decrypted text to user
std::cout << "\nThe decrypted text is:" << std::endl;
std::cout << decryptedText << std::endl;
return 0;
}
void encrypt(std::string &input, std::string &key, std::string &encryptedText) {
std::string::iterator i;
std::string::iterator j;
// Contains the encrypted version of the text
encryptedText = "";
// Encrypt every character in the input string
for(i = key.begin(), j = input.begin(); j < input.end();) {
// Remove non-letters from text
if (!isalpha(*j)) {
j++;
continue;
}
// get encrypted char
encryptedText += getEncryptedText(tolower(*j),tolower(*i));
i++;
j++;
}
}
char getEncryptedText(char p, char k) {
// Number to be converted into the nth letter in the alphabet
int encryptedText;
encryptedText = p + k;
if (encryptedText >= 219) {
return (char) (encryptedText - 123);
}
return (char)(encryptedText - 97);
}
void decrypt(std::string &encryptedText, std::string &key, std::string &decryptedText) {
std::string::iterator i;
std::string::iterator j;
// Contains the decrypted version of the text
decryptedText = "";
// Change key to decrypt
key = decryptionKey(key);
// Decrypt every character in the input string
for(i = key.begin(), j = encryptedText.begin(); j < encryptedText.end();) {
// get decrypted char
decryptedText += getDecryptedText(tolower(*j),tolower(*i));
i++;
j++;
}
}
char getDecryptedText(char p, char k) {
// Number to be converted into the nth letter in the alphabet
int decryptedText;
decryptedText = p + k;
// If it gets passed z, go back to a
if (decryptedText >= 219) {
return (char) (decryptedText - 123);
}
return (char)(decryptedText - 98);
}
std::string decryptionKey(std::string &key) {
for (int i = 0; i < key.length(); i++) {
// Store integer ASCII value of char
int asc = key[i];
int rem = asc - (26 - (key[i] - 'a'));
int m = rem % 26;
key[i] = (char)(key[i] + 15);
}
// Decryption Key cout for testing
std::cout << "Altered key: " << key;
return key;
}
getEncryptedText can be simplified to:
char getEncryptedText( char p, char k )
{
return ( ( p - 'a' ) + ( k - 'a' ) ) % 26 + 'a';
}
I've replaced magic numbers with the actual character values to make the code easier to read.
If we make sure that getDecryptedText is the exact reverse of getEncryptedText there is no need to modify the key.
char getDecryptedText( char p, char k )
{
return ( ( p - 'a' ) - ( k - 'a' ) + 26 ) % 26 + 'a';
}
The +26 is a fiddle to make sure the value is positive as the modulo won't produce the correct result for negative numbers.

C++ check If a hexadecimal consists of ABCDEF1 OR 0

I have written a program below that converts a string to an int and then converts the decimal number to hexadecimal. I'm struggling to check if the hexadecimal consists only of these characters A, B, C, D, E, F, 1, 0. If so set a flag to true or false.
#include<iostream>
#include <stdlib.h>
#include <string>
#include <sstream>
string solution(string &S){
int n = stoi(S);
int answer;
cout << "stoi(\"" << S << "\") is "
<< n << '\n';
//decToHexa(myint);
// char array to store hexadecimal number
string hexaDeciNum[100];
// counter for hexadecimal number array
int i = 0;
while(n!=0)
{
// temporary variable to store remainder
int temp = 0;
// storing remainder in temp variable.
temp = n % 16;
// check if temp < 10
if(temp < 10)
{
hexaDeciNum[i] = temp + 48;
i++;
}
else
{
hexaDeciNum[i] = temp + 55;
i++;
}
n = n/16;
}
// printing hexadecimal number array in reverse order
for(int j=i-1; j>=0; j--){
cout << hexaDeciNum[j] << "\n";
return "";
}
int main() {
string word = "300";
cout << solution(word);
return 0;
}
OK, it is not the exact answer to what you are asking for, but it is a valuable alternative approach for the entire problem of conversion:
char letter(unsigned int digit)
{
return "0123456789abcdefg"[digit];
// alternatively upper case letters, if you prefer...
}
Now you don't have to differenciate... You can even use this approach for inverse conversion:
int digit(char letter)
{
int d = -1; // invalid letter...
char const* letters = "0123456789abcdefABCDEF";
char* l = strchr(letters, letter);
if(l)
{
d = l - letters;
if(d >= 16)
d -= 6;
}
// alternatively upper case letters, if you prefer...
}
Another advantage: This works even on these strange character sets where digits and letters are not necessarily grouped into ranges (e. g. EBCDIC).

Writing program in C++ using Microsoft VS, but I get a debug assertion message here. It runs on cpp.sh and repl.it fine, but not on VS. What can I do?

This function is meant to remove all special characters, numbers, and whitespace from the char array.
// Michael E. Torres II
// Vigenere Cipher
// February 4, 2018
// C++ code to implement Vigenere Cipher
#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
#include <algorithm>
#include <cctype>
#include <iterator>
#include <sstream>
#include <functional>
using namespace std;
// This function generates the key in
// a cyclic manner until it's length isi'nt
// equal to the length of original text
string generateKey(string str, string key)
{
int x = str.size();
for (int i = 0; ; i++)
{
if (x == i)
i = 0;
if (key.size() == str.size())
break;
key.push_back(key[i]);
}
return key;
}
// This function returns the encrypted text
// generated with the help of the key
string cipherText(string str, string key)
{
string cipher_text;
for (int i = 0; i < str.size(); i++)
{
// converting in range 0-25
int x = (str[i] + key[i]) % 26;
// convert into alphabets(ASCII)
x += 'A';
cipher_text.push_back(x);
}
return cipher_text;
}
// This function decrypts the encrypted text
// and returns the original text
string originalText(string cipher_text, string key)
{
string orig_text;
for (int i = 0; i < cipher_text.size(); i++)
{
// converting in range 0-25
int x = (cipher_text[i] - key[i] + 26) % 26;
// convert into alphabets(ASCII)
x += 'A';
orig_text.push_back(x);
transform(orig_text.begin(), orig_text.end(), orig_text.begin(), ::tolower);
}
return orig_text;
}
string removeNonAlpha(char *str)
{
unsigned long i = 0;
unsigned long j = 0;
char c;
while ((c = str[i++]) != '\0')
{
if (isalpha(c)) // this is where the breakpoint is automatically placed
{
str[j++] = c;
}
}
str[j] = '\0';
return str;
}
// Driver program to test the above function
int main(int argc, char *argv[])
{
string keyword = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
stringstream ss;
char a[] = "“I think and think for months and years. Ninety-nine times, the conclusion is false. The hundredth time I am right.” – Albert Einstein “Imagination is more important than knowledge. For knowledge is limited, whereas imagination embraces the entire world, stimulating progress, giving birth to evolution.” – Albert Einstein";
int i = 0;
string str = removeNonAlpha(a);
str.append(512 - str.length(), 'X');
transform(str.begin(), str.end(), str.begin(), ::toupper);
transform(keyword.begin(), keyword.end(), keyword.begin(), ::toupper);
string key = generateKey(str, keyword);
string cipher_text = cipherText(str, key);
transform(cipher_text.begin(), cipher_text.end(), cipher_text.begin(), ::tolower);
transform(key.begin(), key.end(), key.begin(), ::tolower);
string orig = originalText(cipher_text, key);
cout << "Original/Decrypted Text : " << "\n";
for (int i = 0; i < orig.size(); i += 81)
orig.insert(i, "\n");
cout << orig;
cout << "\n\n" << "Ciphertext : " << "\n";
for (int i = 0; i < cipher_text.size(); i += 81)
cipher_text.insert(i, "\n");
cout << cipher_text;
cout << "\n\nPress ENTER key to Continue\n";
getchar();
return 0;
}
The char array works fine with this while loop, so long as there are no special characters [.,%$#!^]. As soon as there are any special characters in the char array, it gives me the debug assertion:
"Program: ...\Projects\ConsoleApplication17\Debug\ConsoleApplication17.exe
File: minkernel\crts\ucrt\src\appcrt\convert\isctype.cpp
Line: 42
Expression: c >= -1 && c <= 255
...
The program '[11048] ConsoleApplication17.exe' has exited with code 3 (0x3)."
If I run this on repl.it or cpp.sh, I get no issues though. I appreciate any help. Thank you.
It isn't done at all. It needs to be cleaned up a lot, but I'm just trying to test it as is.
see https://msdn.microsoft.com/en-us/library/xt82b8z8.aspx
isalpha expects a number between 0 and 0xFF:
The behavior of isalpha and _isalpha_l is undefined if c is not EOF or
in the range 0 through 0xFF, inclusive. When a debug CRT library is
used and c is not one of these values, the functions raise an
assertion.
You need to cast you char to an unsigned char before passing to isalpha.

Randomizing char array to display random password

I have been tasked with create a solution which will generate a secure password for the user.
i need to...
Prompt the user for the length of the password, the number of
special characters along with the number of numbers.
A password should then be generated randomly using those inputs.
for example output:
What’s the password length? 8
How many special characters? 2
How many numbers? 2
Your password is:
aun2$1s#
My level of programming is at a beginner stage here is and example of what i have done so far
#include <iostream>
#include <algorithm>
using namespace std;
void WorkoutPass(int ,int,int);
int passlength;
int specChar;
int number;
int main()
{
cout << "Enter the length of password: ";
cin >> passlength;
if (passlength > 0)
{
cout << "Enter the amount of special characters: ";
cin >> specChar;
if (specChar > passlength)
{
cout << "Error - invalid value entered is above the length of password";
}
cout << "Enter amount of numbers";
cin >> number;
if (number > passlength)
{
cout << "Error - invalid value entered is above the length of password";
}
WorkoutPass(passlength, specChar, number);
}
else
{
cout << "Error - invalid value entered password must be above zero";
}
return 0;
}
void WorkoutPass(int p, int s, int n)
{
string password;
char alphaBetArray[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
char specCharArray[10] = {'!','£','$','%','&','#','~','#','>','<'};
char numberArray[10] = {'1','2','3','4','5','6','7','8','9','10'};
int numberOfLetters = p - s - n;
char letter;
// generate (numberOfLetters) letters
// each letter generated we add to the string
password += letter;
// Add special characters
// Add numbers
random_shuffle(password.begin(), password.end());
cout << password.c_str() << endl;
}
void DisplayPass()
{
}
c++17 has introduced sample Which you'll want to use along with the random_shuffle you already have in place to generate password:
random_device rd;
mt19937 g(rd());
auto it = sample(cbegin(alphaBetArray), cend(alphaBetArray), begin(password), numberOfLetters, g);
it = sample(cbegin(specCharArray), cend(specCharArray), it, s, g);
sample(cbegin(numberArray), cend(numberArray), it, n, g);
Live Example
A couple notes:
Your arrays are not comprehensive, writing a lambda to randomly generate characters in a range may be a preferable option, you could do that using generate_n.
random_shuffle was deprecated in c++14 you need to use shuffle now
You "just" miss the random generation part, which you can get through the rand function.
So in your case that will be:
for (int i=0; i<numberOfLetters; i++)
password += alphaBetArray[rand()%sizeof(alphaBetArray)];
for (int i=0; i<s; i++)
password += specCharArray[rand()%sizeof(specCharArray)];
for (int i=0; i<n; i++)
password += numberArray[rand()%sizeof(numberArray)];
Be sure to check in the input also the sum of special chars and numbers, now you just check the single entries but someone could put: 10 (password length), 6 (special chars), 7 (numbers), and that's bad.
Generate p random chars
Generate s special chars
Generate n random numbers
Concatenate them and shuffle them
string workout_pass(int p, int s, int n)
{
string password;
const char alphaBetArray[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
const char specCharArray[10] = {'!','£','$','%','&','#','~','#','>','<'};
const char numberArray[10] = {'1','2','3','4','5','6','7','8','9','10'};
int numberOfLetters = p - s - n;
for (i = 0 ; i < numberOfLetters; ++i ) {
password += alphaBetArray[rand() % 26];
}
for (i = 0 ; i < s; ++i ) {
password += specCharArray[rand() % 10];
}
for (i = 0 ; i < n; ++i ) {
password += numberArray[rand() % 10];
}
random_shuffle(password.begin(), password.end());
return password;
}
Some comments :
Since it is a function it is better not to use CamelCase
Since it is a function you better return the generated string and not void
Try to get rid of the char arrays and play with ascii numbers (like 97 + (rand() % 26)) for [a-z]
Last but not least better use C with these problems not C++/STL functions like random_shuffle and try to achieve the same result, you will learn best that way