I have to count the vowels of evey word in a given text. My attempt :
#include <iostream>
#include <string.h>
using namespace std;
char s[255], *p, x[50][30];
int c;
int main()
{
cin.get(s, 255);
cin.get();
p = strtok(s, "?.,;");
int n = 0;
while (p)
{
n++;
strcpy(x[n], p);
p = strtok(NULL, "?.,;");
}
for (int i = 1; i <= n; i++)
{
c = 0;
for (int j = 0; j < strlen(x[i]); j++)
if (strchr("aeiouAEIOU", x[i][j]))
c++;
cout << c << " ";
}
return 0;
}
PS: I know that my code is a mix between C and C++, but this is what I am taught in school.
Case closed in the comments.
However, for the fun, I propose you another variant that avoids to use the terrible strtok(), doesn't require a risky strcpy(), and processes each input character only one.
As you are bound to your teacher's mixed style and apparently are not supposed to use c++ strings yet, I also respected this constraint:
const char separators[]=" \t?.,;:"; // I could put them in the code directly
const char vowels[]="aeiouyAEIOUY"; // but it's for easy maintenance
int vowel_count=0, word_count=0;
bool new_word=true;
char *p=s;
cout << "Vowels in each word: ";
do {
if (*p=='\0' || strchr(separators,*p)) {
if (!new_word) { // here, we've reached the end of a word
word_count++;
cout << vowel_count << " ";
vowel_count = 0;
new_word=true;
} // else it's still a new word since consecutive separators
}
else { // here we are processing real chars of a word
new_word=false; // we have at least on char in our word
if (strchr(vowels, *p))
vowel_count++;
}
} while (*p++); // It's a do-while so not to repeat the printing at exit of loop
cout << endl<<"Words: "<<word_count<<endl;
Demo
This is my solution:
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char s[255];
int n,i,counter=0;
cin.get(s,255);
for(i=0; i<=strlen(s)-1; i++)
if(s[i]=='a' || s[i]=='e' || s[i]=='i' || s[i]=='o' || s[i]=='u') counter++;
cout<<counter;
return 0;
}
If you have a vowel( a, e, i, o or u) you are adding up to the counter.
You can also use strchr but this is a more simple, understandable method.
Related
Am revisiting an exercise from an online course where we created a 'Whale translator' which checks through each character that the user inputs and extracts / returns only the vowels.
I thought it would be fun to have the returned values capitalized at random so the whole thing would feel a little like Dory speaking whale (finding Nemo) so I created a function to take each character and convert them to caps based on whether a random number is odd or even. Thing is that I cannot get the program to acknowledge or use my function. Runs fine otherwise.
Could somebody give me a pointer as to where I'm going wrong?
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
char converter(char);
int main() {
std::cout << "WeELCooOmE ToOOoO the WHaALe translaAtoOor \n";
std::cout << "\n PlEaAsE EnntEer yoOur text tOo beEE trAanslaAateEd \n\n";
std::string input;
std::getline(std::cin, input);
std::cout << "\n";
std::vector<char> vowels;
vowels.push_back('a');
vowels.push_back('e');
vowels.push_back('i');
vowels.push_back('o');
vowels.push_back('u');
std::vector<char> whale_talk;
for (int i = 0; i < input.size(); i++) {
for (int j = 0; j < vowels.size(); j++) {
if (input[i] == vowels[j]) {
whale_talk.push_back(input[i]);
}
}
}
std::cout << "HeEre iS yOoUr translaAtiOn..\n\n";
for (int k = 0; k < whale_talk.size(); k++) {
converter(whale_talk[k]);
std::cout << whale_talk[k];
}
std::cout << "\n";
}
char converter(char x) { //function to convert characters toupper based on random number generation.
int rando = rand() % 100;
if (rando % 2 == 0) {
x = toupper(x);
return x;
}
else {
return x;
}
}
You converter function is returning the modified char but you never use the returned value in the for loop:
converter(whale_talk[k]);
You need to do:
whale_talk[k] = converter(whale_talk[k]);
Here's a demo.
Alternatively, you can leave the call site as it is, but pass the char to be converted by reference, like this:
void converter(char &x) { // << pass by reference
// and modify x, but don't return it
}
Here's a demo.
You ignore the retun value of converter, so it has no effect.
This
converter(whale_talk[k]);
std::cout << whale_talk[k];
should be
std::cout << converter(whale_talk[k]);
I am trying to do is display all the suffixes of a word as such:
word: house
print:
h
ho
hou
hous
house
What I did is:
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char cuvant[100];
int i,k;
cin>>cuvant;
for(i=0;i<strlen(cuvant);i++)
{
for(k=0;k<i;k++)
{
if(k==0)
{
cout<<cuvant[k]<<endl;
}else
{
for(k=1;k<=i;k++){
if(k==i) cout<<endl;
cout<<cuvant[k];
}
}
}
}
}
What am I doing wrong?
You're over-complicating it. Here's a simpler way:
#include <iostream>
#include <string>
#include <string_view>
int main() {
std::string s;
std::cin >> s;
for (std::string::size_type i = 0, size = s.size(); i != size; ++i)
std::cout << std::string_view{s.c_str(), i + 1} << '\n';
}
If you don't have access to a C++17 compiler, you can use this one:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
int main() {
std::string s;
std::cin >> s;
for (auto const& ch : s) {
std::copy(s.c_str(), (&ch + 1),
std::ostream_iterator<decltype(ch)>(std::cout));
std::cout << '\n';
}
}
Even so, I think it would be better for your learning progress to use a debugger to finger out the problem yourself. Here the problems with your code:
For the i=0 (the first iteration of your outer loop) the for(k=0;k<i;k++) will not be executed at all, as k<0 evaluates to false.
And having a running variable (k) that you change in two for loops that are nested, is most of the time also an indication that something is wrong.
So what you want to do: You want to create each possible prefix, so you want to create n strings with the length of 1 to n. So your first idea with the outer loop is correct. But you overcomplicate the inner part.
For the inner part, you want to print all chars from the index 0 up to i.
int main() {
char cuvant[100];
std::cin >> cuvant;
// loop over the length of the string
for (int i = 0, size = strlen(cuvant); i < size; i++) {
// print all chars from 0 upto to i (k<=0)
for (int k = 0; k <= i; k++) {
std::cout << cuvant[k];
}
// print a new line after that
std::cout << std::endl;
}
}
But instead of reinventing the wheel I would use the functions the std provides:
int main() {
std::string s;
std::cin >> s;
for (std::size_t i = 0, size = s.size(); i < size; i++) {
std::cout << s.substr(0, i + 1) << std::endl;
}
}
For this very simple string suffix task you can just use:
void main()
{
std::string s = "house";
std::string s2;
for(char c : s)
{
s2 += c;
cout << s2 << endl;
}
}
For more complicated problems you may be interested to read about Suffix Tree
Your code is wrong, the following code can fulfill your requirements
#include <iostream>
using namespace std;
int main()
{
char cuvant[100];
int i,k;
cin>>cuvant;
for(i=0;i<strlen(cuvant);i++)
{
for (k = 0; k <= i; ++k)
{
cout<<cuvant[k];
}
cout<<endl;
}
}
I'm very new to C++. This code is supposed to store and print out every other number and stop when given the symbol #, but the output is weird. It outputs something like 0x6fdd90. Any help would be much appreciated.
#include <iostream>
#include <string>
using namespace std;
int main(){
string s[11];
int count = 1, wordlength = 0;
char a;
cin.get(a);
while (a != '#'){
if (wordlength == 10)
break;
if (count % 2 != 0){
s[wordlength] = a;
wordlength++;
}
cin.get(a);
count++;
}
s[wordlength] = '\0';
cout << s;
return 0;
}
cout << s;
Is printing the address of the 1st element in your array s.
You may want to loop through s to print all the elements.
for (int i =0; i < sizeof(s)/sizeof(s[0]); i++) {
cout<< s[i] << "\n";
}
It is better to user char array than string array for your purpose.
I have a working function that generates all possible “words” of a specific length, i.e.
AAAAA
BAAAA
CAAAA
...
ZZZZX
ZZZZY
ZZZZZ
I want to generalize this function to work for arbitrary lengths.
In the compilable C++ code below
iterative_generation() is the working function and
recursive_generation() is the WIP replacement.
Keep in mind that the output of the two functions not only differs slightly, but is also mirrored (which doesn’t really make a difference for my implementation).
#include <iostream>
using namespace std;
const int alfLen = 26; // alphabet length
const int strLen = 5; // string length
char word[strLen]; // the word that we generate using either of the
// functions
void iterative_generation() { // all loops in this function are
for (int f=0; f<alfLen; f++) { // essentially the same
word[0] = f+'A';
for (int g=0; g<alfLen; g++) {
word[1] = g+'A';
for (int h=0; h<alfLen; h++) {
word[2] = h+'A';
for (int i=0; i<alfLen; i++) {
word[3] = i+'A';
for (int j=0; j<alfLen; j++) {
word[4] = j+'A';
cout << word << endl;
}
}
}
}
}
}
void recursive_generation(int a) {
for (int i=0; i<alfLen; i++) { // the i variable should be accessible
if (0 < a) { // in every recursion of the function
recursive_generation(a-1); // will run for a == 0
}
word[a] = i+'A';
cout << word << endl;
}
}
int main() {
for (int i=0; i<strLen; i++) {
word[i] = 'A';
}
// uncomment the function you want to run
//recursive_generation(strLen-1); // this produces duplicate words
//iterative_generation(); // this yields is the desired result
}
I think the problem might be that I use the same i variable in all the recursions. In the iterative function every for loop has its own variable.
What the exact consequences of this are, I can’t say, but the recursive function sometimes produces duplicate words (e.g. ZAAAA shows up twice in a row, and **AAA gets generated twice).
Can you help me change the recursive function so that its result is the same as that of the iterative function?
EDIT
I realised I only had to print the results of the innermost function. Here’s what I changed it to:
#include <iostream>
using namespace std;
const int alfLen = 26;
const int strLen = 5;
char word[strLen];
void recursive_generation(int a) {
for (int i=0; i<alfLen; i++) {
word[a] = i+'A';
if (0 < a) {
recursive_generation(a-1);
}
if (a == 0) {
cout << word << endl;
}
}
}
int main() {
for (int i=0; i<strLen; i++) {
word[i] = 'A';
}
recursive_generation(strLen-1);
}
It turns out you don't need recursion after all to generalize your algorithm to words of arbitrary length.
All you need to do is "count" through the possible words. Given an arbitrary word, how would you go to the next word?
Remember how counting works for natural numbers. If you want to go from 123999 to its successor 124000, you replace the trailing nines with zeros and then increment the next digit:
123999
|
123990
|
123900
|
123000
|
124000
Note how we treated a number as a string of digits from 0 to 9. We can use exactly the same idea for strings over other alphabets, for example the alphabet of characters from A to Z:
ABCZZZ
|
ABCZZA
|
ABCZAA
|
ABCAAA
|
ABDAAA
All we did was replace the trailing Zs with As and then increment the next character. Nothing magic.
I suggest you now go implement this idea yourself in C++. For comparison, here is my solution:
#include <iostream>
#include <string>
void generate_words(char first, char last, int n)
{
std::string word(n, first);
while (true)
{
std::cout << word << '\n';
std::string::reverse_iterator it = word.rbegin();
while (*it == last)
{
*it = first;
++it;
if (it == word.rend()) return;
}
++*it;
}
}
int main()
{
generate_words('A', 'Z', 5);
}
If you want to count from left to right instead (as your example seems to suggest), simply replace reverse_iterator with iterator, rbegin with begin and rend with end.
You recursive solution have 2 errors:
If you need to print in alphabetic order,'a' need to go from 0 up, not the other way around
You only need to print at the last level, otherwise you have duplicates
void recursive_generation(int a) {
for (int i=0; i<alfLen; i++)
{ // the i variable should be accessible
word[a] = i+'A';
if (a<strLen-1)
// in every recursion of the function
recursive_generation(a+1); // will run for a == 0
else
cout << word << '\n';
}
}
As I am inspired from #fredoverflow 's answer, I created the following code which can do the same thing at a higher speed relatively.
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cmath>
void printAllPossibleWordsOfLength(char firstChar, char lastChar, int length) {
char *word = new char[length];
memset(word, firstChar, length);
char *lastWord = new char[length];
memset(lastWord, lastChar, length);
int count = 0;
std::cout << word << " -> " << lastWord << std::endl;
while(true) {
std::cout << word << std::endl;
count += 1;
if(memcmp(word, lastWord, length) == 0) {
break;
}
if(word[length - 1] != lastChar) {
word[length - 1] += 1;
} else {
for(int i=1; i<length; i++) {
int index = length - i - 1;
if(word[index] != lastChar) {
word[index] += 1;
memset(word+index+1, firstChar, length - index - 1);
break;
}
}
}
}
std::cout << "count: " << count << std::endl;
delete[] word;
delete[] lastWord;
}
int main(int argc, char* argv[]) {
int length;
if(argc > 1) {
length = std::atoi(argv[1]);
if(length == 0) {
std::cout << "Please enter a valid length (i.e., greater than zero)" << std::endl;
return 1;
}
} else {
std::cout << "Usage: go <length>" << std::endl;
return 1;
}
clock_t t = clock();
printAllPossibleWordsOfLength('A', 'Z', length);
t = clock() - t;
std:: cout << "Duration: " << t << " clicks (" << ((float)t)/CLOCKS_PER_SEC << " seconds)" << std::endl;
return 0;
}
Here is v1.0 of the binary_to_decimal converter I wrote. I want to make several changes as I keep improving the spec. Classes and pointers will be added as well in the future. Just to keep me fresh and well practiced.
Well, I now want to implement an error-correcting loop that will flag any character that is not a 0 or a 1 and ask for input again.
I have been trying something along the line of this code block that worked with an array.
It might be way off but I think I can tweak it. I am still learning 0_0
I want to add something like this:
while ((cin >> strint).get())
{
cin.clear(); //reset the input
while (cin.get() != '\n') //clear all the way to the newline char
continue; //
cout << "Enter zeroes and/or ones only! \n";
}
Here is the final code without the error-correcting loop:
#include <iostream>
#include <cmath>
#include <string>
using namespace std;
const int MAX = 100;
int conv(int z[MAX], int l[MAX], int a);
int main()
{
int zelda[MAX];
int link[MAX];
string strint;
int am;
cout << "Enter a binary number: \n";
(cin >> strint).get(); //add error-correction to only read 0s and 1s.
am = strint.size();
cout << am << " digits entered." << endl;
int i = 0;
int p = 0;
while (i < am)
{
zelda[i] = strint[p] - '0'; //copies the string array elements into the int array; essentially STRING TO INT (the minus FORCES a conversion because it is arithmetic) <---- EXTREMELY CLEVER!
++i;
++p;
}
cout << conv(zelda, link, am);
cin.get();
return 0;
}
int conv(int zelda[MAX], int link[MAX], int length)
{
int sum = 0;
for (int t = 0; t < length; t++)
{
long int h, i;
for (int h = length - 1, i = 0; h >= 0; --h, ++i)
if (zelda[t] == 1)
link[h] = pow(2.0, i);
else
link[h] = 0;
sum += link[t];
}
return sum;
}
thanks guys.
I'm not completely sure of what you're trying to do, but I think what you're wanting is string::find_first_not_of. There's an example included in that link. You could have something like: myString.find_first_not_of("01");
If the return value is string::npos, then there are no characters in the string other than 1 or 0, therefore it's valid. If the return value is anything else, then prompt again for valid input and continue looping until the input's valid.