Looping back to the beginning of the alphabet after z - c++

I am working on a problem for school, and I have to write a program that rotates 13 characters. I have the program done, but it rotates into some weird characters. I want to make it look back to 'a' after it reaches 'z' for both uppercase and lowercase. Basically, I want to restrict my options to A-Z and a-z.
Tried a mixture of while statements and if statements, and ended up on with just some if statements. I know they are wrong, but it runs in its current state.
#include <iostream>
using namespace std;
//Function Prototypes
char rot(char c);
int mylen(char c[]);
int main()
{
char in[120], out[120];
int i; // index into in
cout << "Enter text: ";
cin.getline(in,120);
while (strcmp(in, "exit"))
{
for (i = 0; i < mylen(in); i++)
{
out[i] = rot(in[i]);
}
out[i++] = '\0';
cout << out << endl;
cout << endl << "Enter some more text: ";
cin.getline(in,120);
}
return 0;
}
char rot(char c)
{
if (c >= 'a' and c <= 'z')
c = c + 13;
if (c > 'z')
c = c - 26;
else if (c >= 'A' and c <= 'Z')
c = c + 13;
if (c > 'Z')
c = c - 26;
return c;
}
int mylen(char c[])
{
int cnt = 0;
while (c[cnt] != '\0')
cnt++;
return cnt;
}
I am looking just to have it rotate 13 characters, and when someone inputs rotated code, to rotate it again 13 characters.

I suggest you should carefully observe the table of ASCII code to display the character.There are 6 characters between the uppercase letter "A"~"Z" and the lowercase letter "a"~"z"
Here is my code:
if (c >= 'n' && c <= 'z')
{
c = c - 13;
}
else if (c >= 'a' && c <= 'm')
{
c = c + 13;
}
if (c >= 'N' && c<='Z')
{
c = c - 13;
}
else if (c >= 'A' && c <= 'M')
{
c = c+13;
}

Related

How to ignore white space and marks when encrypting a string variable in c++

I am trying to encrypt a string with white space and a question mark on it, for example, I am going to encrypt all the alphabet into numbers based on the order of the alphabet, but when I turn the string into numbers white space and question mark also gets enumerated how do I ignore that?
example)
int main() {
string alphabet;
int encrypted_code;
int first_int = 1, second_int = 2, third_int = 3;
string text = "hey what is your name?";
for (char ch = 'a'; ch <= 'z'; ch++) {
alphabet += ch;
}
for (int i = 0; i < text.length(); i++) {
encrypted_code = alphabet.find(text[i]);
if (i == 0 || i % 3 == 0) {
encrypted_code = encrypted_code + first_int;
}
cout << encrypted_code << " ";
}
}
Use an if statement to only work on letters:
for (int i = 0; i < text.length(); i++) {
if ('a' <= text[i] && text[i] <= 'z') {
// rest of your code goes here
}
}

Counting occurrence of each character in string C++

