C++ - How to find a (variable) character in a string? - c++

I'm required to find a character entered by the user in a for loop. I'd usually do
if (sentence[i] == 'e')
but since here, 'e' will be a one letter char variable, I don't know how to get that value to be compared. I can't just enter
if (sentence[i] == thechar)
but I also can't create a variable to contain the character in between quotation marks like
char2 = "\'" + thechar + "\'";
So how do I do it in this context? I'm not allowed to use other, more effective, more advanced methods. This is a basics course. Please help!

string word;
char letter;
cout << "Enter a word\n";
cin >> word;
cout << "What letter would you like to search for?\n";
cin >> letter;
for (int i = 0; i < word.length(); i++)
{
if (word[i] == letter)
{
cout << letter << " is the " << i + 1 << "character of " << word << endl;
}
}
You can create a variable where you ask for the letter the user wants, and use that variable to compare.

To find position of chosen letter you can use std::string.find(...)
std::string str = "My house is white.";
std::size_t pos = str.find('s');
std::cout << "Position: " << pos << std::endl;
Output:
Position: 6
For more informations go to http://www.cplusplus.com/reference/string/string/find/ page.

Related

Validating user input as coordinates (A1...)

I am struggling to find a way to break down an input from the user to a location on a chess board. For example (A1). I want to make sure that they have entered a Letter between A and H and a number between 1 and 8. Not sure if comparing ASCII is the best approach?
Using C++ this is a snippet of what I have attempted. startingp is the input from the user
char startChar = startingp[0];
int SCascii = startChar;
int startInt = startingp[1];
if (!(ascii_A <= SCascii >= ascii_H) || !(1 <= startInt >= 8))
{
cout << "Your inputted move, " << startPos << ", is invalid." << endl;
cout << "Enter the coordinates of the piece you want to move. (eg A1) : ";
cin >> startingp;
cout << endl;
}
This condition:
(ascii_A <= SCascii >= ascii_H)
is not correct. Or at least, I don't think it's what you mean. Instead, do:
((ascii_A <= SCascii) && (SCascii >= ascii_H))
Other than that, your logic seems reasonable.
I made a Chess game as well, and this is what I used to get the coordinates:
Position* Interface::askPosition()
{
cout << "position: ";
string inp;
cin >> inp;
while (!(isalpha(inp[0]) && isdigit(inp[1]))) {
cout << "Please press CHAR + DIGIT\n";
cin >> inp;
}
return new Position(inp[0] - 'A', inp[1] - '1');
}
It's a static method of a class called Interface and returned a pointer to a Position object. However, this might be not a C++-clean way
You can just compare it with characters, no need to convert it into an int (ASCII).
char startChar = startingp[0];
int SCascii = startChar;
int startInt = startingp[1];
if (!(startChar>='A' && startChar<='H') || !(startInt>=1 && startInt<=8))
{
cout << "Your inputted move, " << startPos << ", is invalid." << endl;
cout << "Enter the coordinates of the piece you want to move. (eg A1) : ";
cin >> startingp;
cout << endl;
}

How to check if char doesnt exist in a string

Say we have the user input a name that is a string "william" and then the user enters the character that they want to find the index of.
using namespace std;
string name;
char characterToFind;
cout << "Enter a name ";
cin >> name;
cout << "Enter a character to find ";
cin >> characterToFind;
We then want to find the index of the character in the name string array.
for (int j = 0; j < name.length(); j++) {
if (name[j] == characterToFind) {
cout << "char is at index: " << j << endl;
}
}
How do I then check if the inputted character doesnt exist in the name string array? I try to do the following:
if (characterToFind != name.find(characterToFind)) {
cout<< "doesnt exist" << endl;
}
The if statement always seems to be true and runs the code even if the character that was inputted existed in the name string array.
The problem with my approach was that I was doing was that in the if condition i was checking a 's' char vs a index position of an array.
instead, doing:
if (name.find(characterToFind) == std::string::npos) {
cout << "doesnt exist" << endl;
}
this is checking if the character input is equal to a position that doesnt exist! This is true so it tells the user that the character entered does not exist.

