char array c++ vowels - c++

I am trying to make a program that will use a switch statement and see if an element of a char array is a vowel and which one, but i am stuck at how to check the elements:
int prob2() {
char uName[25] = "";
int voCo = 0;
cout<<"Enter you first and last name, under 25 chars please: ";
cin>>uName;
int i = 0;
while(i <= 25){
switch(i){
case 1:
voCo++;
break;
case 2:
voCo++;
break;
case 3:
voCo++;
break;
case 4:
voCo++;
break;
case 5:
voCo++;
break;
default:
break;
}
i++;
}
cout<<"Your first and last name have: "<<voCo<<" vowels in them."<<endl;
return 0;
}

It seems you mean the following
#include <iostream>
#include <cctype>
using namespace std;
//...
size_t prob2()
{
const size_t N = 25;
char uName[N] = "";
size_t voCo = 0;
cout<<"Enter you first and last name, under " << N << " chars please: ";
cin.getline( uName, N );
for ( char *p = uName; *p != '\0'; ++p ) *p = toupper( ( unsigned char )*p );
for ( const char *p = uName; *p != '\0'; ++p )
{
switch( *p )
{
case 'A':
voCo++;
break;
case 'E':
voCo++;
break;
case 'I':
voCo++;
break;
case 'O':
voCo++;
break;
case 'U':
voCo++;
break;
default:
break;
}
}
cout<<"Your first and last name have: "<<voCo<<" vowels in them."<<endl;
return voCo;
}

You could try something like this:
const std::string vowels = "aeiou";
const std::string name = "martin luther king, jr.";
const unsigned int name_length = name.length();
unsigned int vowel_count = 0U;
for (unsigned int i = 0U; i < name_length; ++i)
{
if (vowels.find(name[i]) != std::string::npos)
{
++vowel_count;
}
}
No need for switch statement. This is one of many possible algorithms or implementations.
Edit 1: An array of counts
You could also use an array of counts:
unsigned int counts[26] = {0};
for (unsigned int i = 0U; i < name_length; ++i)
{
const c = std::tolower(name[i]);
if (isalpha(c))
{
counts[c - 'a']++;
}
}
const unsigned int vowel count =
counts['a'] + counts['e'] + counts['i']
+ counts['o'] + counts['u'];

First of all decouple user interaction from the logic solving your requirement. I think we can safely assume you can collect the input in this case and save it into an string. So we will not waste our time with that.
We will focus on developing and testing the code that solves the requirement. In a standard C++. Now here is the deep end of the pool. The code.
// mike.h
#pragma once
// std::string view requires C++17
#include <string_view>
// always use namespace,to avoid name clashes
namespace mike {
// make 'sv' the string_view literal available
using namespace std::string_view_literals;
// declare and define compile time
// string view literal
// 'constexpr' guarantees compile time
// notice the use of 'sv'
constexpr auto vowels = "eaiouEAIOU"sv;
// compile time function to count literals
// again 'constexpr' guarantees compile time
// inline gurantees we can include this header many times
// without making accidental duplicates of `count_vowels`
// 'in_' argument has 'std::string_view' passed by value
// pass by value is preferred standard C++ method
// of functions arguments passing
// 'std::string_view' is standard C++ preferred type
// to pass strings into functions
inline constexpr size_t
count_vowels(std::string_view in_)
{
// return type is size_t
// we can count very large number of vowels
// but all at compile time
size_t rezult{};
// this is C+17 'range for'
// we cast implicitly references to input elements
// from, `char const &` to `int const &`
// cost of that is very likely 0
for (int const & ch_ : in_)
for (int const & v_ : vowels)
// there is no if() here
// we simply add 0's or 1's, to the rezult
// false is 0, true is 1
// the correct by the book way of coding that is
// static cast from bool to int
// rezult += static_cast<int>( v_ == ch_ ) ;
rezult += v_ == ch_ ;
return rezult;
}
// runtime speed of this call is 0 (zero)
// all happens at compile time
// notice how we pass normal string literal
// no need to create string_view
constexpr size_t r1
= count_vowels("abra ca dabra");
// no runtime tests necessary
// `static_assert()` is compile time assert
// failure message is optional
static_assert(r1 == 5,
"compile time calculation failed, 'abra ca dabra', must contain 5 vowels");
} // mike ns
Hopefully there are a lots of comments. Solution does not use switch() statement or if() statements. Thanks to standard C++ constructs, code is very simple, resilient and probably very fast when compiled by modern optimizing compilers.
Solution works at compile time too. That is not stopping you to use it in your run-time scenario. Although, I would advise again using native char array. std::string might be a perfect match here.
std::string input_ = collect_user_input() ;
int rezult = count_vowels(input_);
Enjoy the standard C++ ...

