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]);
Related
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.
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;
}
Lets say I have a loop and an if statement in the loop. If i is true in the loop it prints with a space or comma and it does this for the rest of the i's that are true, but I want to do something else with the last i that that is true. How would I do this?
for (i = 0; i <= somenum; i++){
if (i % 2 != 0)
{
cout << i;
}
}
I want to figure out the last value that follows the condition and do something else with it.
There are really three ways to approach this problem. To illustrate this I'm going to use the example that you want to have a for loop print the numbers 0-9 separated by comas and spaces.
(1) Make the loop do the same thing every time, but modify your result after the loop. An example of how to do this is:
#include <iostream>
#include <sstream>
int main(int, char**) {
std::stringstream ss;
for (int i = 0; i < 10; ++i) {
ss << i << ", ";
}
ss.seekp(-2, std::ios_base::end);
ss << '\0';
std::cout << ss.str();
}
(2) Exit your loop before your last iteration and handle the last case outside the loop:
#include <iostream>
int main(int, char**) {
for (int i = 0; i < 9; ++i) {
std::cout << i << ", ";
}
std::cout << 9;
}
(3) Special case your last iteration in the loop. This option is bad, and you probably only want to do this in cases where you can't make 1 or 2 apply. The reason this is bad is because your conditional in the loop will be executed every time, and it will only be true once.
#include <iostream>
int main(int, char**) {
std::stringstream ss;
for (int i = 0; i < 10; ++i) {
if (i == 9) {
std::cout << i;
break;
}
std::cout << i << ", ";
}
}
In most cases option 2 is your best bet from a performance standpoint, but sometimes option 1 provides cleaner code which can be valuable.
If you have a "sequence" then you have no way of knowing if an element is the last or not. If you're using a for loop with a known length then it's trivial:
for(size_t i = 0; i < length; i++ ) {
if( i == length - 1 ) {
// do something for the last element
}
}
Reading your question, it sounds like you want to print a comma between elements but obviously don't want a trailing comma. The solution is not to test on the last, but to actually test on the first, like so:
bool isFirst = true;
iterator it;
for( it = sequence.begin(); it != sequence.end(); it++ ) {
if( !isFirst ) print(", ");
isFirst = false;
print( element );
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I was asked this question in an interview:
Given an array with the input string, display the output as shown below
Input
INDIA
Output
INDA
****
*
I iterated through the array and stored each character as a key in std::map with value as number of occurrence. Later I iterate the map and print the asteriks and reduce the value in the map for each character.
Initially, I was asked not to use any library. I gave a solution which needed lot of iterations. For every character, iterate the complete array till the index to find previous occurrences and so on.
Is there any better way, e.g. better complexity, such as faster operation, by which this can be achieved?
Essentially what you are asking is how to implement map without using the STL code, as using some kind of data structure which replicates the basic functionality of map is pretty much the most reasonable way of solving this problem.
There are a number of ways of doing this. If your keys (here the possible characters) come from a very large set where most elements of the set don't appear (such as the full Unicode character set), you would probably want to use either a tree or a hash table. Both of these data structures are very important with lots of variations and different ways of implementing them. There is lots of information and example code about the two structures around.
As #PeterG said in a comment, if the only characters you are going to see are from a set of 256 8-bit chars (eg ASCII or similar), or some other limited collection like the upper-case alphabet you should just use an array of 256 ints and store a count for each char in that.
here is another one:
You can see it working HERE
#include <stdio.h>
int main()
{
int i,j=0,f=1;
char input[50]={'I','N','D','I','A','N','A','N'};
char letters[256]={0};
int counter[256]={0};
for(i=0;i<50;i++)
{
if(input[i])
counter[input[i]]++;
if(counter[input[i]]==1)
{
putchar(input[i]);
letters[j]=input[i];
j++;
}
}
putchar('\n');
while(f)
{
f=0;
for(i=0;i<j;i++)
if(counter[letters[i]])
{
putchar('*');
counter[letters[i]]--;
f=1;
}
else
{
putchar(' ');
}
putchar('\n');
}
return 0;
}
If the alphabet under consideration is fixed, it can be done in two passes:
Create an integer array A with the size of the alphabet, initialized with all zeros.
Create a boolean array B with size of the input, initialize with all false.
Iterate the input; increase for every character the corresponding content of A.
Iterate the input; output a character if its value it B is false and set its value in B to true. Finally, output a carriage return.
Reset B.
Iterate input as in 4., but print a star if if the character's count in A is positive, then decrease this count; print a space otherwise.
Output a carriage return; loop to 5 as long as there are any stars in the output generated.
This is interesting. You shouldnt use a stl::map because that is not a hashmap. An stl map is a binary tree. An unordered_map is actually a hash map. In this case we dont need either. We can use a simple array for char counts.
void printAstr(std::string str){
int array[256] ;// assumining it is an ascii string
memset(array, 0, sizeof(array));
int astrCount = 0;
for(int i = 0; i < str.length()-1; i++){
array[(int) str[i]]++;
if(array[(int) str[i]] > 1) astrCount++;
}
std::cout << str << std::endl;
for(int i = 0; i < str.length()-1;i++) std::cout << "* ";
std::cout << std::endl;
while(astrCount != 0){
for(int i= 0; i< str.length() - 1;i++){
if(array[(int) str[i]] > 1){
std::cout << "* ";
array[(int) str[i]]--;
astrCount--;
}else{
std::cout << " ";
}
}
std::cout << std::endl;
}
}
pretty simple just add all values to the array, then print them out the number of times you seem them.
EDIT: sorry just made some logic changes. This works now.
The following code works correctly. I am assuming that you can't use std::string and take note that this doesn't take overflowing into account since I didn't use dynamic containers. This also assumes that the characters can be represented with a char.
#include <iostream>
int main()
{
char input[100];
unsigned int input_length = 0;
char letters[100];
unsigned int num_of_letters = 0;
std::cin >> input;
while (input[input_length] != '\0')
{
input_length += 1;
}
//This array acts like a hash map.
unsigned int occurrences[256] = {0};
unsigned int max_occurrences = 1;
for (int i = 0; i < input_length; ++i)
{
if ((occurrences[static_cast<unsigned char>(input[i])] += 1) == 1)
{
std::cout<< " " << (letters[num_of_letters] = input[i]) << " ";
num_of_letters += 1;
}
if (occurrences[static_cast<unsigned char>(input[i])] > max_occurrences)
{
max_occurrences = occurrences[static_cast<unsigned char>(input[i])];
}
}
std::cout << std::endl;
for (int row = 1; row <= max_occurrences; ++row)
{
for (int i = 0; i < num_of_letters; ++i)
{
if (occurrences[static_cast<unsigned char>(letters[i])] >= row)
{
std::cout << " * ";
}
else
{
std::cout << " ";
}
}
std::cout << std::endl;
}
return 0;
}
The question is marked as c++ but It seems to me that the answers not are all quite C++'ish, but could be quite difficult to achieve a good C++ code with a weird requirement like "not to use any library". In my approach I've used some cool C++11 features like in-class initialization or nullptr, here is the live demo and below the code:
struct letter_count
{
char letter = '\0';
int count = 0;
};
int add(letter_count *begin, letter_count *end, char letter)
{
while (begin != end)
{
if (begin->letter == letter)
{
return ++begin->count;
}
else if (begin->letter == '\0')
{
std::cout << letter; // Print the first appearance of each char
++begin->letter = letter;
return ++begin->count;
}
++begin;
}
return 0;
}
int max (int a, int b)
{
return a > b ? a : b;
}
letter_count *buffer = nullptr;
auto testString = "supergalifragilisticoespialidoso";
int len = 0, index = 0, greater = 0;
while (testString[index++])
++len;
buffer = new letter_count[len];
for (index = 0; index < len; ++index)
greater = max(add(buffer, buffer + len, testString[index]), greater);
std::cout << '\n';
for (int count = 0; count < greater; ++count)
{
for (index = 0; buffer[index].letter && index < len; ++index)
std::cout << (count < buffer[index].count ? '*' : ' ');
std::cout << '\n';
}
delete [] buffer;
Since "no libraries are allowed" (except for <iostream>?) I've avoided the use of std::pair<char, int> (which could have been the letter_count struct) and we have to code many utilities (such as max and strlen); the output of the program avobe is:
supergaliftcod
**************
* ******* *
* *** *
* *
*
*
My general solution would be to traverse the word and replace repeated characters with an unused nonsense character. A simple example is below, where I used an exclamation point (!) for the nonsense character (the input could be more robust, some character that is not easily typed, disallowing the nonsense character in the answer, error checking, etc). After traversal, the final step would be removing the nonsense character. The problem is keeping track of the asterisks while retaining the original positions they imply. For that I used a temp string to save the letters and a process string to create the final output string and the asterisks.
#include <iostream>
#include <string>
using namespace std;
int
main ()
{
string input = "";
string tempstring = "";
string process = "";
string output = "";
bool test = false;
cout << "Enter your word below: " << endl;
cin >> input;
for (unsigned int i = 0; i < input.length (); i++)
{ //for the traversed letter, traverse through subsequent letters
for (unsigned int z = i + 1; z < input.length (); z++)
{
//avoid analyzing nonsense characters
if (input[i] != '!')
{
if (input[i] == input[z])
{ //matched letter; replace with nonsense character
input[z] = '!';
test = true; //for string management later
}
}
}
if (test)
{
tempstring += input[i];
input[i] = '*';
test = false; //reset bool for subsequent loops
}
}
//remove garbage symbols and save to a processing string
for (unsigned int i = 0; i < input.size (); i++)
if (input[i] != '!')
process += input[i];
//create the modified output string
unsigned int temp = 0;
for (unsigned int i = 0; i < process.size (); i++)
if (process[i] == '*')
{ //replace asterisks with letters stored in tempstring
output += tempstring[temp];
temp++;
}
else
output += process[i];
//output word with no repeated letters
cout << output << endl;
//output asterisks equal to output.length
for (unsigned int a = 0; a < output.length (); a++)
cout << "*";
cout << endl;
//output asterisks for the letter instances removed
for (unsigned int i = 0; i < process.size (); i++)
if (process[i] != '*')
process[i] = ' ';
cout << process << endl << endl;
}
Sample output I received by running the code:
Enter your word below:
INDIA
INDA
****
*
Enter your word below:
abcdefgabchijklmnop
abcdefghijklmnop
****************
***
It is possible just using simple array to keep count of values.
#include<iostream>
#include<string>
using namespace std;
int main(){
string s;
char arr[10000];
cin>>s;
int count1[256]={0},count2[256]={0};
for(int i=0;i<s.size();++i){
count1[s[i]]++;
count2[s[i]]++;
}
long max=-1;
int j=0;
for(int i=0;i<s.size();++i){
if(count1[s[i]]==count2[s[i]]){ //check if not printing duplicate
cout<<s[i];
arr[j++]=s[i];
}
if(count2[s[i]]>max)
max=count2[s[i]];
--count1[s[i]];
}
cout<<endl;
for(int i =1; i<=max;++i){
for(int k=0;k<j;++k){
if(count2[arr[k]]){
cout<<"*";
count2[arr[k]]--;
}
else
cout<<" ";
}
cout<<endl;
}
}
I'm writing a program which is intended to compare the numbers in 2 arrays and output the number of matches that there are.
RandomNumber.h
#pragma once
#include <iostream>
#include <cstdlib>
#include <ctime>
class RandomNumber
{
public:
void randomNumber();
int actualRandomNumber;
};
RandomNumber.cpp
#include "RandomNumberGenerator.h"
void RandomNumber::randomNumber()
{
actualRandomNumber = rand() % 66 + 1;
}
Game.h
#include "RandomNumberGenerator.h"
class Game
{
private:
int randomNumbers[6];
public:
void generateRandomNumbers();
void compareNumbers2();
};
Game.cpp
void Game::generateRandomNumbers()
{
RandomNumber create;
for (int i = 0; i < 6; i++)
{
create.randomNumber();
randomNumbers[i] = create.actualRandomNumber;
}
for (int i = 0; i < 6; i++)
{
std::cout << randomNumbers[i] << " ";
}
}
void Game::compareNumbers2()
{
int k = 0;
for (int i = 0; i < 6; ++i)
{
for (int j = 0; j < 6; ++j)
{
if (randomNumbers[i] == randomNumbers[j])
{
k++;
}
}
}
if (k > 0)
{
std::cout << "Congratulations you matched: " << k << " number(s)";
}
if (k == 0)
{
std::cout << "Unfortunatly you matched: " << k << " numbers";
}
}
Main.cpp
#include "Game.h"
#include "RandomNumberGenerator.h"
int main()
{
Game play;
srand (time(NULL));
play.generateRandomNumbers();
std::cout << std::endl << std::endl;
play.generateRandomNumbers();
std::cout << std::endl << std::endl;
play.compareNumbers2();
system("pause");
return 0;
}
The problem I'm having isn't in creating the arrays and filling them, I get two filled arrays with 2 different sets of random numbers, but for some reason when comparing them the number of matches it tells me I have is always about 6 or 8 when I in fact rarely have more than one or two if that.
The most obvious problem is that you only have one array.
class Game
{
...
int randomNumbers[6];
Where did you think the second array was?
Based on your code, I saw only 1 array. And in the function compareNumber2(), you compare each number with it once. Therefore, the result is the number of elements (e.g, 6).
Looking at code, I can say you will be getting 6 matches all the time, since you randomNumbers array will be overwritten in second step (when you try to generate random numbers second time)
There are actually two problems bigger and smaller:
You're comparing your array int randomNumbers[6] with itself.
Please don't call the object create. Its very wrong habit. Call the object of class RandomNumber i.e a randomNumber and take your random number from it like:
randomNumber.getValue()
Usually try to call the methods with verbs and objects with nouns it will be more natural don't you think?
You do no not compare two arrays. You compare one array, data member of class Game, with itself. You simply fill it two times.