Program that counts the number of types of letters in a paragraph, C++

What I want is to have a multiple-line text input, and to be able to count the number of lower-case letters, upper-case letters, periods, commas, spaces, line-breaks, and other characters in the input.
I am trying to use just one string with getline for inputs in a while loop with a running count for each punctuation category.
I just don't know how to actually figure out how many of each character type there are in each line. Given a string, how do I count the number of each type?
Here is my code so far (obviously incomplete):
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <cmath>
#include <string>
using namespace std;
int main(){
cout << "This program takes any number of sentences as inputs. " << endl;
cout << "It will count the number of lower-case letters and upper-case letters. " << endl;
cout << "It will also count the number of periods, exclamation marks, spaces, end-lines, etc. " << endl;
cout << " " << endl;
cout << "Please type your text, pressing enter whenever you wish to end a line. " << endl;
cout << "Use the EOF key (CTRL + Z on Windows) when you are finished. " << endl;
string InputString; // This is the string that will be used iteratively, for each line.
int NumberOfLowerCase = 0;
int NumberOfUpperCase = 0;
int NumberOfSpaces = 0; // spaces
int NumberOfTabs = 0; // tabs
int NumberOfPeriods = 0; // periods
int NumberOfCommas = 0; // commas
int NumberOfOtherChars = 0; // other characters
int NumberOfEnters = 0; // end of line, will be incremented each loop
do {
getline(cin, InputString); // input
cout << InputString << endl; // filler just to test the input
NumberOfLowerCase = NumberOfLowerCase + 0 // I don't know what I should be adding
// (obviously not zero, that's just a filler)
} while (!cin.eof() && cin.good());
system("pause");
return 0;
}
If you simply want the number of unique characters, use a set! You can push all of your characters into the set and then just check how big the set is and you'll be good to go!
If you actually want to know how many of each character there are you can use a map (which in fact uses a set under the hood!). With the map, given some character c, you could do
std::map<char, int> counter;
//do stuff...
counter[c]++; //increment the number of character c we've found
//do more stuff...
std::cout << "Found " << counter['A'] << " A's!" << std::endl;
See these helpful functions. Here what you would do:
std::string s = /*...*/;
for(auto c : s) {
if(std::islower(c)) ++NumberOfLowerCase;
else if(std::isupper(c)) ++NumberOfUpperCase;
else if(c == ' ') ++NumberOfSpaces;
else if(c == '\t') ++NumberOfTabs;
else if(c == '.') ++NumberOfPeriods;
else if(c == ',') ++NumberOfCommas;
else ++NumberOfOtherChars;
}
Here's a very simple example I wrote very quickly. Of course there are better ways of doing it, but this should give you an idea of how you could do that. One question: Are you reading from a file or from an istream directly from the console?
int lowerCase = 0;
int upperCase = 0;
int spaces = 0; // spaces
int tabs = 0; // tabs
int newLines = 0; // end of line, will be incremented each loop
int periods = 0; // periods
int commas = 0; // commas
int otherChars = 0;
// read from istream, char by char
for (char ch; cin >> noskipws >> ch;) {
// test which classification or char ch is and increment its count
if (islower(ch))
++lowerCase;
else if (isupper(ch))
++upperCase;
else if (ch == ' ')
++spaces;
else if (ch == '\t')
++tabs;
else if (ch == '\n')
++newLines;
else if (ch == '.')
++periods;
else if (ch == ',')
++commas;
else
++otherChars;
}
cout << "Number of characters of each type:\n";
cout << "lowerCase:\t" << lowerCase << '\n'
<< "upperCase:\t" << upperCase << '\n'
<< "spaces:\t\t" << spaces << '\n'
<< "tabs:\t\t" << tabs << '\n'
<< "periods:\t" << periods << '\n'
<< "commas:\t\t" << commas << '\n'
<< "newLines:\t" << newLines << '\n'
<< "otherChars:\t" << otherChars << '\n';

Why isn't this while loop exiting?