Related

How to make efficient C++ jump table?

I'm beginner to C++ and I have implemented the following simple jump table, but was wondering if I'm doing it the right way. Is there anyway I can improve the following code?
The following code is using a dictionary (I'm from a C# background) to store functions' pointers.
#include <cstdio>
#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;
void Zero() { printf("Zero\n"); }
void One() { printf("One\n"); }
void Two() { printf("Two\n"); }
void Three() { printf("Three\n"); }
string prompt()
{
printf("Enter number from 0 to 3 or q to quit:\n");
string line;
getline(cin, line);
return line;
}
int main(int argc, const char * argv[]) {
unordered_map<string, void(*)()> map;
map["0"] = Zero;
map["1"] = One;
map["2"] = Two;
map["3"] = Three;
while (true) {
string c = prompt();
if (c == "q") break;
map[c]();
}
return 0;
}
How about a switch statement?
switch (c) {
case 0:
printf("Zero\n"); break;
case 1:
printf("One\n"); break;
case 2:
printf("Two\n"); break;
case 3:
printf("Three\n"); break;
default:
break;
}
There's not much you can do to make your code "faster" without going for the switch solution which breaks the original idea of having an array of functions. If you only gonna use 'characters' such as '0' => '9', 'a' => 'z' you could dodge the memory allocation needed for the string, and you could also initialize your map with an initializer_list, and you could also make such array const static if that's viable.
Here goes my "optimized" code if it helps.
inline char prompt() //this function will probably 900% be inlined even if you don't specify the inlike keyword
{
printf("Enter number from 0 to 3 or q to quit:\n");
char v;
while (!(std::cin >> v)); //Just to make sure we get valid input
return v;
}
int main()
{
static const std::unordered_map<char, void(*)()> mymap =
{
{ '0' , Zero },
{ '1' , One },
{ '2' , Two },
{ '3' , Three }
};
while(1)
{
auto it = mymap.find(prompt());
// Without this check, your program will crash if input is invalid.
if (it != mymap.end())
{
it->second();
break;
}
}
return 0;
}
Pleas provide more details for your case of efficiency. Do you mean memory/cpu cycles/pass-through?
According to your code:
it's not error prone (use auto it = map.find(key); function for searching and check output it != map.end() value, so no new elements will be created)
it's good enough for string key type
you case easily make more flexible by replacing function pointer with std::function<void()>
It terms of more low-level control you can you custom hash function and custom hash tables implementations.
On some data it may be usefull to consider std::map or sorted std::vector as an option.
As static lookup is fast, This will perform very good irrespective of compiler. Jump table differs from compiler to compiler. I would use following code, May be some people will object to this as global are bad. But before commenting, please evaluate this
string prompt()
{
printf("Enter number from 0 to 3 or q to quit:\n");
string line;
getline(cin, line);
return line;
}
enum Choice = {ZERO = 0, ONE, TWO, THREE};
static char *choice_str[] = {
"Zero",
"One",
"Two",
"Three"
};
int main(int argc, const char * argv[]) {
while (true) {
string c = prompt();
if (c == "q")
{
break;
}
else {
assert(atoi(c) >= Choice::ZERO && atoi(c) <=Choice::THREE);
printf("%s\n", choice_str[atoi(c)]);
}
}

Using user input to to return more than one value from a sturcture [duplicate]

This question already has answers here:
Why does C++ not have reflection?
(15 answers)
Closed 8 years ago.
I have a question about structures. I'm trying to have the user input a letter and have the the computer return two values. Here's what I have till now:
#include <iostream>
struct coords{
int coordsx1;
int coordsy1;
} a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p;
int main()
{
char first;
int coordsx1;
int coordsy1;
a.coordsx=0; e.coordsx=0; i.coordsx=0; m.coordsx=0;
b.coordsx=1; f.coordsx=1; j.coordsx=1; n.coordsx=1;
c.coordsx=2; g.coordsx=2; k.coordsx=2; o.coordsx=2;
d.coordsx=3; h.coordsx=3; l.coordsx=3; p.coordsx=3;
cin >> first;
coordsx1= first.coordsx; // this is the part that doesn't work
}
For example if the user inputs 'd' for the variable first, I want the computer to set the value of coordsx1 to be equal to 3 and coordsy1 to be equal to 0 (I haven't done the coordsy1 part yet).
Also, is this a good way to return more than one value for a user input?
What the user inputs in cin >> first is text, and it is stored in first, which is char. This is a variable that contains a character, not the variable whose name is the contained character, which is why it doesn't work.
C++ does not have the reflexive capabilities required to transform the text representation of a variable into the variable name, but you can do the conversion explicitly with chained ifs or, more conveniently, a switch:
switch(first)
{
case 'a':
coordsx1 = a.coordsx;
coordsy1 = a.coordsy;
break;
case 'b':
coordsx1 = b.coordsx;
coordsy1 = b.coordsy;
break;
case 'c':
coordsx1 = c.coordsx;
coordsy1 = c.coordsy;
break;
// All other cases
default:
std::cerr << "Wrong input" << std::endl;
}
Alternatively, you can simply put your data in an array and use the characters to index it, this also makes the data initialisation more readable:
#include <iostream>
struct Coords
{
int x;
int y;
};
Coords coords[3] = {
{ 1, 2 }, // a
{ 2, 3 }, // b
{ 3, 4 }, // c
};
int main(int arg, char** argv)
{
char first;
int coordsx1;
int coordsy1;
std::cin >> first;
if (first > 'c' || first < 'a')
{
std::cerr << "Wrong input" << std::endl;
return 1;
}
int index = first - 'a'; // Convert 'a' into 0, 'b' into 1, etc.
coordsx1 = coords[index].x;
coordsy1 = coords[index].y;
}
Ups :-)
You first have to learn that a character in runtime is not a variable definition from compile time!
What you get from cin is a character because you made
char first;
so if you want to select from this input your output, you have to write a cascade of case statements like:
switch ( first ) {
case 'a': coordsx1=a.coordsx; coordsy1=a.coordsy; break;
case 'b': coordsx1=b.coordsx; coordsy1=b.coordsy; break;
... a lot more ...
default: std::cerr << "Unknown value entered" << std::endl;
}
please have a look at std::vector or std::map. Both containers can help a lot in this use case!

How do I count vowels in a string using recursion

I'm trying to count the number of vowels in a string using recursion. Here is what I have so far:
int vowels(string str, int pos, int length)
{
if (str.length() == 0)
return 0;
switch (str[pos])
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
return 1 + vowels(str.substr(1), pos, length);
default:
return vowels(str.substr(1), pos, length);
}
}
int main()
{
string str;
int len;
cout << "Enter a string: ";
getline(cin, str);
cout << endl;
len = static_cast<int>(str.length());
cout << "Number of vowels in \"" << str << "\" = "
<< vowels(str, 0, len) << endl;
return 0;
}
The problem is, I need to set pos to 0 only on the first time the vowels function is called without resetting it to 0 on subsequent recursive calls. Also, instead of using substrings, I need to increment pos before each recursive call of vowels(). Also, the base case should be when pos == length (when there are no more characters to check in the string).
Seems like you forgot to increment pos:
/* inside the vowels function switch statement */
return 1 + vowels(str.substr(1), pos+1, length);
default:
return vowels(str.substr(1), pos+1, length);
Besides, if you change the end of recursion condition to "pos==str.length()" you won't be needing str.substr(...) at all. Also, pass std::string by const reference (it's a good habit), if you do skip substr(...).
I would define the function the following way
#include <cstring>
#include <string>
std::string::size_type count_vowels( const std::string &s,
std::string::size_type pos,
std::string::size_type length )
{
const char *vowels = "aeiouAEIOU";
if ( s.length() <= pos || length == 0 ) return 0;
return ( s[pos] && std::strchr( vowels, s[pos] ) != 0 ) +
count_vowels( s, pos + 1, length - 1 );
}
And using your approach
#include <string>
std::string::size_type count_vowels( const std::string &s,
std::string::size_type pos,
std::string::size_type length )
{
if ( s.length() <= pos || length == 0 ) return 0;
std::string::size_type n = 0;
switch ( s[pos] )
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
++n;
default:
return n + count_vowels( s, pos + 1, length - 1 );
}
}
You shouldn't use recursion for this problem. There are times when it is sensible to use recursion when you're doing C++ development, but for general use the lack of tail-call elision represents a little bit of a performance bottleneck. Generally speaking, if a recursive process only calls itself once per invocation, you're probably better off using a loop. If a recusive process calls itself twice (eg. descending into the left and right branches of a tree-type data structure, or perhaps computing a fibonacci sequence), it may be easier to use a recursive function instead of a loop.
That said, this is clearly a homework assignment, and sensible software development practises have no place there.
Passing in pos and length as well as a string seems silly... C++ has already provided you with a nice general purpose tool to deal with iterating through a collection (and a string is just an iterable collection of characters after all) in the form of... Iterators!
Iterators effectively encapsulate the notion of 'position' within a container. string::begin() gets you an Iterator pointing to the beginning of the string, and string::end() gets you one pointed to the end. You can dereference a non-end iterator to get the character it points at (much like a pointer), and increment an iterator to advance it to the next element in the collection.
Here's an example which simply counts characters, but I'm sure you'll be able to adapt it to your needs.
template<class Iterator>
int count_characters(Iterator begin, Iterator end)
{
// if we're at the end of the string, there's nothing more to count
if (begin == end)
return 0;
else // note the pre-increment here. post-increment won't work.
return 1 + count_characters(++begin, end);
}
It can be used like this:
std::string foo = "a phrase, yay";
std::cout << count_characters(foo.begin(), foo.end());
By way of a bonus, it can be used on any other simple container... a vector or set of char would work just as well as a string here, because iterators provide a nice generic way to work with containers. This facility probably isn't of interest for this specific homework question, however.
One function, no need for wrappers or passing superfluous parameters around. Be cautious if you copypaste this into the work you hand in; if you don't understand template it'll be a sure sign of thoughtless plagiarism ;-)

