Encrypting a text file by incrementing chars - c++

I need to encrypt a simple text file by incrementing each character by 1 i.e 'a' becomes 'b', 'b' becomes 'c' etc. with 'z' becoming 'a'.
I have done this as per the code below, and although majority of my output is correct, it seems to have trouble at the end of each file.
For example, when the input file contains 'a b c d' the output generated is 'b c d ef' as opposed to the answer which should be 'b c d e'. I cannot seem to figure this out.
This is my code for the encrypt function:
void encrypt(char* inFileName, char* outFileName) {
out_stream.open(outFileName);
in_stream.open(inFileName);
if(in_stream.fail()) {
cout << "Failed to open input file." << endl;
exit(1);
}
else {
while(!in_stream.eof()) {
in_stream.get(letter);
if (letter == 'z') {
letter = 'a';
}
if (letter == 'Z') {
letter = 'A';
}
if (letter == ' ') {
letter = letter;
}
else {
letter = letter + 1;
}
out_stream << letter;
}
}
}

Shift ciphers can be achieved using this way:
while(!in_stream.eof()) {
if (letter>='a' && letter<='Z')
letter = (letter+1)%'Z' + 'a';
out_stream << letter;
}
Reduce redundancy from your code and make it as compact as possible, there are so many useless conditions in your code.
The main logic lies in ciphering characters from a...Z, you cannot predict other characters in text file such as \n \0 etc, so they shouldn't be dealt with at all.

I can suggest this piece of code
while(!in_stream.eof()) {
if ((letter>='A' && letter<='Y')|| (letter>='a' && letter<='y'))
letter = (letter+1);
else if(letter== 'Z' || letter== 'z')
letter =(letter-25);
out_stream << letter;
}

Related

Hidden characters in a std::string? string.length() is returning more than expected

Writing a homework problem where I encode any char (e.g. number, letter or punctuation), to its pre-supplied 'braille' string format (e.g. 'x' == "0.00.0").
I have decided to encode each char by declaring an empty string and appending this string (using += operator) with the relevant 'braille' code, using helper functions shown below:
string braille_ = "";
if(isdigit(ch))
encode_digit(ch, braille_);
else if(ispunct(ch))
encode_punctuation(ch, braille_);
else if(isalpha(ch))
encode_letter(ch, braille_);
else
braille_ = "......";
When I pass (for example) the letter 'Z' and the string by reference to the function below, it appends '|' to the string followed by ".....0|" (because it isupper) followed by "0.0.00" (the code for 'z').
void encode_letter(char ch, string& braille)
{
braille += '|';
if(isupper(ch)){
braille += ".....0";
ch = tolower(ch);
}
if(ch == 'a')
braille += "0.....";
else if(ch == 'b')
braille += "00....";
...
else if(ch == 'x')
braille == "0.00.0";
else if(ch == 'y')
braille += "0.0000";
else if(ch == 'z')
braille += "0.0.00";
My problem: When I cout the resulting string I get "|.....0|0.0.00". I count 14 characters in that string, yet when I do string.length() it returns 17. It appears that there are some hidden characters in there which don't show up when I print the string, but which add to its length.
This is happening across the board where I append to the string several times. Can anyone tell me what is going on? What are these hidden characters, if they exist at all? I'm not looking for an alternative method (I know there are many), I just want to understand the behaviour
EDIT: I have isolated the problem to when I use the += operator twice over as below. Minimal reproducible example:
string braille_ = "";
encode_letter('H', braille_);
void encode_letter(char ch, string& encoded)
{
size_t before = encoded.length();
encoded += ".....0|";
encoded += "00..0.|";
size_t after = encoded.length();
cout << ch << " = " << encoded << " with length growing from " << before <<
" to " << after << endl;
}
Expected output:
H = .....0|00..0.| with length growing from 0 to 14
Actual output:
H = .....0|00..0.| with length growing from 0 to 17

Determining the amount of letters in each word of a string in C++

I'm new to c++ and coding in general and I ran into a bit of an issue in one of my assignments. I'm just looking for some input and hopefully an explanation on why my code isn't working.
I'm trying to get input from a user and use a cin.get() function to count all the characters in that string. I do this because I want to determine the letters in each word of the string. Now my issues are I can't get it to print the result correctly.
My question is: Why can't I get a result when I try to determine if my variable chr is a '\n' character? chr is the variable that hold the value of the current character being read by the cin.get() function) is a '\n'.
I want to be able to update the parameters (word1, word2.....) of my function countWordsByLegth() when the current value of chr is '\n' or in other words the end of the string.
The following code, for example, won't run and it's the only way I know how to update my parameter for a string that contains no spaces (one word strings):
if (counter == 5 && chr == '\n')
{
++word5;
counter =0;
}
Here's my code for reference. The function isWhitespace() just determines if the character is one of the following '\n' , '\r' , '\t'):
while (cin.get(chr) && chr != '\n')
{
counter++;
if (isWhitespace(chr))
{
--counter;
//test = true;
}
if (counter == 5 && chr == '\n')
{
++word5;
counter =0;
}
if (counter == 4 && chr =='\n')
{
++word4;
counter =0;
}
if (counter == 3 && chr =='\n')
{
++word3;
counter =0;
}
if (counter == 2 && chr == '\n')
{
++word2;
counter =0;
}
if (counter ==1 && chr == '\n')
{
++word1;
counter =0;
}
cout << counter << endl; // Test code {delete later}
}
cout << "This is the total of word5: " << word5 << endl;
}
You could use std::string.length() to get the amount of chars in a string.
The length() function returns the number of chars in the string.
#include <iostream>
#include <string>
int main()
{
std::string s;
s = "test";
std::cout << "The string has " << s.length() << " letters!";
}
http://www.cplusplus.com/reference/string/string/ here you can read about the different functions that you can use with strings.

