substitution cipher in c++ - c++

I have generate a random text file
A B C D E F G H
T W G X Z R L N
I want to encode my message so that A = T , B = W , C = G and so on..
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int
main ()
{
string getmsg;
ifstream openfile ("random.txt");
if (openfile.is_open ()) {
while (! openfile.eof ()) {
getline (openfile,getmsg); //read from random.txt
cout << getmsg << endl;
}
}
}
Am quite of stuck here.
eg. when i input the word "HAD" it will display "NTX" and by using the same random text file I can input "NTX" and give me back the "HAD"

While others have pointed out Map, I would have used a simple array (subs), of size 26 (If there are only capital alphabets).
Initialize the array with 0s. Read all the chars and their mapping. Store it something like this subs[char-'A'] = mapped_char. I will leave the reading to you.
EDIT-
If you are ready to pay for extra memory usage, just make the size of subs as 123 (ASCII for z + 1).
This will also simplify the logic to subs[char] = mapped_char

Since this feels like homework I'll give you guidance rather than a solution.
You want to create a bijectional map between an input character and a corresponding character to output.
One solid way to do that is with a Map. Create a Map that has as its key the input character e.g. 'A' and as its value the output character e.g. 'T'.
For each character that you read in from your file, use the Map to lookup the corresponding output character.
You will need to read input one character at a time (simplest), or read one line at a time (as you do now) and run through each line, character by character, to do the translation with the Map.
Update
To clarify a point in the comments, this is a bijectional function because there is exactly one encoded character for each original character. If the text does not have to be decoded, a Map will do for the software representation of the function. If decoding is needed, a Bimap is more appropriate.
Injective Function
Bijective Function
http://en.wikipedia.org/wiki/Injective_function

one way to do it is if you
take a look at std::map<> (map<char,char> in your case)
using it you can setup a map of character pairs, then when you read one character from your file/buffer you look it up in the map and retrieve the corresponding character.
another, more verbose way, would be to have a switch statement
char ch;
ch << openfile
switch(ch)
{
case 'A': ch = 'T'; break;
...
}
cout << ch;
there are other ways as well, see if you can find one more involving an array.

Related

How to find out how many strings are written into a binary file?

I have a binary file text.bin. The text inside is written this way:
4helo5hello6helloo. If I was not to know there are 3 strings inside,
how would I find out? I want to make a dynamic array of strings from a
binary file, but first I have to know how many strings there are in the file.
I know I can read it like this:
ifstream dat("text.bin", ios_base::binary);
if (!dat)
{
cout << "Error";
return 1;
}
int temporary;
dat.read((char*)(&temporary), sizeof(temporary));
char *arrray = new char[temporary];
dat.read(arrray, temporary);
string word = string(arrray, temporary);
How would I make this into a loop, so that it reads as long as there is something to read in the binary file? How would I find out how many words there are, so that I could prepare a dynamic array for the words? I am using:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
Keep it simple. If the binary format is like you said : 4helo5hello6helloo for example, do the following;
Read the first number,
substring from the position of the first number to however long the string is (the number you read),
Put the substring into a two-dimensional array (one dimension for the number of strings, the other for the length of the strings),
Wash rinse repeat until you reach the end of the file.
The length of the first dimension of the array is the number of strings in the file. The array now contains all the strings in the read file.
Cheers!
For 4helo5hello6helloo, write a separate function to iterate over word and at each numerical value increment the String array index by that value and increment a word_counter variable by 1 to get the number of words in your file.
The skipped indices contain your words (maybe write them to another array).
read () function has a return type size_t and returns the number of bytes read from file, where a return value of 0 signifies that end of file has been reached.
int not_end = 1;
while (not_end)
{
not_end = dat.read((char*)(&temporary), sizeof(temporary));
char *arrray = new char[temporary];
dat.read(arrray, temporary);
string word = string(arrray, temporary);
// Note that word will get overwritten each time the loop is run
// Store word in an array of Strings and keep incrementing index
}

Shift cipher in C++ (How to get ASCII value and handling numbers)