How to add dot character to a character in string?

I want to add '.' character besides another character in a string but I don't know how to do it ? is it possible?
#include <iostream>
#include <string.h>
using namespace std;
int main(int argc, char *argv[]) {
string input;
char dot='.';
cin>>input;
for(int i=0;i<input.length();i++)
{
if( input[i]>=65 && input[i]<=90)
{
input[i]=input[i]+32;
}
if( (input[i]=='a') || (input[i]=='e') || (input[i]=='i') || (input[i]=='o') || input[i]=='y' || input[i]=='u' )
{
input.erase(i,i+1);
}
input[i]+=dot;
}
cout<<input<<endl;
return 0;
}
From the cpluplus.com reference ( http://www.cplusplus.com/reference/string/string/insert/ )
// inserting into a string
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str="to be question";
string str2="the ";
string str3="or not to be";
string::iterator it;
// used in the same order as described above:
str.insert(6,str2); // to be (the )question
str.insert(6,str3,3,4); // to be (not )the question
str.insert(10,"that is cool",8); // to be not (that is )the question
str.insert(10,"to be "); // to be not (to be )that is the question
str.insert(15,1,':'); // to be not to be(:) that is the question
it = str.insert(str.begin()+5,','); // to be(,) not to be: that is the question
str.insert (str.end(),3,'.'); // to be, not to be: that is the question(...)
str.insert (it+2,str3.begin(),str3.begin()+3); // (or )
cout << str << endl;
return 0;
}
Also, check these links:
http://www.cplusplus.com/reference/string/string/
http://www.cplusplus.com/reference/string/string/append/
http://www.cplusplus.com/reference/string/string/push_back/
Before you try writing the code, you should write a detailed
specification of what it is supposed to do. With your code, I
can only guess: convert to lower case (naïvely, pretending that
you'll only encounter the 26 unaccented letters in ASCII), then
delete all vowels (again, very naïvely, since determining
whether something is a vowel or not is non-trivial, even in
English—consider the y in yet and day), and finally
inserting a dot after each character. The most obvious way of
doing that would be something like:
std::string results;
for ( std::string::const_iterator current = input.begin(),
end = input.end();
current != end;
++ current ) {
static std::string const vowels( "aeiouAEIOU" );
if ( std::find( vowels.begin(), vowels.end(), *current )
!= vowels.end() ) {
results.push_back(
tolower( static_cast<unsigned char>( *current ) ) );
}
results.push_back( '.' );
}
But again, I'm just guessing as to what you are trying to do.
Another alternative would be to use std::transform on the
initial string to make it all lower case. If you're doing this
sort of thing regularly, you'll have a ToLower functional
object; otherwise, it's probably too much of a bother to write
one just to be able to use std::transform once.
I’m assuming you want this input:
Hello world!
To give you this output:
h.ll. w.rld!
Rather than trying to modify the string in place, you can simply produce a new string as you go:
#include <cctype>
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char *argv[]) {
string input;
getline(cin, input);
string output;
const string vowels = "aeiouy";
for (int i = 0; i < input.size(); ++i) {
const char c = tolower(input[i]);
if (vowels.find(c) != string::npos) {
output += '.';
} else {
output += c;
}
}
cout << output << '\n';
return 0;
}
Notes:
<cctype> is for toupper().
<string.h> is deprecated; use <string>.
Read whole lines with getline(); istream::operator>>() reads words.
Use tolower(), toupper(), &c. for character transformations. c + 32 doesn’t describe your intent.
When you need comparisons, c >= 'A' && c <= 'Z' will work; you don't need to use ASCII codes.
Use const for things that will not change.
I'm not sure how this old question got bumped back onto the current list, but after reviewing the answers, it looks like all will miss the mark if the input is more than a single word. From your comments, it appears you want to remove all vowels and place a '.' before the character immediately prior to where the removal occurred. Thus your example "tour" becomes ".t.r".
Drawing from the other answers, and shamelessly removing 'y' as from the list of vowels, you can do something similar to:
#include <iostream>
#include <string>
int main()
{
std::string input;
if (!getline (std::cin, input)) {
return 1;
}
size_t i = 0;
for (; input[i]; i++)
{
switch (input[i])
{
case 'A': /* case fall-through intentional */
case 'E':
case 'I':
case 'O':
case 'U':
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
{
size_t pos = input.find_first_not_of("AEIOUaeiou", i+1);
if (pos == std::string::npos) {
pos = input.length();
}
input.erase(i, pos-i);
if (pos - i > 1) {
input.insert(i, 1, '.');
}
input.insert(i-1, 1, '.');
break;
}
}
}
std::cout << input << '\n';
}
Example Use/Output
Your example:
$ ./bin/vowels-rm-mark
tour
.t.r
A longer example:
$ ./bin/vowels-rm-mark
My dog has fleas and my cat has none.
My .dg .hs f.l.s. nd my .ct .hs .n.n.
Based on your comments, it sounds like you want something like this:
#include <iostream>
#include <string>
#include <algorithm>
int main(int argc, char *argv[])
{
std::string input;
std::cin >> input;
std::transform (input.begin(), input.end(), input.begin(), tolower);
size_t i = 0;
while (i < input.length())
{
switch (input[i])
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'y':
case 'u':
{
size_t pos = input.find_first_not_of("aeioyu", i+1);
if (pos == std::string::npos)
pos = input.length();
input.erase(i, pos-i);
break;
}
default:
{
input.insert(i, 1, '.'); // or: input.insert(i, ".");
i += 2;
break;
}
}
}
std::cout << input << std::endl;
return 0;
}

