isalpha causing a "Debug Assertion Failed" in c++ - c++

I have a short program designed to count the number of consonants in a string by first testing to see if the character in the array is an alpha character (to skip any white space or punctuation). I keep getting a Debug Assertion Failed for my "if (isalpha(strChar))" line of code.
"strChar" is a variable that is assigned the char value in a for loop
Sorry if this is a remedial issue, but I'm not sure where I'm going wrong. Thanks in advance for any help!
#include <iostream>
#include <cctype>
using namespace std;
int ConsCount(char *string, const int size);
int main()
{
const int SIZE = 81; //Size of array
char iString[SIZE]; //variable to store the user inputted string
cout << "Please enter a string of no more than " << SIZE - 1 << " characters:" << endl;
cin.getline(iString, SIZE);
cout << "The total number of consonants is " << ConsCount(iString, SIZE) << endl;
}
int ConsCount(char *string, const int size)
{
int count;
int totalCons = 0;
char strChar;
for (count = 0; count < size; count++)
{
strChar = string[count];
if (isalpha(strChar))
if (toupper(strChar) != 'A' || toupper(strChar) != 'E' || toupper(strChar) != 'I' || toupper(strChar) != 'O' || toupper(strChar) != 'U')
totalCons++;
}
return totalCons;
}

I guess the problem is that you are always looping through 81 characters even though less were entered. That results in some random data fed to isalpha().
Anyway, I would change to code to use std::string instead of char iString[SIZE] to get the actual length of the input text.

The function ConsCount(char* string, const int size) should be like this:
int ConsCount(char *string, const int size)
{
int consCount = 0;
char* begin = string;
for (char* itr = begin; *itr != '\0'; ++itr)
{
if (isalpha(*itr)) {
char ch = toupper(*itr);
switch(ch) {
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
break; // If ch is any of 'A', 'E', 'I', 'O', 'U'
default:
++consCount;
}
}
}
return consCount;
}
As you can see I replaced the if statement with switch for better readability and using char* as a iterator to iterate the string. You can remove the unused parameter int size in your code.
And also I suggest you to use std::string for the safe-code. It also provides you a iterator class to iterate over the std::string.

int ConsCount(char *string, const int size)
{
int consCount = 0;
char* begin = string;
for (char* itr = begin; *itr != '\0'; ++itr)
{
if (isalpha(*itr)) {
char ch = toupper(*itr);
switch(ch) {
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
break; // If ch is any of 'A', 'E', 'I', 'O', 'U'
default:
++consCount;
}
}
}
return consCount;
try this
}

Related

char array c++ vowels

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++ ...

Go word-by-word through a text file and replace certain words

