I have made small encryption program that uses to keys rot7 and rot13. Everything works fine except two 6 letters uvwxyz.
If I type ABCDEFGHIJKLMNOPQRSTUVWXYZ it encrypts and decrypts no problem. However, if I enter the same in lower case letters then uvwxyz do not work.
Having said this, I have allowed all the writable characters within the ascii table as the valid range as follows:
// allow all writable characters from 32 to 255
if ((str[i] >= 32 ) && (str[i] <=255))
{
str[i] -= key;
}
Here is the process of encryption:
cout << endl;
cout << "Encrypting process started " << endl << endl;
cout << "--------------------------- " << endl;
//get the string length
int i = 0;
int length = str.length();
int key = rot13 ;
int k = 5;
int multiple = 0;
int count = 0;
cout << "the text to encrypt is: " << str << endl;
cout << "text length is: " << length << endl;
cout << "using rot13"<<endl;
cout <<"---------------------------" << endl;
cout << "using rot13" << endl;
//traverse the string
for(i = 0; i < length; i++)
{
count ++;
cout << left;
//if it is a multiple of 5 not the first character change the key
if((multiple = (( i % 5 ) == 0)) && (count != 1) && (key == rot13)){
key = rot7;
}
//if it is a multiple of 5 not the first character change the key
else if((multiple = (( i % 5 ) == 0)) && (count != 1) && (key == rot7) ) {
key = rot13;
}
// Capital letters are 65 to 90 (a - z)
if ((str[i] >= 32) && (str[i] <= 255))
{
str[i] += key;
}
}
return str;
How is it possible that the capital letters work and not the lower case if I have allowed this range? Can it be because of something else? I have added these captures with what happens step by step... hopefully this helps
In your code :
if ((str[i] >= 32) && (str[i] <= 255))
{
if (str[i] + key > 255)
str[i] = ((str[i] + key) % 255 )+ 32;
else
str[i] += key;
}
if key has a value of 13 and str[i] is 'u' or greater, str[i] has a value higher than 255.
You should use modulo % operator in this case, this is rotation, not only a shift
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 months ago.
Improve this question
I am making a program to calculate the value of words for a friend who is interested in numerology.
In my program, I ask the user how many words they want to calculate, so I can dynamically allocate the size of the array to store the words.
It works perfectly the first time they run the program, but when I ask if they want to test more words, and if they hit yes, it reruns the while loop and it asks them for how many words to evaluate, but this time, no matter what number they type, it always sets the size of the array to 1, due to the number variable being set to 1 and not changing after user input. My friend has to rerun the program to make it work again.
I really want to fix this problem to make it easier for my friend.
(Yes, I do plan on fixing my code, and if you have seen this code in another question, that was me, and yes, I am going to improve my code based on the suggestions I got, but I want it to at least work before I improve on it.)
Here is my code:
#include <iostream>
#include <string>
#include <sstream>
void clear()
{
system("clear");
}
int main(int argc, char* argv[])
{
int number{1};
int total{0};
int value{0};
std::string number_str;
std::string response;
std::stringstream ss;
bool isDigit;
while (true)
{
clear();
number = 1;
total = 0;
value = 0;
number_str = "";
response = "";
isDigit = true;
clear();
std::cout << "How many words to evalute? (Default: 1):\n> ";
//std::cin >> number;
std::getline(std::cin, number_str);
//std::cin.ignore();
clear();
for (int i = 0; i < number_str.size(); ++i)
{
if (!(std::isdigit(number_str[i])))
isDigit = false;
break;
}
if (isDigit)
{
if (number_str.empty()) {
number = 1;
} else {
ss << number_str;
ss >> number;
}
}
if (std::isdigit(number)) {
if (number <= 0) {
number = 1;
}
}
std::string* pPhrase = new std::string[number];
int* pValue = new int[number]{}; // Initialized each element to 0
for (int i = 0; i < number; ++i) // could replace "number" with "sizeof(pPhrase)/sizeof(pPhrase[0])"
{
(i == 0) ? std::cout << "Enter Word #" << i+1 << " (or type your full phrase):\n> " :
std::cout << "Enter Word #" << i+1 << ":\n> ";
std::cin >> pPhrase[i];
for (char j : pPhrase[i])
{
value = 0;
if (std::isalnum(j) && j != '0')
{
if (std::isalpha(j))
j = std::tolower(j);
} else {
continue;
}
if (j == 'a' || j == 'i' || j == 'j'
|| j == 'q' || j == 'y' || j == '1')
value += 1;
if (j == 'b' || j == 'k' || j == 'r' || j == '2')
value += 2;
if (j == 'c' || j == 'g' || j == 'l'
|| j == 's' || j == '3')
value += 3;
if (j == 'd' || j == 'm' || j == 't' || j == '4')
value += 4;
if (j == 'e' || j == 'h' || j == 'n'
|| j == 'x' || j == '5')
value += 5;
if (j == 'u' || j == 'v' || j == 'w' || j == '6')
value += 6;
if (j == 'o' || j == 'z' || j == '7')
value += 7;
if (j == 'f' || j == 'p' || j == '8')
value += 8;
pValue[i] += value;
value = 0;
std::cout << '\n';
clear();
}
}
std::cin.ignore();
std::cin.clear();
std::cout << "\n\n";
for (int i = 0; i < number; ++i)
{
std::cout << "Value of \"" << pPhrase[i] << "\": " << pValue[i] << '\n';
total += pValue[i];
}
std::cout << "Total value: " << total << "\n\nPress \'Enter\' or \'Return\' to Continue... ";
//std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
//std::cin.clear();
std::cout << "\n\n\nWould you like to evaluate another phrase? (Y/n):\n> ";
std::getline(std::cin, response);
delete[] pPhrase;
delete[] pValue;
if (response[0] == 'y' || response[0] == 'Y'
|| response.empty() || response[0] == ' ')
continue;
break;
}
std::cout << "Exiting...";
try {
//system("killall Terminal");
} catch (std::exception& ex) {}
std::cout << "\n\n\n";
return 0;
}
for (int i = 0; i < number; ++i) // could replace "number" with "sizeof(pPhrase)/sizeof(pPhrase[0])"
Actually, you can't use the sizeof(array)/sizeof(array[0]) trick on a pointer to an array. It only works when you use it directly on the actual array itself. There are numerous questions on StackOverflow that explain this, including (just to name a few):
How to get the size of an array using a pointer to the first element and properties of "\0"?
Pointer to an array get size C++
getting size of array from pointer c++
In any case, one problem I do see in your code is that on each iteration of the outer while loop, you are not resetting the std::stringstream that you use to convert the user's input to the number variable. Each iteration is just pushing more and more data into the stream without removing the old data first.
Also, using std::isdigit(number) is useless. You already validated the user entered only digits, and then converted those digits to the number variable. What you didn't do is validate that the conversion to int was actually successful before using number. You must validate that the extraction of the number from the stringstream is successful, ie in case the user enters a large value that can't fit into an int.
Try this instead:
while (true)
{
clear();
number = 1;
total = 0;
value = 0;
number_str = "";
response = "";
isDigit = true;
// ADD THIS!
ss.str("");
ss.clear();
//
...
if (isDigit)
{
ss << number_str;
if (!(ss >> number) { // <-- ADD THIS!
number = 1;
}
}
...
}
That being said, you could just get rid of the stringstream altogether, you don't actually need it. You can extract the number value directly from std::cin itself (which you are already aware of, because you commented out that code), eg:
std::cout << "How many words to evalute? (Default: 1):\n> ";
if (!(std::cin >> number)) {
number = 1;
std::cin.clear();
}
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// no need for the `isdigit() check at all...
I've been working on this code for a while now and I keep getting the same terminal error. I have narrowed the issue down to two at functions. I've looked it up but the only answer I can seem to find is if the coder used the wrong variable in a for loop or that the variable in the at function isn't indexed properly.
Can't seem to figure out why the str.at() functions specifically are throwing errors when the variable str should be initialized. The at functions in question are the second and fourth if statements inside the do-while loop.
Here's the code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
// start main function
int main()
{
ifstream infile;
string line;
string str;
int words = 0;
int charsNotIncludingSpaces = 0;
int charsIncludingSpaces = 0;
int wordsEndingWithE = 0;
int sixLetterWords = 0;
int wordsBeginningWithVowel = 0;
int wordsContainingATE = 0;
int allEs = 0;
int wordsWithAtleastTwoEs = 0;
infile.open("USDictionary.txt");
// read the first line from the file
getline(infile, line);
while(!infile.eof())
{
unsigned int startIndex = 0;
unsigned int endIndex = 0;
// get each word from the line and find the required results
do
{
endIndex = line.find(' ', startIndex);
if(endIndex > 0 && endIndex < line.size())
{
str = line.substr(startIndex, endIndex - startIndex);
}
else
{
str = line.substr(startIndex);
}
startIndex = endIndex + 1;
words++;
charsNotIncludingSpaces += str.size();
if(str.at(str.size() - 1) == 'e')
{
wordsEndingWithE++;
}
if(str.size() == 6)
{
sixLetterWords++;
}
if(str.at(0) == 'a' || str.at(0) == 'A'
|| str.at(0) == 'e' || str.at(0) == 'E'
|| str.at(0) == 'i' || str.at(0) == 'I'
|| str.at(0) == 'o' || str.at(0) == 'O'
|| str.at(0) == 'u' || str.at(0) == 'U')
{
wordsBeginningWithVowel++;
}
unsigned int ateIndex = str.find("ate");
if (ateIndex >= 0 && ateIndex < str.size())
{
wordsContainingATE++;
}
for (unsigned int k = 0; k < str.size(); k++)
{
if(str.at(k) == 'e')
allEs++;
}
if (str.find_first_of('e') != str.find_last_of('e'))
{
wordsWithAtleastTwoEs++;
}
} while (endIndex > 0 && endIndex < line.size());
charsIncludingSpaces += line.size();
// read the next line from the file
getline(infile, line);
}
infile.close();
/*// print the results
cout << "Total number of words in the dictionary: "
<< words << endl;
cout << "Total number of characters in the dictionary (not including white spaces): "
<< charsNotIncludingSpaces << endl;
cout << "Total number of characters in the dictionary (including white spaces): "
<< charsIncludingSpaces << endl;
cout << "Total number of words ending in the letter e: "
<< wordsEndingWithE << endl;
cout << "Total number of 6 letter words: "
<< sixLetterWords << endl;
cout << "Total number of words beginning with a vowel: "
<< wordsBeginningWithVowel << endl;
cout << "Total number of words containing the substring \"ate\": "
<< wordsContainingATE << endl;
cout << "Total number of occurances of the letter e: "
<< allEs << endl;
cout << "Total number of words containing at least two occurances of the letter e: "
<< wordsWithAtleastTwoEs << endl;*/
return 0;
}
I am learning C++. I am having a problem where I am allocating memory without the new keyword. The memory leak starts from UserInputCharArray[size - 1] = aChar. I am assigning a character to a memory location which is not allocated using the new keyword.
Can anyone help me solve this issue to allocate memory using the new keyword?
Here is an image when I run:
Here is my code:
#include <iostream>
using namespace std;
// Creating a function for high frequency letters by passing in our vowels and
// a boolean for moving from lower-case vowels to upper-case vowels.
void highestFreq(int a, int e, int i, int o, int u, bool isLow) {
// Declaring variables.
int maximumCount = 0;
char mainChar;
// Creating an array of five for the vowels.
int arr[5];
arr[0] = a;
arr[1] = e;
arr[2] = i;
arr[3] = o;
arr[4] = u;
// Set counter to zero.
int counter = 0;
// Looping through the vowels starting with value 1 -> 5.
for (int x = 1; x < 5; x++) {
// Count when array is less than
if (arr[counter] < arr[x])
counter = x;
}
// Looping through the vowels starting with value 0 -> 5
for (int x = 0; x < 5; x++) {
// count plus one.
if (arr[counter] == arr[x])
maximumCount += 1;
}
// Checking with the vowels.
if (counter == 0)
mainChar = 'a';
else if (counter == 1)
mainChar = 'e';
else if (counter == 2)
mainChar = 'i';
else if (counter == 3)
mainChar = 'o';
else if (counter == 4)
mainChar = 'u';
// Moving from lower case letter to upper case letter.
if (!isLow)
// Conversion happening here from lower-case to upper-case letters.
mainChar = mainChar - 'a' + 'A';
// If there are multiple high frequency letters then a message needs to be passed in there.
if (maximumCount > 1) {
// checking to see if there are no lower case vowels .
if (isLow)
// Display - if there is no lower case vowels or there is no
// upper case vowels.
cout << "There are no lower ";
else
// Otherwise - display there are no upper case vowels
cout << "There are no upper ";
cout << "case vowels" << "\n";
}
else {
// Otherwise - display the highest frequency letters.
cout << "The highest frequency ";
// Checking to see if there is any high frequency letters.
if (isLow)
// Displaying lower case vowels
cout << "lower ";
else
// Displaying upper case vowels
cout << "upper ";
// Display how many high frequency vowels are their.
cout << "case vowel is " << mainChar << " with a frequency of " << arr[counter] << "\n";
}
}
int main() {
// A char is being used - for the user to still continue with the program.
char userInputProceed = 'y';
// Looping begin for user to continue.
while (userInputProceed == 'Y' || userInputProceed == 'y') {
// Declaration for the lower-case and upper-case vowels.
int low_a, low_e, low_i, low_o, low_u;
int high_A, high_E, high_I, high_O, high_U;
// Initializing the count of lower-case and upper-case vowels.
low_a = low_e = low_i = low_o = low_u = 0;
high_A = high_E = high_I = high_O = high_U = 0;
// Setting a size starting from one.
int size = 1;
// Declaring a variable of type char.
char aChar;
// Declaring a size to be using the new operator.
char *UserInputCharArray = new char[size];
// Prompt the user to enter a string.
cout << "Enter a string: ";
// Capturing userInput, one char at a time.
aChar = cin.get();
// A loop that will be taking values from the input stream and it will
// count the size of input. \n
while (aChar != 10) {
// Count size of input.
UserInputCharArray[size - 1] = aChar;
// Getting each size and add one.
size += 1;
// Then get the char one at a time - once more.
aChar = cin.get();
}
// The loop process of the vowels.
for (int x = 0; x < size; x++) {
aChar = *(UserInputCharArray + x);
if (aChar - 'a' == 0)
low_a += 1;
else if (aChar - 'e' == 0)
low_e += 1;
else if (aChar - 'i' == 0)
low_i += 1;
else if (aChar - 'o' == 0)
low_o += 1;
else if (aChar - 'u' == 0)
low_u += 1;
else if (aChar - 'A' == 0)
high_A += 1;
else if (aChar - 'E' == 0)
high_E += 1;
else if (aChar - 'I' == 0)
high_I += 1;
else if (aChar - 'O' == 0)
high_O += 1;
else if (aChar - 'U' == 0)
high_U += 1;
}
// Displaying lower-case vowels with their frequency and display - following with
// if the count of any vowel is zero then it will not be displayed.
if (low_a > 0 || low_e > 0 || low_i > 0 || low_o > 0 || low_u > 0) {
cout << "The lower-case vowels which are present are: ";
if (low_a > 0)
cout << "a (" << low_a << ")";
if (low_e > 0)
cout << "e (" << low_e << ")";
if (low_i > 0)
cout << "i (" << low_i << ")";
if (low_o > 0)
cout << "o (" << low_o << ")";
if (low_u > 0)
cout << "u (" << low_u << ")";
cout << endl;
}
// Displaying upper case vowels with their frequency and display - following with
// if the count of any vowel is zero then it will not be displayed.
if (high_A > 0 || high_E > 0 || high_I > 0 || high_O > 0 || high_U > 0) {
cout << "The upper-case vowels which are present are: ";
if (high_A > 0)
cout << "A (" << high_A << ")";
if (high_E > 0)
cout << "E (" << high_E << ")";
if (high_I > 0)
cout << "I (" << high_I << ")";
if (high_O > 0)
cout << "O (" << high_O << ")";
if (high_U > 0)
cout << "U (" << high_U << ")";
cout << endl;
}
// Calling out the high frequency letter function.
highestFreq(low_a, low_e, low_i, low_o, low_u, true);
highestFreq(high_A, high_E, high_I, high_O, high_U, false);
// Using the delete operator.
delete[] UserInputCharArray;
// Waiting for the user input if they want to continue with the program.
cout << "To continue enter y or Y, anything else will quit the program" << endl;
// Getting the user input to continue with the program.
cin >> userInputProceed;
// Wait for userInput until he/she quits.
cin.get();
}
return 0;
}
Updated Code
#include <iostream>
#include <string>
using namespace std;
// ----- REFACTORED MY CODE. ------
// Returning a lower case vowels.
char LowVowel(int x) {
switch(x) {
case 0:
return 'a';
break;
case 1:
return 'e';
break;
case 2:
return 'i';
break;
case 3:
return 'o';
break;
case 4:
return 'u';
break;
}
}
// Returning a upper case vowels.
char UpperVowel(int x) {
switch (x) {
case 0:
return 'A';
break;
case 1:
return 'E';
break;
case 2:
return 'I';
break;
case 3:
return 'O';
break;
case 4:
return 'U';
break;
}
}
// Initializing the array to be used for upper and lower cases frequency.
void init(int arr[]) {
for (int x = 0; x < 5; x++) {
arr[x] = 0;
}
}
int main() {
// Declaring a variable of type char
char aChar;
// Allocation of memory to a character pointer as per the size of
// the entered input.
char *cPointer = new char;
// Store an array for the frequency of lower and upper vowels.
int arr[5];
// counter and maximum to be stored for our maximum frequency.
int counter = 0, maximum;
// Prompting the user to enter a string.
cout << "Enter a string: ";
// Capturing userInput.
aChar = cin.get();
while (aChar != '\n') {
// increment counter.
counter++;
// then if enter key is pressed - stop entering data.
if (aChar == '\n')
break;
// Storing the accepted char inside the pointer.
*(cPointer + counter) = aChar;
// Increase the counter.
aChar = cin.get();
}
// Initializing the arr array
init(arr);
// Looping until the end of inputted information.
for (int x = 0; x < counter; x++) {
// Checking the lower case vowels
// and even increase the counter
if (*(cPointer + x) == 'a')
arr[0]++;
else if (*(cPointer + x) == 'e')
arr[1]++;
else if (*(cPointer + x) == 'i')
arr[2]++;
else if (*(cPointer + x) == 'o')
arr[3]++;
else if (*(cPointer + x) == 'u')
arr[4]++;
}
// Display lower case vowels results.
cout << "The lower-case vowels which are present are: \n ";
// Looping..
for (int x = 0; x < 5; x++) {
// find the maximum frequency.
maximum = arr[x];
if (arr[x] > maximum)
maximum = x;
// then if the frequency value not zero then
// display.
if (arr[x] != 0) {
cout << LowVowel(x)
<< " ( " << arr[x] << " )";
}
}
// Display lower case vowels.
cout << "Lower case vowel " << LowVowel(maximum)
<< " which appears most frequently = " << arr[maximum];
// init the arr array .
init(arr);
// looping once again for the entered info.
for (int x = 0; x < counter; x++) {
// checking the upper case vowels
// and increasing the counter once again.
if (*(cPointer + x) == 'A')
arr[0]++;
else if (*(cPointer + x) == 'E')
arr[1]++;
else if (*(cPointer + x) == 'I')
arr[2]++;
else if (*(cPointer + x) == 'O')
arr[3]++;
else if (*(cPointer + x) == 'U')
arr[4]++;
}
// Display upper case vowels.
cout << "Upper case vowels and its frequency" << endl;
// looping
for (int x = 0; x < 5; x++) {
// finding the maximum freq.
maximum = arr[x];
if (arr[x] > maximum)
maximum = x;
// if the frequency value is not zero then display.
if (arr[x] != 0) {
cout << "\n Vowel " << UpperVowel(x) << " occurred " << arr[x] << " times";
}
}
cout << "Upper case vowel " << UpperVowel(maximum) << " which appears most frequently = " << arr[maximum];
}
I am assigning a character to a memory location which I am not even
allocated memory using the 'new' keyword.
Actually, you have allocated memory for that location... Specifically, you declare and allocate 1-char of data with:
int size = 1;
char *UserInputCharArray = new char[size];
So the pointer UserInputCharArray points to a valid block of memory of size 1. The value at that memory address can be accessed by dereferencing the pointer with either:
*UserInputCharArray;
or
UserInputCharArray[0]; (or UserInputCharArray[size-1] as you used)
(the [] operator acts as a dereference.)
Both are equivalent. However, when using [], you are limited to the single index 0. Anything more (e.g. 1) would invoke Undefined Behavior as an attempt to access memory outside the bounds of the block you allocated. (as you do in your loop beginning when size = 2)
Why Not Use string?
While you are free to manage the storage needs for UserInputCharArray your self with new and delete, you are far better served using the features of C++ (namely the string handling provides by #include <string>) that will provide automatic memory management for UserInputCharArray, e.g. you can #include <string> and change:
char *UserInputCharArray = new char[size];
to
string UserInputCharArray;
and then:
UserInputCharArray[size - 1] = aChar;
to
UserInputCharArray.push_back(aChar);
The memory will then also be freed when UserInputCharArray goes out of scope.
Note, you have additional logic errors with your code.
I need a little help figuring out a couple of parts from a C++ assignment. I am asked to write a program as follows:
Write a program that accepts input from the keyboard (with the input
terminated by pressing the Enter key) and counts the number of letters (A-Z and a-z), numerical digits (0-9), and other characters. Input the string using cin and use the following looping structure to examine each character in the string with an "if" statement and multiple "else if" statements.
char s[50];
int i;
. . .
i = 0;
while (s[i] != 0) { // a string is terminated with a null (0) value
. . .
i++;
}
Your program should make use of the relational operators (e.g., == < > <= >= !=) to determine whether a particular character is a letter, number, or other character. You may only #include and
may not use any other include files.
The program should have an output similar to the following:
Enter a continuous string of characters with no blank spaces (example: aBc1234!##$%)
enter your string: aBc1234!##$%
your string has 12 total characters
3 letters
4 numerical characters
5 other characters
Here is an example program that counts lower case letters:
// PROG07.CPP example
#include <iostream>
using namespace std;
int main()
{
char s[50];
int i;
int lowercase = 0;
//get string from the user
cout << "Enter a continuous string of characters with no blanspaces\n"
cout << "(example: aBc1234!##$%)" << endl << endl;
cout << "Enter your string: ";
cin >> s;
cout << endl;
// loop through the string, lower case letters
// note, strings (character arrays) have an invisible
// zero value at their end
i = 0;
while (s[i] != 0) // while the character does not have ASCII code zero
{
if ((s[i] >= 'a' && s[i] <= 'z'))
lowercase++;
i++;
}
cout << "Your string has " << lowercase << " lower case letters" << endl;
// including the next line for Dev-C++:
system("pause"); // not needed for CodeBlocks
return 0;
}
So far, I have come up with this:
#include <iostream>
using namespace std;
int main()
{
char s[50];
int i;
int lowercase, uppercase, numChars, otherChars = 0;
cout << "Enter a continuous string of characters" << endl;
cout << "(example: aBc1234!##$%)" << endl;
cout << "Enter your string: ";
cin >> s;
cout << endl;
while (s[i] != 0) // while the character does not have ASCII code zero
{
if ((s[i] >= 'a' && s[i] <= 'z'))
lowercase++;
i++;
}
while (s[i] != 0)
{
if ((s[i] >= 'A' && s[i] <= 'Z'))
uppercase++;
i++;
}
cout << lowercase + uppercase << " letters" << endl;
i = 0;
while (s[i] != 0)
{
if ((s[i] >= '0' && s[i] <= '9'))
numChars++;
i++;
}
cout << numChars << " numerical characters" << endl;
return 0;
}
Any help would be greatly appreciated.
You have to reset i to 0 before every loop:
#include <iostream>
using namespace std;
int main()
{
char s[50];
int i;
int lowercase, uppercase, numChars, otherChars = 0;
cout << "Enter a continuous string of characters" << endl;
cout << "(example: aBc1234!##$%)" << endl;
cout << "Enter your string: ";
cin >> s;
cout << endl;
i = 0; //missing
while (s[i] != 0) // while the character does not have ASCII code zero
{
if ((s[i] >= 'a' && s[i] <= 'z'))
lowercase++;
i++;
}
i = 0; // missing
while (s[i] != 0)
{
if ((s[i] >= 'A' && s[i] <= 'Z'))
uppercase++;
i++;
}
cout << lowercase + uppercase << " letters" << endl;
i = 0;
while (s[i] != 0)
{
if ((s[i] >= '0' && s[i] <= '9'))
numChars++;
i++;
}
cout << numChars << " numerical characters" << endl;
return 0;
}
Looks good so far, just a few things
First off, you only need the one while loop:
while (s[i] != 0)
{
//All your if checks can go in here
}
Then, according to the output you need, you will need 4 variables:
int total, lettters, numbers, otherCharacters;
At the start of your loop, add to total:
while (s[i] != 0)
{
total++;
}
Then you will need 3 if checks inside your while loop, one for letters, one for numbers, and one for other characters:
if ((s[i] > 'a' && s[i] < 'z') || (s[i] > 'A' && s[i] < 'Z')) { ... }
else if (s[i] > '0' && s[i] < '9') { ... }
else { ... }
Then just output all your variables according to the output you mentioned:
cout << "your string has " << total << " total characters, " << letters << " letters, " << numbers << " numerical characters, and " << otherCharacters << " characters.";
i cant seem to figure out what wrong
for some reason it wont compile and it think theres a problem on my jumbleString function
#include <iostream>
#include <iomanip>
#include <string>
#include <istream>
using namespace std;
int main ()
{
int lengthofstring, x, countWords(string str), countConsonant(string str, int), consonant, jumbleString(string str);
string str, str2, wordone;
char options;
cout << "Please enter a word, a sentence, or a string of numbers." << endl;
getline(cin, str);
//cin >> str;
lengthofstring = str.length();
str2=str;
bool another= true;
while (another)
{
cout << '\n' << "USE THIS MENU TO MANIPULATE YOUR STRING" << endl;
cout << "---------------------------------------" << endl;
cout << "1) Inverse String" << endl;
cout << "2) Reverse String" << endl;
cout << "3) To Uppercase" << endl;
cout << "4) Jumble String" << endl;
cout << "5) Count Number Words" << endl;
cout << "6) Count Consonants" << endl;
cout << "7) Enter a Different String" << endl;
cout << "8) Print the String" << endl;
cout << "Q) Quit" << endl;
cin >> options;
switch (options)
{
case '1':
for (x = 0; x < lengthofstring; x++)
{
if (islower(str[x]))
str[x] = toupper(str[x]);
else if (isupper(str[x]))
str[x] = tolower(str[x]);
}
cout<< str;
break;
case '2':
for (x = 0; x < lengthofstring; x++)
{
str2[x] = str[lengthofstring-1-x];
}
cout<< str2;
break;
case '3':
{
for (x = 0; x < lengthofstring; x++)
{
if (islower(str[x]))
str[x] = toupper(str[x]);
}
cout<< str;
}
break;
case '4':
jumbleString(str);
break;
case '5':
cout << countWords(str);
break;
case '6':
consonant = 0;
cout<< countConsonant(str, consonant);
break;
case '7':
cout << "Please enter another word, a sentence, or a string of numbers." << endl;
cin.ignore();
getline(cin, str);
cout << str <<endl;
break;
case '8':
cout<< str2;
break;
case 'q':
another = false;
break;
}
}
cin.get();
cin.get();
return 0;
}
void jumbleString(string str)
{
int length = str.length();
int j, k;
for(int i = 0; i < length; j++)
{
k = rand() % length;
j = rand() % length;
char c = str[j];
str[j] = str[k];
str[k] = c;
}
cout << str<<endl;
}
int countWords(string str)
{
int length = str.length();
int words = 1;
for(int size = 1; length > size; size++)
{
if (str[size] == ' ' && str[size-1] != ' ')
words++;
}
if (str[0] == ' ')
words--;
return words;
}
int countConsonant(string str, int consonant)
{
int length = str.length();
consonant = 0;
for (int i = 0; i < length; i++)
{
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' && str[i] != ' '&& str[i] != '1'
&& str[i] != '2' && str[i] != '3' && str[i] != '4' && str[i] != '5' && str[i] != '6'
&& str[i] != '7' && str[i] != '8' && str[i] != '9' && str[i] != '0')
consonant = consonant + 1;
}
return consonant;
}
the problem is changing i inside the loop (I guess you meant to change k):
if you did mean to set k, change i = rand() % length; into k = rand() % length;
also, your question is a variant of the permutation problem, which Fisher-Yates solves. I would suggest looking at it, you will probably get better "randomness" by using it.
You are mistakenly using the loop variable, i , twice here. Also you might want to seed the random number generator if you want truly random jumbling of the strings.
For an idiomatic way of doing this in c++ you can use the standard algorithms to do this as follows:
#include <iostream>
#include <algorithm>
#include <ctime>
#include <cstdlib>
int main(void){
srand ( unsigned ( time (NULL) ) );//seed the random shuffle
std::string test = "abcdef";
std::cout << "original string: " << test << std::endl;
std::random_shuffle(test.begin(),test.end());
std::cout << "shuffled string: " << test << std::endl;
return 0;
}
You are using i, j for your two random indices whereas these should be j, k.
It should be:
j = rand() % length;
k = rand() % length;
You are using i as loop variable but at the same time assign a random value to it within the loop.
A possible solution would be not to use two randoms at all but instead the iterating variable i itself [online example].
for(int i = 0; i < length; i++)
{
j = i + (rand() % (length-i));
char c = str[j];
str[j] = str[i];
str[i] = c;
}