I have a program set up already to read in a file and split each line into words, storing them into a double vector of strings. That is,
std::vector < std::vector <std::string> > words
So, the idea is to use an array from alphabet a-z and using the ASCII values of the letters to get the index and swapping the characters in the strings with the appropriate shifted character. How would I get the value of each character so that I can look it up as an index?
I also want to keep numbers intact, as a shift cipher, I believe, doesn't do anything with numbers in the text to be deciphered. How would I check if the character is an int so I can leave it alone?
If you want the ASCII value, you simply have to cast the value to a int:
int ascii_value = (int)words[i][j][k];
If you want to have a value starting from A or a you can do this:
int letter_value_from_A = (int)(words[i][j][k] - 'A');
int letter_value_from_a = (int)(words[i][j][k] - 'a');
Your char is nothing else than a value. Take this code as example (I am used to program C++11, so this will be a little ugly):
char shiftarray[256] = {0, 0, 0, 0 // Here comes your map //
std::string output;
for(int w=0; w<words.length(); w++)
{
for(int c=0; c<words[w].length(); c++)
{
output.pushback(shiftarry[words[w][c]]);
}
output.push_back(' ');
}
I do not know how to do it in anything other than basic, but very simply get the ascii value of each letter in the string using a loop. As the loop continues add a value to, or subtract a value from the ascii value you just obtained, then convert it back to a letter and append it to a string. This will give you a different character than you had originally. By doing this, you can load and save data that will look like gibberish if anyone tried to view it other than in the program it was written in. The data then becomes a special propriatry document format.

cpp stringstream read input file algorithm to find LCS

Hi here's my first questions here, I would write as clear as possible, if I am too newbie here, please bear it with me. Thanks
Backgroud: I was asked to solve longest common substring(lcs) problem with given input files in c++.
Its purpose is to optimize the algorithm, so it has limited run-time and RAM requirement.(case insensitive)
My Approach: I used to stringstream to parse the every input line and stored them into a vector. use something like suffix tree to chop the string, sort it and put into a vector array (vector that store vectors) and compare every 2 lines (v1,v2) to find common substirng.(I used nested foop loop to compare each word inside every vector), and then put common substrings back to array and remove v1 and v2.
suffix tree eg. banana -> anana -> nana -> ana -> na -> a..[I stored all 5 elements into the vector]
result: it works for most of the files (normal textfiles)
problem: I got 2 special test case that took me forever to find lcs.
1. has 10000 line input, and each line has ave 3000 chars (include space). It took me 50 mins to find lcs. the requirement is not exceed 5 mins.
2. has 100 line input, and each line has ave 60k chars. It never finish running
what I tried:build a common word dictionary for first 2 sentence
read first two lines and stored into vectors
used suffix tree again to find common elements(substring) and named as dictionary
for rest of input lines,
if (words read is within dictionary)
fine do what I did before, read next one
else if (word is not in dictionary)
ignore this word, read next one
help needed: I still cannot read the first two lines if each line contains 60k char, so building the dict itself would exceed the run time limitations. I am not sure if the hashed table would work way better than vectors. I knew a bit about HT but never write anything with it, so if you can explain HT with patience, I would appreciate that.
Update:
As suggested, I put some code here (first one for parse and store into vector, second involve how I compare 2 string and find common element)
vector< vector<string> > parsed_array;
vector<string> choped_element;
// Num1::read from file in a while loop
while (getline (myfile,line))
{
cout << "< InputlineLoopCounter: "<<InputlineLoopCounter<<endl;:q
choped_element.clear();
choped_element.push_back(line); //whole string as first element, eg'Hello World"
stringstream ss(line);
string copystr (line);
while (ss >> temp)
{
copystr.erase(0,copystr.find_first_of(" \t")+1); // here turns into "World"
choped_element.push_back(copystr);
}
choped_element.pop_back();//since I stored whole string as frist element, last one is not necessary
sort(choped_element.begin(),choped_element.end());
parsed_array.push_back(choped_element);//stored into vector array
InputlineLoopCounter ++;
}
//Num::2 compare part in 2 diff string and assembly into new string
//v1 and v2 and 2 vectors full of chopped strings and v3 should be common element
// eg. v1[0]="hello world"; v1[1]="world"
// eg. v2[0]="I dislike hello world"; v2[1]="dislike hello word"; v2[2]="hello word"; v2[4]="word"
// eg. v3 as result would be v3[0]="hello word";v3[1]="word"
for (size_t i = 0; i < v1len; i++)
{
for (size_t j = 0; j< v2len; j++)
{
stringstream ss1(v1[i]);
string fword1;
ss1>>fword1;
stringstream ss2(v2[j]);
string fword2;
ss2>>fword2;
if(fword1 == fword2) //v1[i] and v2[j] are space seperated words
{
string nword1;
string nword2;
string lcommon;
int comlen = 1;
string combine;
combine.append(fword1);
combine.append(space);
while (ss1>>nword1 && ss2>>nword2)
{
if (nword1 == nword2)
{
combine.append(nword1);
combine.append(space);
comlen ++;
}
else
break;
}
combine.erase(combine.find_last_of(" "));
cout<< "common word: "<<combine<<endl;
v3.push_back(combine);
}
}
}

How to remove a character from the string and change data if need it?

I have possible inputs 1M 2M .. 11M and 1Y (M and Y stand for months ) and I want to output "somestring1 somestring2.... and somestring12" note M and Y are removed and the last string is changed to 12
Example: input "11M" "hello" output: hello11
input "1Y" "hello" output: hello1
char * (const char * date, const char * somestr)
{
// just need to output final string no need to change the original string
cout<< finalStr<<endl;
}
The second string is getting output as a whole itself. So no change in its output.
The second string would be output as long as M or Y are encountered. As Stack Overflow discourages providing exact source codes, so I can give you some portion of it. There is a condition to be placed which is up to you to figure out.(The second answer gives that as well)
Code would be somewhat like this.
//Code for first string. Just for output.
for (auto i = 0 ; date[i] != '\0' ; ++i)
{
// A condition comes here.
cout << date[i] ;
}
And note that this is considering you just output the string. Otherwise you can create another string and add up the two or concatenate the existing ones.
is this homework? If not, here's what i'd suggest. (i ask about homework because you may have restrictions, not because we're not here to help)
1) do a find on 'M' in your string (using find), insert a '\0' at that position if one is found (btw i'm assuming you have well formatted input)
2) do a find on 'Y'. if one is found, insert a '\0' at that position. then do an atoi() or stringstream conversion on your string to convert to number. multiply by 12.
3) concatenate your string representation of part 1 or part 2 to your somestr
4) output.
This can probably be done in < 10 lines if i could be bothered.
the a.find('M') part and its checks can be conditional operator, then the conversion/concatenation in two or three lines at most.