I wrote a console program to help me test a function library I coded. Part of it is this piece of code:
char insertChoice[2] = {'9'};
while (insertChoice[0] != '0')
{
cout << "\nEnter a string:\n";
char insertStringInput[256];
cin.getline(insertStringInput, 255);
char insertChoice[2];
insertChoice[0] = '9';
cout << "\nWhere would you like to insert the substring?\n\n
1) At the beginning of the string\n
2) At the end of the string\n\nInput: ";
cin >> insertChoice;
cin.ignore();
while (insertChoice[0] != '1' && insertChoice[0] != '2')
{
cout << "\nInvalid input.\nWhere would you like to insert the substring?\n\n
1) At the beginning of the string\n
2) At the end of the string\n\nInput: ";
cin >> insertChoice;
cin.ignore();
}
cout << "\nEnter the substring you would like to insert: ";
char insertSubstring[256];
cin.getline(insertSubstring, 255);
std::string used = "", substr = "";
used += insertStringInput;
substr += insertSubstring;
char insertOutputChoice[2];
insertOutputChoice[0] = '1';
if (insertChoice[0] == '1')
insertOutput(insertInBeginning(used, substr));
else
insertOutput(insertInEnd(used, substr));
cin >> insertOutputChoice;
cin.ignore();
if (insertOutputChoice[0] == '1')
{
ofstream outfile("logfile.txt", ios::app);
outfile << "Test type: Insert Substring\n";
outfile << "Test carried out on: " << __DATE__ << "; " << __TIME__ <<"\n";
outfile << "PARAMETERS:\n";
outfile << "usedString: \"" << insertStringInput << "\"\n";
outfile << "insertString: \"" << insertSubstring << "\"\n";
outfile << "function used: "
<< (insertChoice[0]=='1'?"insertInBeginning":"insertInEnd")
<< "\nOUTPUT:\n";
outfile << "\""
<< (insertChoice[0]=='1'?insertInBeginning(used, substr):insertInEnd(used, substr))
<< "\"\n\n";
outfile.close();
cout << "\nWould you like to do another string insertion test? [y/n]: ";
char insertConfirm[2];
insertConfirm[0] = ' ';
while (tolower(insertConfirm[0]) != 'y'
&& tolower(insertConfirm[0] != 'n'))
{
cin >> insertConfirm;
cin.ignore();
if (tolower(insertConfirm[0]) != 'y'
&& tolower(insertConfirm[0] != 'n'))
cout << "\nInvalid input.
Would you like to do another string insertion test? [y/n]: ";
}
if (insertConfirm[0] == 'n')
insertChoice[0] = '0';
}
}
However, the while (insertChoice[0] != '0') loop does not exit when the user types in insertOutputChoice as 1, regardless of whether the user types in insertConfirm as y or n even though it is supposed to exit when insertConfirm is typed in as n.
insertOutput looks as looks as follows:
void insertOutput(std::string substrOut)
{
cout << "\nThe new string generated is:\n";
cout << substrOut;
cout << "\n\n1) Generate a log file of this test\n";
cout << "2) Insert another substring into a string\n\n";
cout << "0) Finish testing string insertion\n\n\n";
cout << "Input: ";
}
Please excuse the messy, unoptimized code. My first priority is to get this done, and I usually leave optimization until last.
Inside the while loop you create a new insertChoice array. And it hides external one. So when you modify values in this array, external one remains unmodified.
I think there may also be an issue with the if statement at the end of the code. Have you tried this while inputting in both upper and lower case? When checking for a valid input you are converting to lowercase to check but not when checking if the response is 'n'.
Remove line 9:
char insertChoice[2];
There are a lot of errors in your code, are you sure it's compiling correctly?
First, there are 2 insertChoice declarations
char insertChoice[2] = {'9'}; // <------- 1ˢᵗ
and in the while loop:
char insertChoice[2]; // <------- 2ⁿᵈ
insertChoice[0] = '9';
The compiler should warn you about that. If not you must enable warnings with the appropriate options of your compiler (/W3 for cl, -Wall -Wpedantic for gcc...). Never compile without warnings
Second, the following string has syntax error
cout << "\nWhere would you like to insert the substring?\n\n
1) At the beginning of the string\n
2) At the end of the string\n\nInput: ";
If you want a line break in the string you must use an escape right before the new line character
cout << "\nWhere would you like to insert the substring?\n\n\
1) At the beginning of the string\n\
2) At the end of the string\n\nInput: ";
or use multiple string literals like this
cout << "\nWhere would you like to insert the substring?\n\n"
"1) At the beginning of the string\n"
"2) At the end of the string\n\nInput: ";
Consecutive literals will be automatically combined into one by the compiler
In C++-0x life is a lot easier with raw string literals where embedded quotes or newlines are possible
cout << R"(
Where would you like to insert the substring?
1) At the beginning of the string
2) At the end of the string
Input: )";

