So I am making a small program.You enter a string then my program outputs the string except where a was a consonant is now a "C" and for vowels a "V".Why does it output wrong when I enter "Elicopter" and maybe other words?
#include <iostream>
#include <string>
using namespace std;
int main()
{
const char con[]={'b','c','d','f','g','h','i','j','k','l','m','n','p','q','r','s','t','v','w','x','y','z','B','C','D','F','G','H','I','J','K','L','M','N','P','Q','R','S','T','V','W','X','Y','Z'};
const char vow[]={'a','e','i','o','u','A','E','I','O','U'};
const char car[]={'!','#','#','$','%','^','&','*','?','+','-','_','0','1','2','3','4','5','6','7','8','9'};
int scon=sizeof(con)/sizeof(con[0]);
int svow=sizeof(vow)/sizeof(vow[0]);
int scar=sizeof(car)/sizeof(car[0]);
string x;
int i,j;
getline(cin,x);
for(i=0;i<x.length();i++){
if(x[i]==' '){
cout<<" ";
}
else{
for(j=0;j<scon;j++){
if(x[i]==con[j]){
cout<<"C";
break;
}
}
for(j=0;j<svow;j++){
if(x[i]==vow[j]){
cout<<"V";
break;
}
}
for(j=0;j<scar;j++){
if(x[i]==car[j]){
cout<<x[i];
break;
}
}
}
}
return 0;
}
I am sorry my code is a mess.
Aside from the obvious already pointed out by #1201ProgramAlarm ('i' being in the list of consonants), there is lots of very unidiomatic code in there -- the way you would code in C, and rather low quality C at that (no offense).
While no code is ever perfect, perhaps you might benefit from having a look at the same (well, a pretty similar...) program, written in actual C++. Just to get an idea what you could do.
#include <iostream>
#include <string>
#include <string_view>
#include <locale>
// "using namespace" is a habit that tends to get in the way
// once you start including headers from multiple namespaces,
// so while it has its place in quick one-shots, personally I
// got into the habit of fully qualifying.
int main()
{
// This is, of course, very non-international, but I will
// let this slide and not drag the ICU library into this...
std::string_view const consonants { "bcdfghjklmnpqrstvwxyz" };
std::string_view const vowels { "aeiou" };
std::string input;
// while instead of if allows you to make multiple lines of
// input. <Ctrl>-D to end the program (<Ctrl>-Z <Enter> on
// Windows).
while ( getline( std::cin, input ) )
{
// Range-For eliminates the need for loop counters / iterators
for ( auto const c : input )
{
if ( consonants.find( std::tolower( static_cast<unsigned char>( c ) ) ) != std::string::npos )
{
std::cout << 'C';
}
else if ( vowels.find( std::tolower( static_cast<unsigned char>( c ) ) ) != std::string::npos )
{
std::cout << 'V';
}
else if ( std::isprint( static_cast<unsigned char>( c ) ) )
{
// Not exactly the same as your list of digits
// and punctuation, but similar, and showing the
// use of character types. isprint() is also true
// for ' '.
std::cout << c;
}
}
// std::endl ensures a flush of the write buffer
std::cout << std::endl;
}
}
Related
I've been looking for ways to count the number of words in a string, but specifically for strings that may contain typos (i.e. "_This_is_a___test" as opposed to "This_is_a_test"). Most of the pages I've looked at only handle single spaces.
This is actually my first time programming in C++, and I don't have much other programming experience to speak of (2 years of college in C and Java). Although what I have is functional, I'm also aware it's complex, and I'm wondering if there is a more efficient way to achieve the same results?
This is what I have currently. Before I run the string through numWords(), I run it through a trim function that removes leading whitespace, then check that there are still characters remaining.
int numWords(string str) {
int count = 1;
for (int i = 0; i < str.size(); i++) {
if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') {
bool repeat = true;
int j = 1;
while (j < (str.size() - i) && repeat) {
if (str[i + j] != ' ' && str[i + j] != '\t' && str[i + j] != '\n') {
repeat = false;
i = i + j;
count++;
}
else
j++;
}
}
}
return count;
}
Also, I wrote mine to take a string argument, but most of the examples I've seen used (char* str) instead, which I wasn't sure how to use with my input string.
You don't need all those stringstreams to count word boundary
#include <string>
#include <cctype>
int numWords(std::string str)
{
bool space = true; // not in word
int count = 0;
for(auto c:str){
if(std::isspace(c))space=true;
else{
if(space)++count;
space=false;
}
}
return count;
}
One solution is to utilize std::istringstream to count the number of words and to skip over spaces automatically.
#include <sstream>
#include <string>
#include <iostream>
int numWords(std::string str)
{
int count = 0;
std::istringstream strm(str);
std::string word;
while (strm >> word)
++count;
return count;
}
int main()
{
std::cout << numWords(" This is a test ");
}
Output:
4
Albeit as mentioned std::istringstream is more "heavier" in terms of performance than writing your own loop.
Sam's comment made me write a function that does not allocate strings for words. But just creates string_views on the input string.
#include <cassert>
#include <cctype>
#include <vector>
#include <string_view>
#include <iostream>
std::vector<std::string_view> get_words(const std::string& input)
{
std::vector<std::string_view> words;
// the first word begins at an alpha character
auto begin_of_word = std::find_if(input.begin(), input.end(), [](const char c) { return std::isalpha(c); });
auto end_of_word = input.begin();
auto end_of_input = input.end();
// parse the whole string
while (end_of_word != end_of_input)
{
// as long as you see text characters move end_of_word one back
while ((end_of_word != end_of_input) && std::isalpha(*end_of_word)) end_of_word++;
// create a string view from begin of word to end of word.
// no new string memory will be allocated
// std::vector will do some dynamic memory allocation to store string_view (metadata of word positions)
words.emplace_back(begin_of_word, end_of_word);
// then skip all non readable characters.
while ((end_of_word != end_of_input) && !std::isalpha(*end_of_word) ) end_of_word++;
// and if we haven't reached the end then we are at the beginning of a new word.
if ( end_of_word != input.end()) begin_of_word = end_of_word;
}
return words;
}
int main()
{
std::string input{ "This, this is a test!" };
auto words = get_words(input);
for (const auto& word : words)
{
std::cout << word << "\n";
}
return 0;
}
You can use standard function std::distance with std::istringstream the following way
#include <iostream>
#include <sstream>
#include <string>
#include <iterator>
int main()
{
std::string s( " This is a test" );
std::istringstream iss( s );
auto count = std::distance( std::istream_iterator<std::string>( iss ),
std::istream_iterator<std::string>() );
std::cout << count << '\n';
}
The program output is
4
If you want you can place the call of std::distance in a separate function like
#include <iostream>
#include <sstream>
#include <string>
#include <iterator>
size_t numWords( const std::string &s )
{
std::istringstream iss( s );
return std::distance( std::istream_iterator<std::string>( iss ),
std::istream_iterator<std::string>() );
}
int main()
{
std::string s( " This is a test" );
std::cout << numWords( s ) << '\n';
}
If separators can include other characters apart from white space characters as for example punctuations then you should use methods of the class std::string or std::string_view find_first_of and find_first_not_of.
Here is a demonstration program.
#include <iostream>
#include <string>
#include <string_view>
size_t numWords( const std::string_view s, std::string_view delim = " \t" )
{
size_t count = 0;
for ( std::string_view::size_type pos = 0;
( pos = s.find_first_not_of( delim, pos ) ) != std::string_view::npos;
pos = s.find_first_of( delim, pos ) )
{
++count;
}
return count;
}
int main()
{
std::string s( "Is it a test ? Yes ! Now we will run it ..." );
std::cout << numWords( s, " \t!?.," ) << '\n';
}
The program output is
10
you can do it easily with regex
int numWords(std::string str)
{
std::regex re("\\S+"); // or `[^ \t\n]+` to exactly match the question
return std::distance(
std::sregex_iterator(str.begin(), str.end(), re),
std::sregex_iterator()
);
}
I am new to C++ and want to test out how much I actually learned so I made this simple cRaZyTeXt generator. But there's a weird bug I can't find any way to solve.
Codes are here:
#include <iostream>
#include <string>
#include <algorithm>
#include <windows.h>
char convertToUppercase (char x)
{
int asciiCode {static_cast<int>(x) - 32};
char y {static_cast<char>(asciiCode)};
return y;
}
char convertToLowercase (char x)
{
int asciiCode {static_cast<int>(x) + 32};
char y {static_cast<char>(asciiCode)};
return y;
}
void toClipboard(const std::string &s){
OpenClipboard(0);
EmptyClipboard();
HGLOBAL hg=GlobalAlloc(GMEM_MOVEABLE,s.size() + 1);
if (!hg){
CloseClipboard();
return;
}
memcpy(GlobalLock(hg),s.c_str(),s.size() + 1);
GlobalUnlock(hg);
SetClipboardData(CF_TEXT,hg);
CloseClipboard();
GlobalFree(hg);
}
int main()
{
std::cout << "Enter the text you want to convert into cRaZy TeXt: " << '\n';
std::string userInput {};
std::getline(std::cin >> std::ws, userInput);
char userInputArray [userInput.size()];
std::copy(userInput.begin(), userInput.end(), userInputArray);
char outputArray [userInput.size()];
for (int i = 0; i <= userInput.size(); ++i)
{
int x {static_cast<int>(userInputArray[i])};
if (i % 2 == 0)
{
if (x <= 90 && x >= 65)
outputArray[i] = convertToLowercase(userInputArray[i]);
else
outputArray[i] = userInputArray[i];
}
else
{
if (x <= 122 && x >= 97)
outputArray[i] = convertToUppercase(userInputArray[i]);
else
outputArray[i] = userInputArray[i];
}
}
std::cout << outputArray << '\n';
toClipboard(outputArray);
system("pause");
return 0;
}
when I enter Hello, world!, it can output hElLo, WoRlD! as exactly how I want it to be. proof
But when I try my name is sean., its output would look like this: screenshot
mY NaMe iS SeAn.#y name is sean.#%�
What's more weird is that both my name is ma sean. and my name is sean ma. works fine.
my name is ma sean.
my name is sean ma.
I have tried above four inputs in both release and debug configuration and it's all the same.
Please elaborate on the issue and make the explanation friendlier for beginners.
Any helps are appreciated. Thank you in advance.
For starters variable length arrays as for example the declaration of this array
char userInputArray [userInput.size()];
is not a standard C++ feature.
There is no need to use auxiliary arrays to perform the task. You could change the original object userInput of the type std::string itself.
This variable length array
char outputArray [userInput.size()];
does not contain a space for the terminating zero character '\0' to make the stored sequence of characters a string.
As a result this output
std::cout << outputArray << '\n';
invokes undefined behavior.
This for loop
for (int i = 0; i <= userInput.size(); ++i)
leads to access memory beyond the declared variable length arrays because the valid range of indices is [ 0, userInput.size() ).
Also it is a bad idea to use magic numbers like for example 65 or 90. This makes the code unreadable.
If I have understood correctly what you need is a function like the following shown in the demonstrative program below.
#include <iostream>
#include <string>
#include <cctype>
std::string & cRaZyTeXt_generator( std::string &s )
{
int upper_case = 1;
for (auto &c : s)
{
if ( std::isalpha( static_cast< unsigned char >( c ) ) )
{
if ( ( upper_case ^= 1 ) )
{
c = std::toupper( static_cast< unsigned char >( c ) );
}
else
{
c = std::tolower( static_cast< unsigned char >( c ) );
}
}
}
return s;
}
int main()
{
std::string s( "Hello, World!" );
std::cout << s << '\n';
std::cout << cRaZyTeXt_generator( s ) << '\n';
}
The program output is
Hello, World!
hElLo, WoRlD!
#include<iostream>
using namespace std;
void recursiveToLower(char str[])
{
do {
str[0] = toupper( str[0] );
recursiveToLower( str+1 );
}
while ( str[0] != '\0' );
}
int main()
{
char str[];
cin.get(str,80)
cout<<str;
recursivetoLower(str);
}
I have been trying to convert lower case to upper case using recursive function and do while loop
as far as I know the syntax is fine but code is not working need help to compile it while compiling the code it is giving me some errors.
There is no use of the 'do while' loop if you want to use recursion. Either of them can be used to solve the problem. Also, there are few other errors as well, like you have not provided the size of the char array, which is required at the time of array declaration. And also you might have mistakenly called for the wrong function 'recursivetoLower(str)'
though the actual function you have created is 'recursiveToLower(char str[])'.
Remove the loop and insert a base condition and it should work. See the following code for reference.
void recursiveToLower(char str[])
{
if(str[0] == '\0'){
return;
}
str[0] = toupper( str[0] );
recursiveToLower( str+1 );
}
int main(){
char str[80];
cin.get(str,80);
cout<<str << endl;
recursiveToLower(str);
cout << str;
}
You either need iteration or recursion but not both!
Recursive:
void recursiveToLower(char str[])
{
if(str[0] == '\0') return; //Base Case
str[0] = tolower( str[0] );
recursiveToLower( str+1 );
}
Iterative :
void iterativeToLower(char str[])
{
do {
str[0] = tolower( str[0] );
str += 1;
} while ( str[0] != '\0' );
}
You don't need to use a while loop. Just need to keep track of the state and call it recursively.
#include<bits/stdc++.h>
using namespace std;
string recursive(string x, int i){
if(i >= x.size()) return x;
x[i] = toupper(x[i]);
x = recursive(x, i+1);
return x;
}
int main() {
// your code goes here
string x = "Convert to Upper";
cout<<recursive(x, 0);
return 0;
}
Let's see one by one the things that are wrong with your code .
Here's the fixed code ,
#include <iostream>
#include <cctype>
using namespace std;
void recursiveToLower(char str[])
{
if(str[0] != '\0') //replaced while loop with simple if
{
str[0] = tolower(str[0]); //probably should be tolower as the function name suggests
recursiveToLower(str + 1);
}
else
{
return; //break condition for recursion
}
}
int main()
{
const unsigned SZ = 100;
char str[SZ]; //In C++ array size cannot be dynamic , you did not specify array size
cin >> str;
recursiveToLower(str);
cout << str <<endl;
}
Let's start with , loop and recursion don't go together for a task like this . This task could be done with loop or recursion , their combination which you have used don't make much sense , think about it .
Second , in C/C++ , array size should be predefined .
I have added some helpful comments in the corrected code , if you are having problem in some part , you may ask in the comments.
I am writing my own class(called "Longer") such that it can hold a number without any upper bound unlike int. I am using std::string for this.
I am having problem on performing addition.
If i simply add two string, i can't get correct result.
I thought of converting string to int and then performing addition,
but long string can't be converted to int.
How can i define my own way of adding two strings so that i get the desired result? Here is the code:
Longer.h
#pragma once
#include <string>
class Longer
{
public:
Longer(std::string number);
Longer add(Longer num2);
void print();
private:
std::string number;
};
Longer.cpp
#include "Longer.h"
#include <iostream>
#include <string>
Longer::Longer(std::string num): number(num)
{
}
Longer Longer::add(Longer num2){
return Longer(number+num2.number);
}
void Longer::print(){
std::cout<<number<<"\n";
}
main.cpp
#include <iostream>
#include "Longer.h"
int main(){
Longer num1("123456789101112");
Longer num2("121110987654321");
Longer num3 = num1.add(num2);
num3.print();
}
I don't wonder addition doesn't work like you intended. std::string is not meant to be used as an arbitrary-long number container, that's why.
You must define your own way to "add" two strings, which should consist into iterating backwards both strings (from the end) and compare single characters, by interpreting them as numbers.
without any upper bound unlike int
Be careful with such things. There will always be some upper bound with any solution, at the very least when your machine's memory is exhausted. A robust application should always have some kind of error checking.
If i simply add two string, i can't get correct result.
Well, that's obvious, isn't it? String concatentation doesn't know anything about mathematical semantics.
I thought of converting string to int and then performing addition,
but long string can't be converted to int.
Exactly. Internally converting the string to a built-in type would defeat the whole purpose of the solution.
How can i define my own way of adding two strings so that i get the
desired result?
The goal is apparently to support numbers bigger than what the built-in types provide.
First of all, are you really sure that your application needs to work with such huge numbers? Even a standard int should usually be more than enough, not to mention long long (standard since C++11 but practically usable even before that).
Perhaps what you really need is to detect invalid user input like "10000000000000000000000000".
String streams provide this error detection for you. Here is a complete example for you to play with, including exemplary usage of std::numeric_limits:
#include <iostream>
#include <stdexcept>
#include <exception>
#include <limits>
int ReadInt()
{
int result;
std::cin >> result;
if (!std::cin)
{
throw std::runtime_error("Illegal number");
}
return result;
}
int main()
{
try
{
std::cout << "Enter number (max: " << std::numeric_limits<int>::max() << ") > ";
int input = ReadInt();
std::cout << "You entered the following number: " << input << "\n";
}
catch (std::exception const &exc)
{
std::cerr << exc.what() << "\n";
}
}
Here are three example runs on my machine. The first with a "normal" small number, the second just barely larger than the maximum possible, the third exactly the largest possible integer:
Enter number (max: 2147483647) > 1000
You entered the following number: 1000
Enter number (max: 2147483647) > 2147483648
Illegal number
Enter number (max: 2147483647) > 2147483647
You entered the following number: 2147483647
Now, if you really really must support large integer numbers internally, don't reinvent the wheel. Use Boost.Multiprecision:
http://www.boost.org/doc/libs/1_55_0/libs/multiprecision/doc/html/index.html
Since the documentation of that particular library may be a bit hard to swallow, here is an ultra-simple example to get you started:
#include <iostream>
#include <stdexcept>
#include <exception>
#include <boost/multiprecision/cpp_int.hpp>
int main()
{
try
{
boost::multiprecision::int128_t number("100000000000000000000000000000000");
number *= 2;
std::cout << number << "\n";
}
catch (std::exception const &exc)
{
std::cerr << exc.what() << "\n";
}
}
This actually prints 200000000000000000000000000000000.
#include <iostream>
using namespace std;
class Longer {
public:
Longer(std::string number): number(number) {}
void print() { cout << number << endl; }
Longer add(Longer num2) {
char over = '0'; string it;
for(int i = number.size() - 1,
j = num2.number.size() - 1;
i >= 0 || j >= 0; i--, j--) {
char one = i >= 0 ? number[i] : '0';
char two = j >= 0 ? num2.number[j] : '0';
char dig = one-'0' + two-'0' + over;
over = '0'; if(dig > '9') {
dig -= 10; over = '1'; }
it.insert(0, 1, dig);
}
if(over != '0') it.insert(0, 1, over);
return Longer(it);
}
private:
std::string number;
};
int main() {
Longer num1("123456789101112"); num1.print();
Longer num2("121110987654321"); num2.print();
Longer num3 = num1.add(num2); num3.print();
}
Output:
123456789101112
121110987654321
244567776755433
But if that was not homework, look at boost::multiprecision::cpp_int
Here is a ready to use solution
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <iterator>
class Longer
{
public:
Longer() : value( 1, '0' ) {}
Longer (std::string s )
: value( s.rbegin(), s.rend() )
{}
Longer( const char *s )
: value( std::reverse_iterator<const char *>( s + std::strlen( s ) ),
std::reverse_iterator<const char *>( s ) )
{}
const Longer add( const Longer &number ) const;
void print( std::ostream &os = std::cout ) const
{
os << std::string( value.rbegin(), value.rend() );
}
private:
std::string value;
};
const Longer Longer::add( const Longer &number ) const
{
std::pair<std::string::size_type, std::string::size_type> sizes =
std::minmax( this->value.size(), number.value.size() );
std::string result;
result.reserve( sizes.second + 1 );
int overflow = 0;
auto out = std::transform( this->value.begin(),
std::next( this->value.begin(), sizes.first ),
number.value.begin(),
std::back_inserter( result ),
[&] ( char c1, char c2 ) ->char
{
char c = ( c1 - '0' ) + ( c2 -'0' ) + overflow;
overflow = c / 10;
return c % 10 + '0';
} );
std::string::const_iterator first, last;
if ( this->value.size() < number.value.size() )
{
first = std::next( number.value.begin(), sizes.first );
last = number.value.end();
}
else
{
first = std::next( this->value.begin(), sizes.first );
last = this->value.end();
}
std::transform(first, last, out,
[&]( char c )
{
return ( c = c - '0' + overflow ),
( overflow = c / 10 ),
( c % 10 + '0' );
} );
if ( overflow ) result.push_back( overflow + '0' );
Longer n;
n.value = result;
return n;
}
int main()
{
Longer n1( "12345678912345678" );
n1.print();
std::cout << std::endl;
Longer n2( "1123" );
n2.print();
std::cout << std::endl;
Longer n3 = n2.add( "877" );
n3.print();
std::cout << std::endl;
Longer n4( "9999999999" );
n4.print();
std::cout << std::endl;
Longer n5 = n4.add( "1" );
n5.print();
std::cout << std::endl;
return 0;
}
The output is
12345678912345678
1123
2000
9999999999
10000000000
Take into account that it is more convinient to store the string in the reverse order inside the class.
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;
}