debugging c++ program with <set> containers

The problem is to find all vowels all even words in a sentence share, in other words these vowels have to be met in any even word in the sentence.
But i when i enter for example: "ewedyua aiuye dswidje ieuayj eeee eeeui dajhdfjcne aodijsbfe".
I get: e i u
but "e i" is expected as the last even word doesn't contain 'u' (I use " " just for separation here in the text and don't use them in the output)
The program:
int main(){
string str;
char ch = ' ';
set<char> strSet;
set<char> resultSet;
set<char> tempSet;
int count = 1;
int i = 0;
cout << "Enter a line: ";
getline(cin, str);
str = delOverSpace(str); // delete excessive gaps<br>
do {
ch = str.at(i);
if(((count % 2) == 0) && (ch != ' ')){ // this is an even word and not a gap
if(isVowel(upperToLower(ch))) // this is a vowel
tempSet.insert(upperToLower(ch));
}
if (ch == ' ') { // if we've passed through the word add inforamtion on it
if(((count % 2) == 0) && (count / 2) == 1)
strSet.insert(tempSet.begin(), tempSet.end());
else if (((count % 2) == 0) && (count / 2) != 1){
set_intersection(
strSet.begin(),strSet.end(), tempSet.begin(), tempSet.end(),
insert_iterator<set<char> >(resultSet, resultSet.begin())
);
strSet.clear();
tempSet.clear();
strSet.insert(resultSet.begin(), resultSet.end());
resultSet.clear();
}
count++;
}
i++;
}while(ch != '.');
if (count == 2) cout << "Only one word was entered" << endl;
else if (strSet.empty()) cout << "No vowels were found" << endl;
else {
copy(strSet.begin(), strSet.end(), ostream_iterator<char>(cout, " "));
cout << endl;
}
return 0;
}
Try not to use one counter variable for multiple purposes.
For example you could use count for the current character count within the current word and words for word count.
In your example, you're making count work too hard.
Decide what you are counting. Do you want to count every character?
Or do you want to count the characters in the current word?
When incrementing a counter, try to put this next to the logic that needs it.
Eg, i++ should go right after you've used it to get the next character.
And count should be incremented in the block that handles letters (ie not space, not dot).
If the counters get too far away from what they are keeping track of, you can introduce bugs.
Move the space check up first and also check for end of sentence with .
Clear indentation helps to follow the code - I use 4 characters, but 2 or 3 is ok.
1 character indents are hard to read.
Use blank lines to separate different chunks of logic.
You might want to add logic to handle punctuation like ,, ?, ! etc.
When you're processing an input string which is separated into words, it's often easier to handle the end of input condition outside the loop.
In this case, the loop exits after it picks up the last letter.
If that is not a . then you'll have an unprocessed word sitting in tempSet.
You can try and anticipate this within the loop, but it seems more natural to exit the loop and check if there is anything left to process.
If you separate your logic into clearly separated blocks, you can set breakpoints inside each block.
You'll then know what situation you're handling. You can break inside end-of-word logic and check tempSet and count.
Are they what you expect?
And in the else part you can check ch going in and verify that it is classified as a vowel properly.
int main() {
string str;
char ch = ' ';
set<char> strSet;
set<char> tempSet;
int count = 0, words = 0, i = 0;
cout << "Enter a line: ";
getline(cin, str);
str = delOverSpace(str); // delete excessive gaps<br>
while ( i < str.size() && ch != '.' ) {
// Get next character
ch = str.at(i);
i++;
if (ch == ' ' || ch == '.' ) { // if we've passed through the word add inforamtion on it
if( count > 0 && ((count % 2) == 0)) {
strSet.insert(tempSet.begin(), tempSet.end());
words++;
}
count = 0; // reset the char counter
tempSet.clear(); // clear the temp vowel set
}
else {
// letter - not a space or a dot, increase the character count
count++;
if(isVowel(upperToLower(ch))) // this is a vowel
tempSet.insert(upperToLower(ch));
}
}
// pick up any unprocessed word if we hit end of input without seeing '.'
if (count > 0 && ((count % 2) == 0)) {
strSet.insert(tempSet.begin(), tempSet.end());
words++;
}
if (words == 0)
cout << "No words entered" << endl;
else if (words == 1)
cout << "Only one word was entered" << endl;
else if (strSet.empty())
cout << "No vowels were found" << endl;
else {
copy(strSet.begin(), strSet.end(), ostream_iterator<char>(cout, " "));
cout << endl;
}
return 0;
}