So i wanted to count all the characters in a string and categorized them in vowels, consonants, and specials character. For example;
Enter string: sentence example ..
Vowels: e(5) a(1)
Consonants: s(1) n(1) t(1) c(1) x(1) m(1) p(1) l(1)
Specials: blank space .(2)
Here's coding:
void characterType(string input)
{
int vowel = 0;
int consonant = 0;
int special = 0;
int n = input.size();
int freq[26];
memset(freq, 0, sizeof(freq));
for (int i = 0; i < n; i++)
{
freq[input[i] - 'a']++;
}
cout<<"Vowels: ";
for (int i = 0; i < n; i++)
{
char character = input[i];
if(isalpha(character))
{
character = tolower(character);
if (character == 'a' || character == 'e' || character == 'i' || character == 'o' || character == 'u')
{
cout<<input[i]<<freq[input[i] - 'a']<<" ";
}
}
}
cout<<endl;
cout<<"Consonants: ";
for (int i = 0; i < n; i++)
{
char character = input[i];
if(isalpha(character))
{
character = tolower(character);
if (character != 'a' || character != 'e' || character != 'i' || character != 'o' || character != 'u')
{
cout<<input[i]<<freq[input[i] - 'a']<<" ";
}
}
}
cout<<endl;
cout<<"Specials: ";
for (int i = 0; i < n; i++)
{
char character = input[i];
if(!isalpha(character))
{
if(character == ' ')
{
cout<<"[black space]"<<freq[input[i] - 'a']<<" ";
}
else
cout<<input[i]<<freq[input[i] - 'a']<<" ";
}
}
}
And heres what ive got so far:
How do i make it not repeat the same character and why does special characters is not counting?
Since you want to do this and it's not some type of assignment, here's how I would approach the problem, using modern C++ features:
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
int main() {
std::map<char, std::size_t> occurrance;
std::string input{"This is A long string with lots of characters in it. AAA$#!#$!^^! "};
auto is_vowel = [] (char c) -> bool
{
auto lc = std::tolower(c);
return
c == 'a' ||
c == 'e' ||
c == 'i' ||
c == 'o' ||
c == 'u';
};
auto is_special = [] (char c) -> bool
{
// use ascii table to find only "non-special characters"
if(c < '0') return true;
if(c > '9' && c < 'A') return true;
if(c > 'Z' && c < 'a') return true;
if(c > 'z') return true;
return false;
};
auto vowels = std::count_if(
input.begin(),
input.end(),
is_vowel);
auto special = std::count_if(
input.begin(),
input.end(),
is_special);
for(auto c : input)
{
occurrance[c] += 1;
}
std::cout << "Vowels: " << vowels << '\n';
std::cout << "Special: " << special << '\n';
for(auto [c, count] : occurrance)
{
std::cout << c << " -> " << count << '\n';
}
return 0;
}
https://ideone.com/YVaDiI
This does the job, although you can make the output prettier... and take the uppercase letters into account.
void printCharWithFreq(string str)
{
int v=0, c=0, s=0;
// size of the string 'str'
int n = str.size();
// 'freq[]' implemented as hash table
int freq[SIZE];
// initialize all elements of freq[] to 0
memset(freq, 0, sizeof(freq));
// accumulate freqeuncy of each character in 'str'
for (int i = 0; i < n; i++)
freq[str[i] - 'a']++;
// traverse 'str' from left to right
for (int i = 0; i < n; i++) {
// if frequency of character str[i] is not
// equal to 0
if (freq[str[i] - 'a'] != 0) {
// print the character along with its
// frequency
if(str[i] == 'a' || str[i] == 'e' || str[i] == 'i' || str[i] == 'o' || str[i] == 'u' ||
str[i] == 'A' || str[i] == 'E' || str[i] == 'I' || str[i] == 'O' || str[i] == 'U')
{ cout<<"Vowel: " << str[i] << freq[str[i] - 'a'] << " "<<endl; v+=freq[str[i] - 'a']; }
else if(str[i] == ' ' || str[i] == '.')
{ cout<<"Specials"<<endl; s++; }
else
{ cout<<"Consonant: " << str[i] << freq[str[i] - 'a'] << " "<<endl; c+=freq[str[i] - 'a']; }
// update frequency of str[i] to 0 so
// that the same character is not printed
// again
freq[str[i] - 'a'] = 0;
}
}
cout<<"Number of vowels: "<<v<<endl;
cout<<"Number of consonants: "<<c<<endl;
cout<<"Number of specials "<<s<<endl;
}
Then test it in the main function like
int main() {
string str = "some text . .";
printCharWithFreq(str);
return 0;
}
Basically, frequency is updated so it doesn't print the same character again, as it says in the comments. You also made a mistake in your code where you wrote:
character != 'a' || character != 'e' || character != 'i' || character != 'o' || character != 'u'
It is a consonant only if the input is different than ALL of the vowels, meaning you have to put &&, not ||.
As for the special characters, they can be counted with a simple counter.
The rest, I think, is clear from the comments in the code.
I adapted the code from the following source:
https://www.geeksforgeeks.org/print-characters-frequencies-order-occurrence/

Very Basic question c++) Why is my print answer different from what I wish to get?

Here is my simple source code:
char a, b;
cin >> a >> b;
if (a >= 'A' && a <= 'Z')
{
a = a + 'a' - 'A';
cout << a;
}
if (a >= 'a' && a <= 'z')
{
a = a + 'A' - 'a';
cout << a;
}
if (b >= 'A' && b <= 'Z')
{
b = b + 'a' - 'A';
cout << b;
}
if (b >= 'a' && b <= 'z')
{
b = b + 'A' - 'a';
cout << b;
}
return 0;
}
I want to change small letters into capitals and vice versa. Small letters works find but somehow capitals don't.
You second if statement, for example, has the effect of reversing the first if statement.
Writing
if (a >= 'A' && a <= 'Z')
{
a = a + 'a' - 'A';
cout << a;
}
else if (a >= 'a' && a <= 'z')
and so on, is the fix. (Note the else.) Apply the same scheme to b.
Once you have this working, use the C++ standard library functions std::islower, std::tolower, std::iuspper, and std::toupper instead. The code you present is not strictly portable as the standard does not guarantee that the alpha characters are in order.
The simpler approach would be to do it like this...
Check the value of a if it's upper or lower, then simply convert it accordingly.
char a, b;
cin >> a >> b;
if (isupper(a))
{
a = ::tolower(a);
} else {
a = ::toupper(a);
}
cout << a;
if (isupper(b))
{
b = ::tolower(b);
} else {
b = ::toupper(b)
}
cout << b;
return 0;
Edited to simplify code, thanks to Bathsheba

Reverse an array without affecting special characters