Translator Output Problems

I am making a gibberish translator where you input a word and the console outputs the word in gibberish. The parameters of the gibberish language are if the word has any vowels in it you put "ab" infront of that vowel. For example "Hello" in gibberish would be "H-ab-ell-ab-o". Although i'm having a problem (Please go easy on me if you find this code messy or not well written. Im just learning)
This is my code:
int quit = 2;
int i;
bool vowel;
string word;
string letter = &word[int (i)];
void translation() {
cout << "Enter a word: " << endl;
cin >> word;
for (int i = 0; i <= 20; ++i) {
if (letter == "a") {
cout << "ab" << letter;
}
if (letter == "e") {
cout << "ab" << letter;
}
if (letter == "i") {
cout << "ab" << letter;
}
if (letter == "o") {
cout << "ab" << letter;
}
if (letter == "u") {
cout << "ab" << letter;
} else {
cout << letter ;
}
}
}
void again() {
cout << "Enter 1 to translate another word, Enter 0 to quit" << endl;
cin >> quit;
}
int main() {
while (quit >= 1) {
translation();
again();
}
return 0;
}
Say, when it prompts you to put in a word like this:
Enter a word:
You put in the word Hello, it should output this:
Enter a word:
Hello
Habellabo
Enter 1 to translate another word, Enter 0 to quit
But my program outputs this:
Enter a word:
hello
Enter 1 to translate another word, Enter 0 to quit
Why isn't it outputting the translated word?
string letter = &word[int (i)]; is some strange code, and invokes UB because the char* may not be null terminated. It is the equivalent of string letter = &word[0]; and you are taking the address of the reference to char returned from the operator[]. Also, using double quotes is wrong "a" is a string literal. You want single quotes to compare with char.
Change your code to the following:
for (int i = 0; i < word.size(); ++i) {
if (word[i] == 'a') {
cout << "ab" << word[i];
}
if (word[i] == 'e') {
cout << "ab" << word[i];
}
if (word[i] == 'i') {
cout << "ab" << word[i];
}
if (word[i] == 'o') {
cout << "ab" << word[i];
}
if (word[i] == 'u') {
cout << "ab" << word[i];
} else {
cout << word;
}
Try this instead :
string letter;
...
for (int i = 0; i <= word.length(); ++i) {
letter = word[i];
if (letter == "a") {
cout << "ab" << letter;
}
...
The letter variable has to be updated at each iteration, if not it remains empty.
Also, as mentioned in other answers, it would be a better choice, as you are iterating through characters one by one, to use the char type for the letter.
string letter = &word[int (i)];
i is global variable and is initialized to 0. But the problem is the with the string word. It is an empty string. &word[0] yields you the location of \0 character. So, letter is initialized as an empty string. So, you are actually hitting the final else statement and nothing is printed as the letter is empty as well.
You define string letter = &word[int (i)];. This doesn't do what you seem to think. It uses the value of i at the time the statement executes. Changing i later will not change the value of letter. You need to explicitly evaluate word[i] inside the loop. Also, comparing vs "a", "e", etc. compares strings, when you really want character comparison. Try single quotes instead of double quotes, i.e. 'a', 'e', etc.