string conversion c++

I have a string and the first element is for example 'a'. I already declared a variable called a ( so int a=1 for example). My question now is, how can I convert the whole string to numbers (a=1,b=2,c=3,...z=26)? Example:
string str="hello"; this has to be changed to "85121215" and then changed to 85121215.
// transformation itself doesn't care what encoding we use
std::string transform_string(std::string const &in, std::function<int(char)> op)
{
std::ostringstream out;
std::transform(in.begin(), in.end(),
std::ostream_iterator<int>(out),
op);
return out.str();
}
// the per-character mapping is easy to isolate
int ascii_az_map(char ch)
{
if (ch < 'a' || ch > 'z') {
std::ostringstream error;
error << "character '" << ch << "'=" << (int)ch
<< " not in range a-z";
throw std::out_of_range(error.str());
}
return 1 + ch - 'a';
}
// so we can support other encodings if necessary
// NB. ebdic_to_ascii isn't actually implemented here
int ebcdic_az_map(char ch)
{
return ascii_az_map(ebcdic_to_ascii(ch));
}
// and even detect the platform encoding automatically (w/ thanks to Phresnel)
// (you can still explicitly select a non-native encoding if you want)
int default_az_map(char ch)
{
#if ('b'-'a' == 1) && ('j' - 'i' == 1)
return ascii_az_map(ch);
#elif ('j'-'i' == 8)
return ebcdic_az_map(ch);
#else
#error "unknown character encoding"
#endif
}
// use as:
std::string str = "hello";
std::string trans = transform_string(str, ascii_az_map);
// OR ... transform_string(str, ebcdic_az_map);
Note that since the per-character mapping is completely isolated, it's really easy to change the mapping to a lookup table, support different encodings etc.
Your definition is a bit small:
"hello" = "85121215
h = 8
e = 5
l = 12
o = 15
I assume you mean that
a = 1
b = 2
...
z = 26
in which case it is not that hard:
std::string meh_conv(char c) {
switch(c) { // (or `switch(tolower(c))` and save some typing)
case 'a': case 'A': return "1";
case 'b': case 'B': return "2";
....
case 'z': case 'Z': return "26";
....
// insert other special characters here
}
throw std::range_error("meh");
}
std::string meh_conv(std::string const &src) {
std::string dest;
for (const auto c : s)
dest += meh_conv(c);
return dest;
}
or use std::transform():
#include <algorithm>
std::string dest;
std::transform (src.begin(), src.end(), back_inserter(dest),
meh_conv)
(doesn't work for different incoming and outgoing types, at least not as is)
Addendum.
You possibly want to parametrize the replacement map:
std::map<char, std::string> repl;
repl['a'] = repl['A'] = "0";
repl[' '] = " ";
std::string src = "hello";
std::string dest;
for (const auto c : src) dest += repl[c];
I wrote you a simple example. It creates a map what contains the a-1, b-2, c-3 ... pairs. Then concatenate the values using a stringstream:
#include <iostream>
#include <map>
#include <sstream>
int main()
{
std::string str = "abc";
std::map<char,int> dictionary;
int n = 1;
for(char c='a'; c<='z'; c++)
dictionary.insert(std::pair<char,int>(c,n++));
//EDIT if you want uppercase characters too:
n=1;
for(char c='A'; c<='Z'; c++)
dictionary.insert(std::pair<char,int>(c,n++));
std::stringstream strstream;
for(int i=0; i<str.size(); i++)
strstream<<dictionary[str[i]];
std::string numbers = strstream.str();
std::cout<<numbers;
return 0;
}
C++ experts probably going to kill me for this solution, but it works ;)
Easy Approach,
you can find mod of char with 96 (ASCII value before a), as result it will always give you values in range 1-26.
int value;
string s;
cin>>s;
for(int i=0; i<s.size();i++){
value = s[j]%96;
cout<<value<<endl;
}