4

I wrote a program that lets the user input a character. If the character is a vowel, do nothing; if the character is a consonant, find the closest vowel in the alphabet. Is there any easy way to do this?

Here's what I have for now:

char input, output;
cin >> input;
if (input == 'b'){ output = 'a'; }
else if (input == 'c'){ output = 'a'; }
else if (input == 'd'){ output = 'e'; }
else if (input == 'f'){ output = 'e'; }
else if (input == 'g'){ output = 'e'; }
else if (input == 'h'){ output = 'i'; }
else if (input == 'j'){ output = 'i'; }
else if (input == 'k'){ output = 'i'; }
else if (input == 'l'){ output = 'i'; }
else if (input == 'm'){ output = 'o'; }
else if (input == 'n'){ output = 'o'; }
else if (input == 'p'){ output = 'o'; }
else if (input == 'q'){ output = 'o'; }
else if (input == 'r'){ output = 'o'; }
else if (input == 's'){ output = 'u'; }
else if (input == 't'){ output = 'u'; }
else if (input == 'v'){ output = 'u'; }
else if (input == 'w'){ output = 'u'; }
else if (input == 'x'){ output = 'u'; }
else if (input == 'y'){ output = 'u'; }
else if (input == 'z'){ output = 'u'; }

Is there a simpler way to do this?

Jahid
  • 21,542
  • 10
  • 90
  • 108
ʇolɐǝz ǝɥʇ qoq
  • 717
  • 1
  • 15
  • 30

7 Answers7

11

You could also use an array:

const char nearestVowels[26] = "aaaeeeeiiiiioooooouuuuuyyy";
                             // abcdefghijklmnopqrstuvwxyz

Then you could simply do this:

output = nearestVowels[input - 'a'];
Emil Laine
  • 41,598
  • 9
  • 101
  • 157
4

Looks like you want something like this:

if (input != 'a' && input != 'e' && input != 'i' && input != 'o' && input != 'u')
{
    if ('a' <= input && input <= 'c')   { output = 'a'; }
    else if (input <= 'g')              { output = 'e'; }
    else if (input <= 'l')              { output = 'i'; }
    else if (input <= 'r')              { output = 'o'; }
    else if (input <= 'z')              { output = 'u'; }
}

Live On Coliru

Blob
  • 561
  • 1
  • 6
  • 19
4

It can be done like this too:

if(input>='a'&&input<='z'){
if(input<='c')output='a';
else if(input<='g')output='e';
else if(input<='l')output='i';
else if(input<='r')output='o';
else if(input<='z')output='u';
}

The first if makes sure that no input other than a~z are fed into output.

Jahid
  • 21,542
  • 10
  • 90
  • 108
2

There are very many ways to do this, perhaps the most concise (albeit ugly) is:

const char* p = strchr(input, "bacadefegehijikilimonopoqorosutuvuwuxuyuzu");
output = (p && *p) ? p[1] : input;

This works by seeking a char* to input in that string literal, then if found it returns the following character. It won't crash for any character code 0-255, but if you input a vowel it will find it in the string and return the following consonant - if that's a problem, it's probably better to use the following...

Have two arrays - one of consonants and another of vowels, and if you find input in the former get the vowel from the same index in the latter.

Yet another way is to use a std::map:

std::map<char, char> m { { 'b', 'a' }, {'c', 'a' } etc... };
if (auto i = m.find(input))
    output = *i;
else
    output = input;

switch is a bit more verbose than the above, but will likely give the fastest performance (but do measure if you care).

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
1

switch would be simpler:

switch (input)
{
    case 'b':
    case 'c':
        output = 'a';
        break;
    case 'd':
    case 'f':
    case 'g':
        output = 'e';
        break;
    ...
    etc.
}
Emil Laine
  • 41,598
  • 9
  • 101
  • 157
1

This feels more generic:

  1. Get the ASCII value of the input
  2. Substract each vowels's ASCII value as its distance and store (vowel, distance) in a list
  3. Sort the list
  4. Get its first pair's key (the vowel)

#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>

using namespace std; 

bool compare(const pair<char, int>& a, const pair<char, int>& b)
{
    return a.second < b.second;
}

int main()
{
    char vowels[] = { 'a', 'e', 'i', 'o', 'u' };
    char input;
    //std::cin >> input;
    input = 'r';
    vector<pair<char, int>> distances;
    for (char& vowel : vowels)
    {
        distances.push_back(make_pair(vowel, abs(input - vowel)));
    }
    sort(distances.begin(), distances.end(), compare);
    pair<char, int> nearest = distances.front();
    if (nearest.second > 0)
    {
        cout << nearest.first;
    }
}
Matthias
  • 7,432
  • 6
  • 55
  • 88
  • You can use a `map` instead. That gives you `distances[abs(input-vowel)] = vowel` after which you can return `distance.front()`. Lot less code. – MSalters Mar 16 '15 at 10:58
  • @MSalters `std::map` does not offer a `front()` method. http://stackoverflow.com/q/16981600/344480 – Matthias Mar 16 '15 at 11:15
  • Eh, right, `*begin()` then. Still a silly omission from the STL. Also, you'd get a `pair` (compared you your code which has the pair reversed) – MSalters Mar 16 '15 at 11:19
  • @MSalters Referring to the SO answers, "begin() implies lets start somewhere, no matter where". I don't think that the order is guaranteed. Anyway, I wanted to provide an understandable implementation without any over-optimized code. Disclaimer: I'm a Java developer. – Matthias Mar 16 '15 at 11:27
  • The order is not guaranteed in general. For the 3 basic containers, it's insertion order, for the two ordered containers it's obviously the container order, it's just the two unordered containers who have no guarantee whatsoever. As `std::map` is one of the ordered containers, `*begin()` is the smallest. Also, in C++ `list` generally is not a recommended class (prefer `vector`). – MSalters Mar 16 '15 at 16:05
  • @MSalters I updated my answer to `vector` which is faster in sorting. Still I wouldn't like a `std::map` implementation since I had to use the distance rather than the vowel itself as it's key. Anyway, thanks for your comments. I learned some things! – Matthias Mar 17 '15 at 14:06
1

Here's one I made in Java, it's not assigned statically and supports lower and upper case letters.

public static char closestVowel(char character) {
    int value = (int) character;
    if(character == 'z' || character == 'Z')
        return (char) (value - 25);
    if(isVowel(character)) {
        return character;
    } else {
        return closestVowel((char) (value - 1));
    }
}

public static boolean isVowel(char character) {
    return "aeiouAEIOU".indexOf(character) >= 0;
}
Hayden Taylor
  • 329
  • 1
  • 4
  • 9