What is wrong with this Pig Latin program?

What it's supposed to do
My piglatin program is supposed to take a phrase from user input and output it into pig latin. Basically it would turn a word such as "hello" into "ellohay".
My problem
When I input hello my man the output is ellohay y man an may and when I just input hello my the output is ellohay y may. As you can see, after it translates the first word successfully, it struggles on the second word. It places a space after the y and mayI cannot figure out for the life of me why this keeps happening. The output is even stranger when I input more than two words, as shown above. What I want to happen is for it to output ellohay ymay anmay when I input hello my man. Code is below. Thanks!
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
void phrase_Parser(string); // Goes through phrase and looks for ' ' to then pass to pigLatin_Translator()
void pigLatin_Translator(string);
int main()
{
string phrase; //used for user word or phrase to be translated to piglatin
cout << "Enter any word: ";
getline(cin, phrase);
phrase_Parser(phrase);
return 0;
}
void phrase_Parser(string phrase) {
int startCount = 0;
for (int i = 0; i < phrase.length(); i++) {
if (phrase[i] == ' ') {
string word = phrase.substr(startCount, i);
startCount = (i + 1); // decides where to start the word next time it is ran through
pigLatin_Translator(word); // runs word through translator
}
}
}
void pigLatin_Translator(string word) {
string partOne;
string partTwo;
for (int x = 0; x < word.length(); x++) {
if (word[0] == 'q' && word[1] == 'u') {
cout << word.substr(2, word.length()) << word.substr(0, 2) << "ay ";
break;
}
else if ((word[x] == 'a') || (word[x] == 'e') || (word[x] == 'i') || (word[x] == 'o') || (word[x] == 'u') || (word[x] == 'y')) {
partOne = word.substr(x, word.length()); //from first vowel to end of word
partTwo = word.substr(0, x); // from first letter to first vowel, not including the vowel
cout << partOne << partTwo << "ay "; // adding "ay" to the end of the word
break;
}
}
}
Your problem is in the line string word = phrase.substr(startCount, i);
You are using substr incorrectly. The second argument to substr is the length of the substring you wish to extract. Replace i with i-startCount and you should be good to go.
Alternatively, search for a nicer way to split strings. There are a number of options that are much easier than doing it manually.

Converting to lowercase at end of statement?

Slight issue. (Not using toupper() and tolower() functions) I understand what converting to uppercase and lowercase using numerical values is but following my C++ book, why is the conversion at the end of this statement and not before?:
if (letter >= 'A') //test for 'A' or larger
if (letter <= 'Z') //test for 'Z' or smaller
{
cout << endl
<< "You entered a capital letter."
<< endl;
letter += 'a' - 'A'; //Convert to lowercase
return 0;
}
if (letter >= 'a') //test for 'a' or larger
{
if (letter <= 'z') //test for 'z' or smaller
{
cout << endl
<< "You entered a small letter."
<< endl;
return 0;
}
}
Why would it convert the uppercase to lowercase at this point of code execution since the second if statement deals with lowercase input?
The given snippet could be the body of the function:
int convert(char& letter)
{
if (letter >= 'A' && letter <= 'Z')
{
letter += 'a' - 'A';
return 0; // go out of this function...
}
else if (letter >= 'a' && letter <= 'z')
{
letter += 'A' - 'a';
return 0; // go out of this function...
}
return -1; // it wasn't a letter as we expected
}
Note, that there's a possible path that doesn't match none of these 2 situation. Let's say that letter is '?', since you're returning int value, there should be an indication that something is wrong (it's up to you how you deal with error handling).
Possible usage of your this function could look like this:
char letter = '!';
if (convert(letter) == 0)
// success ...
else
// error ...
If the question is really about leaving the scope of function, then this question could be helpful too:
How to break out of a function
Concrete example:
void convertLetterAndPrintResult(char& letter)
{
if (convert(letter) == 0)
std::cout << letter << std::endl;
else
std::cout << "ERROR: '" << letter << "' is not valid character!" << std::endl;
}
int main()
{
char letter = '!';
convertLetterAndPrintResult(letter);
letter = 'g';
convertLetterAndPrintResult(letter);
letter = 'L';
convertLetterAndPrintResult(letter);
}
Output:
ERROR: '!' is not valid character!
G
l
Because there's a return 0; statement in the first part. If the original character was uppercase, the control flow doesn't even reach the second nested if () { if () { } } part.
Why would it convert the uppercase to lowercase at this point of code
execution since the second if statement deals with lowercase input?
That is because
return 0
means that the function is finished. The lines
if (letter >= 'a') //test for 'a' or larger
{
if (letter <= 'z') //test for 'z' or smaller
{
cout << endl
<< "You entered a small letter."
<< endl;
return 0;
}
}
will not be executed if letter was originally an upper case letter. It would print out "You entered a capital letter.", then convert it to lower case, then exit.
why is the conversion at the end of this statement and not before?
It would make no difference if the conversion were before the cout statement.