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.";
Related
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 have a text file containing sort of a graph presentation, as such:
7
{5, 2, 3}, {1,5}, { }, { }, {3}, { }, { }
Now, I know how to read a file and get in into an int
while ((n = myfile.get()) != EOF)
or into a string line by line
getline (myfile,line)
The problem I have, is that with both of these options I can't really seem to compare every character I extract and check if it's a number or a "," or "{" or "}".
Is there a simple way of doing that? I've been banging my head with this for hours since yesterday. I've tried some isdigit and casting, but that didn't work for me as well and really complicated stuff.
The easiest solution, I think, would be to get your hands dirty a bit, by reading the file char by char. I suggest you store the sets in a vector of vectors of ints (visualize it like a 2D array, a matrix, if you like).
If the i-th set is empty, then the i-th vector will be empty too.
In the loop in which you will parse the characters, you will skip the opening curly braces and commas. You will do similarly for the closing curly braces, except from the fact that you would need to update an index, which will help us update the index-th vector.
When we actually read a digit, then you can convert a char to an int.
Complete example:
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
int main(void) {
char ch;
fstream fin("test.txt", fstream::in);
if(!fin) {
cerr << "Something is wrong...! Exiting..." << endl;
return -1;
}
int N; // number of sets
fin >> N;
vector<vector<int> > v;
v.resize(N);
int i = 0;
while (fin >> ch) {
//cout << ch << endl;
if(ch == '{' || ch == ',')
continue;
if(ch == '}') {
i++;
continue;
}
v[i].push_back(ch - '0');
}
if(i == N) {
cout << "Parsing the file completed successfully." << endl;
} else {
cout << "Parsed only " << i << " sets, instead of " << N << endl;
}
for(size_t i = 0; i < v.size(); ++i) {
if(v[i].size() == 0)
cout << i + 1 << "-th set is empty\n";
else {
for(size_t j = 0; j < v[i].size(); ++j)
cout << v[i][j] << " ";
cout << endl;
}
}
return 0;
}
Output:
gsamaras#aristotelis:/Storage/homes/gsamaras$ g++ main.cpp
gsamaras#aristotelis:/Storage/homes/gsamaras$ ./a.out
Parsing the file completed successfully.
5 2 3
1 5
3-th set is empty
4-th set is empty
3
6-th set is empty
7-th set is empty
Important note: This should serve as a starting point, since it won't treat numbers that have more than one digits. In this case, you will to read up to the comma, or the closing curly brace, to make sure that you read all the digits of the numbers, then convert from string to integer, and then store it in the corresponding vector.
Its better to read character by character as follows:
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main()
{
string line;
int lineNum = 0;
ifstream myfile ("file.txt");
if (myfile.is_open())
{
while ( getline (myfile, line) )
{
// Identifying the type of charcter
char a;
cout << "Line Number " << ++lineNum << ": ";
for(int i = 0; i < line.length(); i++)
{
a = line[i];
cout << "\n\t" << a;
if((a >= 32 && a <= 47) || (a >= 58 && a <= 64) || (a >= 91 && a <= 96) || (a >= 123 && a <= 126))
{
cout << "\t(This character is either a Punctuation or arithmetic mark.)";
// If you don't want to porcess these character, then you may 'continue' to the next sub string
}
else if(a >= 48 && a <= 57)
{
cout << "\t(This character is a number.)";
// If you want to change the number ot int, you can use atoi or stoi
}
else if(a >= 65 && a <= 90)
cout << "\t(Capital letter)";
else if(a >= 97 && a <= 122)
cout << "\t(Small letter)";
}
cout<<endl;
}
myfile.close();
}
else
cout << "Unable to open file";
return 0;
}
I hop this helps.
Hi I am working on an encryption program. The program should take a letter inputted by the user and replace it with the corresponding letter 11 places further down the alphabet. For example, if the user inputs "joe" the program should output "uzp".
My current code does this fine but it doesn't recognise spaces and the program should wrap-around the alphabet. So that'Y' becomes 'J' and 'Z' would become 'K' etc. Anyone know how I could fix this?
void encrypt(std::string &e);
int main() {
string nameAttempt;
cout << "Enter your name to be Encrypted: ";
cin >> nameAttempt;
cout << "Original string is: " << nameAttempt << endl;
encrypt( nameAttempt );
cout << "Encrypted string is: " << nameAttempt << endl;
system("pause");
return 0;
}
void encrypt (std::string &e) {
const char* tempCharArray = e.c_str();
for( int i=0; i<e.size(); ++i )
e[i] = tempCharArray[i]+11;
} //
Assuming that you want to:
Replace lower-case letters with lower-case letters
Replace upper-case letters with upper-case letters
Leave spaces and any other non-alphabetic characters as is
void encrypt (std::string &e)
{
int size = e.size();
for (int i=0; i<size; i++)
{
char c = e[i];
if (('A' <= c && c <= 'Z'-11) || ('a' <= c && c <= 'z'-11))
e[i] = c+11;
else if ('Z'-11 < c && c <= 'Z')
e[i] = c+11-'Z'+'A';
else if ('z'-11 < c && c <= 'z')
e[i] = c+11-'z'+'a';
}
}
You could do something like this:
char _character='X';
int _value=static_cast<int>(_character);
if(_value!=32)//not space
{
int _newValue=((_value+11)%90);
(_newValue<65)?_newValue+=65:_newValue+=0;
char _newCharacter=static_cast<char>(_newValue);
}
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
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;
}