In C++, I am trying to take text from a file and count the occurrences of characters, ignoring differences in case. So far, I can do this without ignoring case.
map<char, size_t> char_count;
char character;
while (myfile >> character)
++char_count[character]; // fetch and increment the counter for word
for (const auto &w : char_count) // for each element in the map
// print the results
cout << w.first << " occurs " << w.second
<< ((w.second > 1) ? " times" : " time") << endl;
My solution for this was going to be:
character = tolower(character)
but tolower() will not take a char, only an int. Any ideas? Am I approaching this the wrong way?
that's true, you can use tolower to convert a character to lowercase, i've modified your code, i hope it can help you :
while (myfile >> character)
++char_count[tolower(character)];
Your solution is applicable.
Just use tolower and convert the char to an int.
Related
In Python and C#, we need to place a negative index to get last value.
In C++, I don't know how to do it. I tried the same way to do it but it didn't work out.
Example
string str = "get last space "
cout << str[-1];
In this example, I should get null value because there's a tailing space in the string. How can I do this?
cout << str[str.length() - 1];
str.length()will return the number of chars in this string, and to get the char at the end of str, you should use the index of the end char, which is 1 less than str length, since 0 is the first index
you can use back() method in string class :
string str = "get last space ";
cout << str.back();
its return char& to last character in string
Since you are using std::string, you can use the method std.back();.
cout << str.back();
This will get the last character of the string as you wish.
Since no one mentioned str.back() is UB if str is empty, I'd like to elaborate on it.
std::cout << str.back(); // Trigger UB if str.emtpy() == true
The better form is as following:
if(str.empty() == false){
std::cout << str.back();
}
Since str.back() is equivalent to str[str.length()-1], they both have UB when str is empty.
You can also use the str.end() iterator
string str = "get last space ";
cout << *(str.end()-1);
So we got an optional assignment in our C++ class. The assignment is basically this:
Write a program that holds a string of at least 8 words.
Do the following:
1. Replace the letters of first word with '?'
2. Turn the letters of the last word to uppercase
We did not yet study vectors in our class.
When I first read the assignment, storing the strings to a vector seemed like a good idea so I went with it.
To replace the characters with a '?' I used a for loop. I know that this would not work if I only had to change only certain characters or every other character to a '?'.
My issue is with converting chars of a string to uppercase.
My thought process was: for loop iterates through all chars in the last word, if the char is lowercase it gets turned to uppercase, if it is already uppercase it does not change.
I believe that my approach could work for this problem, I just maybe did not express myself correctly or I made a silly error somewhere. Could anyone assist me or push me in the right direction?
What other options are there to iterate through all chars of a string stored in a vector? Is there another approach that might work better for this? Thank you for your time.
#include <vector>
#include <cctype>
#include <string>
#include <iostream>
using namespace std;
vector<string>words;
//stores words to vector words
void storeWords()
{
cout << "Input 8 words: " << endl;
string s = " ";
for(int i=0; i<=7; i++)
{
cin >> s;
words.push_back(s);
}
}
//prints our words
void printWords()
{
cout << "\n Words stored in vector: " << endl;
for (const string s : words)
cout << s << endl;
}
//replaces chars of the first word with a '?' sign
void replace1(vector<string>&v)
{
cout << "\nReplaced characters of the first word " << words[0] << " with '?'" << endl;
for (char c : words[0])
cout << "?";
}
void replace2(vector<string>&v)
{
for (char c : words[7])
{
if(islower(c))
c = toupper(c);
}
cout << endl;
cout << words[7]<<endl;
}
int main()
{
storeWords();
printWords();
replace1(words);
replace2(words);
return 0;
}
c = toupper(c) will assign c the uppercase value. However, changing c will not change what's inside words[7]. You can get around this by referencing the char directly (char &c).
void replace2(vector<string>&v)
{
for (char &c : words[7]) {
c = toUpper(c);
}
cout << endl;
cout << words[7]<<endl;
}
Also note that your requirements are to hold a string of at least 8 words. So words[7] will probably end up looking like words[words.size() - 1].
This
for (char c : words[7])
Should be:
for (char& c : words[7])
The first version modifies a local variable, while the second changes the actual characters in words[7].
The little ampersand (&) makes c a reference to a certain character in words[7], allowing you to change c as you would words[7][some_i].
Also, I should add that your replace functions do not need that vector argument.
Ideone Example with that change
So I have a while look that checks every character in a file.
while (infile.get(ch))
The problem is that in the same loop I have to check the next character to check for some validation.
Is there anyway I could move the next character while keeping track of the current one?
Thanks
Use the peek() method so you will be able to look at the next character before extracting it. Here's an example:
std::istringstream iss("ABC");
for (char c; iss.get(c); )
{
std::cout << "Current character is: " << c << std::endl;
if (iss.peek() != EOF)
std::cout << "Next character is: " << (char)iss.peek();
}
This should output:
Current character is: A
Next character is: B
Current character is: B
Next character is: C
Current character is: C
Why I cannot initialize string with "\x"
string s = "\x"
It would be useful if I could later write:
int grade = 0;
while (cin >> grade)
if (grade < 60)
cout << "Your grade letter is F!";
else {
x = 50 - grade/10;
s = s + static_cast<string>(x);
cout << "Your grade letter is " << s << endl;
}
I prefer answer, that uses escape sequences computation for setting grade letter.
Because the syntax forbids it. The \x sequence in a string literal is a prefix that means "here comes the hexadecimal code for a character", but you're trying to omit the code part. That means it's not possible to parse the literal and figure out which character to put in the string.
Note that this is a compile-time thing, it has to be possible to compute the sequence of characters represented by a string literal, by just looking at the literal itself.
You misunderstand the way the escape sequences are processed. They are computed at compile-time, not at run time. On other words, when you write
"\x48"
it does not become a string of four characters at runtime; compiler converts it to a single-character string before the program is run.
You also misunderstand static_cast<...>: if x is not a std::string, static-casting it to string will result in an error; if it is a std::string, static-casting will have no effect.
You can create a single-character string at runtime and put a character code into its only character like this:
int grade = 83; // <<<=== 1..100
grade--;
int gradeLetter = g < 60 ? 'F' : ('A' + (100-grade)/10);
// At this point you can do the output:
cout << "Your grade is " << gradeLetter << endl;
// If you must have a string, do this:
string gradeStr(1,gradeLetter);
cout << "Your grade is " << gradeStr << endl;
first post so my apologies if I break protocol.
I'm working on a silly program for school and I have the following code.
cout << "//Dictionary Program//\n\n";
cout << "Enter a command:\n's' - to search for a pattern at the beginning\n";
cout << "'e' - to search for a pattern at the end\n";
cout << "'c' - to search for a pattern anywhere in the word\n";
//Gather user input.
cout << "Please enter a command ('q' to quit): ";
cin >> userCommand;
cmdCheck = userCommand.find("secq");
while(cmdCheck < 0 || userCommand.length() > 1){
cout << "Please enter a valid command\n";
cin >> userCommand;
cmdCheck = userCommand.find("secq");
}
This is driving a menu and I am trying to validate the input. It should be one letter, and one of the following "secq"
I am having a terrible time with the string.find() in the immediate window. I end up with CXX0047: Error: argument list does not match a function. Which I don't understand at all because I am using it elsewhere.
The while condition is not being nice to me. When I give the program a "v" it ends up inside the block like it should, but then I give it an "s" where the cmdCheck should evaluate to 0, but it gives a -1 and stays inside the block.
Lastly, I coded around another error with the cmdCheck but I had that in the while condition and it was not working either. while(userCommand.find("secq") < 0 ...
My inital thought was a problem with the input buffer but when I look at the userCmd variable in the Locals window I have a character array of size 1. There is only the letter and no junk from the buffer (as far as I can tell)
I know I could just tie a bunch of || together with each command but this is a bit more elegant in my opinion. I looked at my final last year and my conditionals were ugly. It's more of a matter of principle at this point.
The expression userCommand.find("secq") tries to find the string "secq" in userCommand. From the sounds of it, you actually want to do the exact opposite, i.e., find the userCommand in the string "secq":
std::string::size_type cmdCheck = std::string("secq").find(userCommand);
while (cmdCheck == std::string::npos) {
...
}
Also note that std::string doesn't return an int. Instead it returns a std::string::size_type. This may be a typedef for int but it may also be a typedef for a different integer type. If the string being passed to find() can't be found, std::string::npos is returned. The exact value for this constant is also not defined so you are best off comparing to this constant instead of making any assumptions.
I'm guessing that userCommand is an std::string. Since the command is supposed to be a single character, use a char instead of a string. Then just use the value as the argument in a switch statement, with appropriate cases for the valid characters and a default case that gives an error message.
Take input using getline in a string.
getline (cin, userCommand) ;
If the input is one letter, take it in a single char. If you insist on taking it in a string, use its first index to check.
Maybe a loop like this would be more appropriate:
char result;
std::cout << "Your command: ";
for (std::string line; ; )
{
if (!(std::getline(std::cin, line))
{
std::cerr << "Fatal error: Unexpected end of input!\n";
std::exit(1);
}
if (line.size() == 1 && line.find_first_of("secq") == 0)
{
result = line[0];
break;
}
std::cout << "Sorry, I did not understand. Please say again: ";
}
std::cout << "Thank you! You said, '" << result << "'\n";
Now if the loop breaks, result will contain the user input.