Is it possible to reverse an array without affecting the special characters ? By special characters, I mean anything characters not included from 'a' to 'z' and 'A' to 'Z'. I am short of ideas to build the algorithm, I still haven't it figured out.
One simple solution would be to Simple Solution:
1) Create a temporary character array --> ex: myArr[].
2) Copy alphabetic characters from the given array to myArr[].
3) Reverse myArr[] using standard string reversal algorithm.
4) Now traverse input string and myArr in a single loop. Wherever there is alphabetic character is input string, replace it with current character of myArr[].
Little problem with above solution, it requires extra space and it does two traversals of input string.
You can reverse with one traversal and without extra space. Below is algorithm.
1) Let input string be 'str[]' and length of string be 'a'
2) l = 0, r = a-1
3) While l is smaller than r, do following
a) If str[l] is not an alphabetic character, do l++
b) Else If str[r] is not an alphabetic character, do r--
c) Else swap str[l] and str[r]
Here's a solution that will do it "in place" in one pass.
bool isspecial(char c)
{
if ((c >= 'a') && (c <= 'z')) return false;
if ((c >= 'A') && (c <= 'Z')) return false;
return true;
}
void rev(char* array, int N)
{
int i = 0; // i points to the first index of the array
int j = N - 1; // j points to the last index of the array
while (i < j)
{
if (isspecial(array[i]))
{
i++;
}
else if (isspecial(array[j]))
{
j--;
}
else
{
char tmp = array[i];
array[i] = array[j];
array[j] = tmp;
i++;
j--;
}
}
}
Console.WriteLine("enter any string");
string str = Console.ReadLine();
string[] revstr = new string[str.Length];
for (int i = 0; i < str.Length; i++)
{
int ch = Convert.ToInt16(str.ToLower()[i]);
if ((ch < 97 || ch > 122))
{
revstr[i] = str[i].ToString();
}
}
for (int k = str.Length - 1; k >= 0; k--)
{
int ch = Convert.ToInt16(str.ToLower()[k]);
if (!(ch < 97 || ch > 122))
{
for (int j = 0; j < str.Length; j++)
{
if (revstr[j] == null)
{
revstr[j] = str[k].ToString();
break;
}
}
}
}
for (int s = 0; s < revstr.Length; s++)
{
Console.Write(revstr[s]);
}
If you want the position of the special characters to remain the same and the rest of the string to be reversed then this should work -
#include <iostream>
using namespace std;
void swap(char& a, char& b)
{
char temp = a;
a = b;
b = temp;
}
int main()
{
string s = "Hell$o World";
for(int i = 0, j = s.length() -1;i < s.length()/2; i++, j--) {
while((s[i] <= 'a' && s[i] >= 'Z') || s[i] >= 'z' || s[i] <= 'A') {
i++;
}
while((s[j] <= 'a' && s[j] >= 'Z') || s[j] >= 'z' || s[j] <= 'A') {
j--;
}
swap(s[i], s[j]);
}
cout << s << endl; //dlro$W olleH
return 0;
}

Changing letters by ascii value

I am trying to use ascii values to check different values of a letter to decipher a simple Cesar cipher. I am running into problems when the program tries to check a letter after z. I am using all lower case so if the letter is on z it should move to the beginning of the alphabet again. My code is as follows
#include <iostream>
using namespace std;
#include <string>
#include <vector>
int main()
{
string unencr;
char temp;
cout << "Enter string:" << endl << endl;
cin >> unencr;
for(int i = 0; i<26; i++){
for(int j = 0; j < unencr.size(); j++){
temp = unencr[j];
if ((int)temp + i <= 122){
temp = (int)temp + i;
}
if ((int)temp + i > 122){
temp = (((int)temp +i) % 122)+96;
}
cout << temp;
}
cout << endl;
}
return 0;
}
Your problem is that in your if statement you say (((int)temp +i) % 122)+96; But what if the char was 155 this would then make it equal to 130. Which is out of the bounds of a-z.
What you want to do instead: if(temp > 122) then you should (temp-122)%122 + 97 instead of moding it by itself.
To change a single character c, use this line:
c = ((c - 'a' + 13) % 26) + 'a';
c - 'a' // convert to position in the alphabet, 0 based
c - 'a' + 13 // rot13 (or any other shift that you want)
(c - 'a' + 13) % 26 // wrap around after 'z'
((c - 'a' + 13) % 26) + 'a' // convert it to ASCII again
Also you might want to embrace all of C++'s features:
#include <iostream>
#include <string>
int main() {
// read a whole line instead of a single word:
std::string str;
std::getline(std::cin, str);
// iterate over the string, not over the letters of the alphabet:
for (char &c : str) {
if (('a' <= c) && (c <= 'z')) {
c = (((c + 13) - 'a') % 26) + 'a';
}
}
std::cout << str << std::endl;
return 0;
}