My intended program is simple: Take each word of a text file and replace it with asterisks if it's a swear word. For instance, if the text file was "Hello world, bitch" then it would be modified to "Hello world, *****".
I have the tool for taking a word as a string and replacing it with asterisks if needed. I need help setting up the main part of my program because I get confused with all the fstream stuff. Should I instead make a new file with the replaced words and then overwrite the previous file?
#include <iostream>
#include <string>
#include <fstream>
const char* BANNED_WORDS[] = {"fuck", "shit", "bitch", "ass", "damn"};
void filter_word(std::string&);
void to_lower_case(std::string&);
int main (int argc, char* const argv[]) {
return 0;
}
void filter_word(std::string& word) {
std::string wordCopy = word;
to_lower_case(wordCopy);
for (int k = 0; k < sizeof(BANNED_WORDS)/sizeof(const char*); ++k)
if (wordCopy == BANNED_WORDS[k])
word.replace(word.begin(), word.end(), word.size(), '*');
}
void to_lower_case(std::string& word) {
for (std::string::iterator it = word.begin(); it != word.end(); ++it) {
switch (*it) {
case 'A': *it = 'a';
case 'B': *it = 'b';
case 'C': *it = 'c';
case 'D': *it = 'd';
case 'E': *it = 'e';
case 'F': *it = 'f';
case 'G': *it = 'g';
case 'H': *it = 'h';
case 'I': *it = 'i';
case 'J': *it = 'j';
case 'K': *it = 'k';
case 'L': *it = 'l';
case 'M': *it = 'm';
case 'N': *it = 'n';
case 'O': *it = 'o';
case 'P': *it = 'p';
case 'Q': *it = 'q';
case 'R': *it = 'r';
case 'S': *it = 's';
case 'T': *it = 't';
case 'U': *it = 'u';
case 'V': *it = 'v';
case 'W': *it = 'w';
case 'X': *it = 'x';
case 'Y': *it = 'y';
case 'Z': *it = 'z';
}
}
}
The usual solution to modifying a file is to generate a new
file, then delete the old and rename the new. In your case,
because your replacement text has exactly the same length as
your new text, you can do it in place, with something like:
std::fstream file( fileName, ios_base::in | ios_base::out );
if ( !file.is_open() ) {
// put error handling here...
std::string word;
std::fstream::pos_type startOfWord;
while ( file.peek() != std::fstream::traits::eof() ) {
if ( ::isalpha( file.peek() ) ) {
if ( word.empty() ) {
startOfWord = file.tellg();
}
word += file.get();
} else {
if ( !word.empty() ) {
if ( std::find_if( banned.begin(), banned.end(), CaseInsensitiveCompare() ) ) {
file.seekp( startOfWord );
file.write( std::string( word.size(), '*').c_str(), word.size() );
}
word.clear();
}
file.get();
}
}
with:
struct CaseInsensitiveCompare
{
bool operator()( unsigned char lhs, unsigned char rhs ) const
{
return ::tolower( lhs ) == ::tolower( rhs );
}
bool operator()( std::string const& lhs, std::string const& rhs ) const
{
return lhs.size() == rhs.size()
&& std::equal( lhs.begin(), lhs.end(), rhs.begin(), *this )
}
};
The tellg and seekp probably aren't the most efficient
operations around, but if the file is large, and you don't have
to seek too often, it may still be more efficient than writing
a completely new file. Of course, if efficiency is an issue,
you might want to consider mmap, and doing the job directly in
memory. That would certainly be the most efficient, and
probably the easiest to code as well. But it would be platform
dependent, and would require extra effort to handle files larger
than your available address space.
Also, for the future (since there is a standard tolower that
you can use), when doing code translation (which is really what
to_lower_case does), use a table. It's much simpler and
faster:
char
to_lower_case( char ch )
{
char translationTable[] =
{
// ...
};
return translationTable[static_cast<unsigned char>( ch )];
}
If you don't want your code to be dependent on the encoding, you
can use dynamic initialization:
if ( !initialized ) {
for ( int i = 0; i <= UCHAR_MAX; ++ i ) {
translationTable[i] = i;
}
static char const from[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static char const to[] = "abcdefghijklmnopqrstuvwxyz";
for ( int i = 0; i != sizeof(from); ++ i ) {
translationTable[from[i]] = to[i];
}
}
This is not a good idea for things like tolower, however;
you would have to know all of the possible upper case
characters, which in turn depends on the encoding. (The
functions in <ctype.h> do do something like this. And
redefine the translation table each time you change locale.) It
can be useful for other types of mappings.
I think you need a code to read file word by word and replace if the word is one of BANNED_WORDS
So here is a solution for main():
int main()
{
std::vector <std::string> words; // Vector to hold our words we read in.
std::string str; // Temp string to
std::cout << "Read from a file!" << std::endl;
std::ifstream fin("thisfile.txt"); // Open it up!
while (fin >> str) // Will read up to eof() and stop at every
{ // whitespace it hits. (like spaces!)
words.push_back(str);
}
fin.close(); // Close that file!
std::ofstream fout("temp.txt"); // open temp file
for (int i = 0; i < words.size(); ++i)
{ // replace all words and add it to temp file
filter_word(words.at(i));
fout<<words.at(i) << endl;
}
// Add code for replace the file
return 0;
}
And for to_lower_case() you can use
#include <ctype.h>
// ...
*it = tolower(*it);
As suggested by Paul Evans
Hope this will help you

C++ find special char and move to the end of a string

I am currently a student taking C++. My issue is that my nested if statement does not find the special chars if they are at the end of the word. From what I can tell, it does not run the function at all. If anyone has any idea what is wrong that will be great!
#include <iostream>
#include <string>
using namespace std;
bool isVowel(char ch);
string rotate(string pStr);
string pigLatinString(string pStr);
bool specialChar(char ch);
int main() {
string str, str2, pigsentence, finalsentence, orgstr, end;
int counter, length, lengtho;
counter = 1;
cout << "Enter a string: ";
getline (cin, str);
cout << endl;
orgstr = str;
//Add in option to move special chars
string::size_type space;
do {
space = str.find(' ', 0); //Finds the space(s)
if(space != string::npos){
str2 = str.substr(0, space); //Finds the word
if(specialChar(str[true])) { //Finds special char
end = str.substr(space - 1); //Stores special char as end
cout << end << endl; //Testing end
str.erase(space - 1); //Erases special car
}
str.erase(0, space + 1); //Erases the word plus the space
pigsentence = pigLatinString(str2); //converst the word
finalsentence = finalsentence + " " + pigsentence + end; //Adds converted word to final string
}else {
length = str.length();
str2 = str.substr(0, length); //Finds the word
if(specialChar(str[true])) { //Finds special char
end = str.substr(space - 1); //Stores special char as end
cout << end << endl; //Testing end
str.erase(space - 1); //Erases special car
}
str.erase(0, length); //Erases the word
pigsentence = pigLatinString(str2); //converst the word
finalsentence = finalsentence + " " + pigsentence + end; //Adds converted word to final string
counter = 0;
}
}while(counter != 0); //Loops until counter == 0
cout << "The pig Laten form of " << orgstr << " is: " << finalsentence << endl;
return 0;
}
The function that lists the specialChars is below
bool specialChar(char ch) {
switch(ch) {
case ',':
case ':':
case ';':
case '.':
case '?':
case '!':
return true;
default:
return false;
}
}
I do have other functions but they are working and just convert a word to piglatin.
your isSpecialChar takes a character as argument so str[index] would be something you could pass but instead you write str[true] which is not correct. If you want to check if there is a specialChar in your string you need to loop through the whole string and check each character.
It seems as if you want to split up a string into words so you could write something like this
char Seperator = ' ';
std::istringstream StrStream(str);
std::string Token;
std::vector<std::string> tokens;
while(std::getline(StrStream, Token, Seperator))
{
tokens.push_back(Token);
}
now that you have the words in a vector you can do whatever what you want
with them like checking for a special char
for (int i = 0; i < tokens.size(); ++i)
{
std::string& s = tokens[i];
for (int j = 0; j < s.length(); ++j)
{
if ( specialChar( s[j] )
{
...do whatever...
}
}
}
You're using true as your array index when passing arguments to the specialChar() function! Surely that isn't what you meant to do. Fix that and you might see some improvement.
Think of the function call broken down a little, like this, to help you keep track of the types:
// takes a char, returns a bool, so....
bool specialChar( char in )
{ ... }
for( int i = 0; i < str.size(); i++ )
{
char aChar = str[i];
// ...pass in a char, and receive a bool!
bool isSpecial = specialChar(aChar);
if( isSpecial )
{
...
}
}
There's generally no harm in writing the code in a way that makes it clearer to you what's going on, when compiled and optimised it will all likely be the same.

C++ : read csv file with fgetc and separate words on semicolon ";"

I have to read in a csv file with 5 fields (int , char[], char[], char[], float) that looks like that :
2345678;Meier;Hans;12.10.1985;2.4;
1234567;Müller;Fritz;17.05.1990;1.9;
I have to put the fields in a struct, and then put the struct after one line is complete, into a array of the struct type ...
for the learning effect, we are only allowed to use LOW-LEVEL coding, and only use functions like fgetc, strcpy and no strings, only char[]...
Now I made my algorithm to read the textfile character by character, but I have problems separating them correctly, putting them together again and assigning them to the struct fields correctly. Here is my Code:
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
using namespace std;
int main(int argc, char **argv)
{
struct Stud{
long matrnr;
char vorname[30];
char name[30];
char datum[30];
float note;
};
const int MAX = 30;
Stud stud;
Stud mystud[30]; // <<-- Array of "Stud" type
//memset((void*)mystud,0,sizeof(mystud) * sizeof(Stud));
int wordCounter(0);
int i(0); //thats the charCounter or index
int studentCounter(0);
char wort[MAX];
//int matrnr;
//char vorname[MAX];
//char name[MAX];
//char datum[MAX];
//float note;
FILE * pFile;
int cnr(0);
pFile=fopen("studentendaten.txt","r");
if (pFile==nullptr)
{
perror ("Fehler beim öffnen der Datei");
}
else
{
while (cnr != EOF)
{
(cnr=fgetc(pFile)) ;
if ((char)cnr == '\n') {
mystud[studentCounter] = stud;
studentCounter++;
continue;
}
if ((char)cnr == ';') {
wort[i] = '\0';
switch (wordCounter % 5) {
case 0:
stud.matrnr = atol(wort);
break;
case 1:
strcpy(stud.name, wort);
break;
case 2:
strcpy(stud.vorname, wort);
break;
case 3:
strcpy(stud.datum,wort);
break;
case 4:
stud.note = atof(wort);
break;
}
wordCounter++;
i = 0;
continue;
}
if (wordCounter % 5 == 0 && (char)cnr != ';') {
wort[i] = (char)cnr;
i++;
//stud.matrnr = atol(wort);
}
if (wordCounter % 5 == 1) {
wort[i] = (char)cnr;
i++;
//strcpy(stud.name, wort);
}
if (wordCounter % 5 == 2) {
wort[i] = (char)cnr;
i++;
//strcpy(stud.vorname, wort);
}
if (wordCounter % 5 == 3) {
wort[i] = (char)cnr;
i++;
//strcpy(stud.datum,wort);
}
if (wordCounter % 5 == 4) {
wort[i] = (char)cnr;
i++;
//stud.note = atof(wort);
}
}
fclose (pFile);
}
for (int i(0) ; i <= studentCounter; i++) {
cout <<mystud[i].matrnr << " " << mystud[i].name << " " << mystud[i].vorname <<" "
<< mystud[i].datum <<" " << mystud[i].note << endl;
//printf("%5ld %5s %5s %5s %5f \n",mystud[i].matrnr,mystud[i].name,mystud[i].vorname,mystud[i].datum,mystud[i].note);
}
return 0;
}
I am not sure if it has to do with a wrong increment variables, or the fact that I don't put an '\0' at the end of my wort[] array..and therefore not recognizing the end of my array? And if so, how do I do it without knowing where the end exactly is... ? (I don't know the length of the words..)
EDIT: I updated my code again, the only thing that wonders me is that the LAST LINE IS NOT BEING CORRECTLY PARSED , its showing some rubbish, and I can't see the error in my code...
2345678;Meier;Hans;12.10.1985;2.4;
1234567;Müller;Fritz;17.05.1990;1.9;
8392019;Thomas;Kretschmer;28.3.1920;2.5;
3471144;Mensch;Arbeit;29.2.2013;4.5;
2039482;Test;Test;30.20.2031;2.0;
7584932;Bau;Maschine;02.02.2010;2.3;
2345678;Meier;Hans;12.10.1985;2.4;
1234567;Müller;Fritz;17.05.1990;1.9;
8392019;Thomas;Kretschmer;28.3.1920;2.5;
3471144;Mensch;Arbeit;29.2.2013;4.5;
2039482;Test;Test;30.20.2031;2.0;
7584932;Bau;Maschine;02.02.2010;2.3;
2345678;Meier;Hans;12.10.1985;2.4;
1234567;Müller;Fritz;17.05.1990;1.9;
8392019;Thomas;Kretschmer;28.3.1920;2.5;
3471144;Mensch;Arbeit;29.2.2013;4.5;
2039482;Test;Test;30.20.2031;2.0;
7584932;Bau;Maschine;02.02.2010;2.3;
2345678;Meier;Hans;12.10.1985;2.4;
1234567;Müller;Fritz;17.05.1990;1.9;
8392019;Thomas;Kretschmer;28.3.1920;2.5;
3471144;Mensch;Arbeit;29.2.2013;4.5;
2039482;Test;Test;30.20.2031;2.0;
7584932;Bau;Maschine;02.02.2010;2.3;
Suggestion: use a case structure for the parsing, and make yourself a "copyToSemicolon" function: then you can write things like
sIndexCount = 0;
char temp[50];
while((cnr=fgetc(pFile)) != EOF) {
offset = 0;
for(var = 0; var < 5; var++ {
switch(var) {
case 0:
offset = copyToSemicolon(temp, cnr, offset) + 1;
stud.matrnr = atoi(temp);
break;
case 1:
offset = copyToSemicolon(mystud[sIndexCount].vorname, cnr, offset) + 1;
break;
... etc
}
}
sIndexCount++;
if(sIndexCount == 50) break; // in case the input file is longer than our structure
}
And you need a function copyToSemicolon that takes two char* pointers as inputs, and that copies characters from the second string (starting at offset) until it reaches either a semicolon or the end of line - and that returns the offset it reached (last character read).
int copyToSemicolon(char* dest, char* source, int offset) {
while(source[offset] != ';' && source[offset] != '\n') {
*dest = source[offset++];
dest++;
}
return offset;
}
EDIT strtok method:
sIndexCount = 0;
char temp[50];
while((cnr=fgetc(pFile)) != EOF) {
offset = 0;
temp = strtok(cnr, ';');
for(var = 0; var < 5; var++ {
switch(var) {
case 0:
stud.matrnr = atoi(temp);
break;
case 1:
strcpy(mystud[sIndexCount].vorname, strtok(NULL, ';'));
break;
... etc
case 4:
mystud[sIndexCount].note = atof(strtok(NULL, '\n'));
}
}
sIndexCount++;
if(sIndexCount == 50) break; // in case the input file is longer than our structure
}
One issue that I am seeing is that your code copies or parses one character at a time, such that when you're reading 2345678;Meier;Hans;12.10.1985;2.4; you first set stud.matrnr to 2, then 23, then 234, then 2345, then 23456, then 234567, then 2345678. Similarly, for stud.name, you first set it to M, then the Me, then to Mei, etc. I propose to you to think of things in a different way. I'll give you some pseudocode:
while (!eof) {
get character from file
if (character isn't ';' and isn't '\n') {
copy character into buffer (increment buffer index)
} else if (character is ';') {
it's the end of a word. Put it in its place - turn it to an int, copy it, whatever
reset the buffer
} else if (character is '\n') {
it's the end of the last word, and the end of the line. Handle the last word
reset the buffer
copy the structure
}
}
This should make life a lot easier on you. You're not changing your data nearly as much, and if you need to debug, you can focus on each part on its own.
Generally, in programming, the first step is making sure you can say in your native speaking language what you want to do, then it's easier to translate it to code. You're close with you implementation, and you can make it work. Just be sure you can explain what should be happening when you see ';' or '\n'.
Since you have tagged this as C++, you should consider using std::getline for reading the line from the file, the use std::getline(file, text_before_semicolon, ';') for parsing the fields.
You could also use std::istringstream for converting the textual representation in the text line to internal numeric format.

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;
}