C++ string manipulation / input

This is for homework! But I need help anyway. The assignment is to input a sentence then output the number of words, and the number of occurrences of each letter. The output must have the letters in alphabetical order. So far, I've been able to count the number of words and get all the letters to lower case so that I'll be able to keep count of them. My question is how to actually keep count of the letters.
Example of output:
I say Hi.
3 words
1 a
1 h
2 i
1 s
1 y
Here's the code that I have so far:
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
int letters[26];
char letter;
int word = 0;
cout << "Please enter a sentence: "<< endl;
do
{
cin.get(letter);
if(isspace(letter))
word++;
letter = tolower(letter);
cout << letter;
}
while (letter != '\n');
cout << "The number of words = " << word << endl;
return 0;
}
Should I input directly into a C-string? or will that mess up the word count?
If you're allowed to use STL, use std::map for mapping letters to counters. It will additionally sort the letters.
Otherwise, treat chars as indexes in an array of counters and increment them.
My question is how to actually keep
count of the letters
It's fairly straight forward. Simply create an array of 26 integers, (one for each letter), and initialize it to zero.
int letters[26] = { 0 }; // Initialize array to zero
Each value in the array corresponds to a count of a particular letter. Array index 0 refers to 'a', array index 1 refers to 'b', and so on. Then, everytime you encounter a letter, increment the appropriate value in the array. You can use the character 'a' (ASCII value 97) as a starting offset. So, given the variable char letter; you would do:
++letters[tolower(letter) - 'a'];
But always make sure that before you increment the appropriate value in the array, you check that isalpha(letter) && islower(letter) to make sure that your letter is in the range of lowercase a-z; otherwise you will access an index beyond the bounds of the array. You can also test for this condition by saying if (letter >= 'a' && letter <= 'z').
Hint: tolower(letter)-'a' is:
0 if letter is a
1 if letter is b
...
Hm, just few points to make your home task more useful to you (and your code more correct):
Think what happens if you have file with several spaces in a row (word counting).
Think how to be more correct with 'letters' (check for isalpha() at least). Also isalpha() could be key for simpler counting with fixed array [256] (this might be even the best solution as for performance vs std::map usage, check std::map documentation anyway).
Think about more effective file input. At least line at once.