This question already has answers here:
How do I iterate over the words of a string?
(84 answers)
Closed 9 years ago.
I am writing a pig latin converter that takes a string as a command line argument and converts each word in the sentence into pig latin. I am trying to break up the string into individual words by finding spaces, but the output I get with the below code... honestly makes no sense.
It works for the first word, but then doesn't convert any subsequent words. So "test this string" becomes "esttay this ay string ay."
At this point we haven't covered vectors, so the solution has to be relatively simple.
Any ideas?
#include <iostream>
#include <string>
using namespace std;
void convertSentence(string sentence);
string pigLatinWord(string input);
bool isVowel(string input);
int main(int argc, char* argv[]) {
if(argc != 2) {
cout << "USAGE: " << argv[0] << " \"[sentence]\"" << endl;
} else {
string sentence(argv[1]);
convertSentence(sentence);
}
return 0;
}
void convertSentence(string sentence) {
string word = "", remainder = sentence, pigLatin = "";
for(int i = sentence.find(" ",0); i != string::npos; i = sentence.find(" ",i)) {
word = sentence.substr(0,i);
pigLatin += pigLatinWord(word) + " ";
sentence = sentence.erase(0,i);
i++;
}
pigLatin += pigLatinWord(sentence);
cout << pigLatin << endl;
}
string pigLatinWord(string input) {
string word = "";
// If the first letter is a vowel, simply add "yay" to the end of it.
if (isVowel(input)) {
word = input + "yay";
//If the first letter is a consonant, add the first letter to the end,
//delete the first letter, then add "ay." - Credit to Tyler Sorrels
//CString/String solution post on Piazza. I had issues working with
//substrings, and this ended up being easier to read.
//But I did add a check for words that start with two consonants
//to cover all cases.
} else {
input += input.at(0);
input = input.erase(0,1);
word = input + "ay";
}
return word;
}
// Checks if the first letter of the word is a vowel.
// Returns true if yes, false if no.
bool isVowel(string input) {
return ((input[0] == 'a') || (input[0] == 'e') || (input[0] == 'i') || (input[0] == 'o') || (input[0] == 'a'));
}
Two errors:
for(int ...; ; i = sentence.find(" ",i)) { // next space find should start from 0.
//..
//..
sentence = sentence.erase(0,i);// you should delete the current space found also.
i++;
}
Change this to:
for(int ...; ; i = sentence.find(" ",0)) {
//..
//..
sentence = sentence.erase(0,i+1);
i++;
}
Output:
esttay histay tringsay
The code is confused because you are trying to skip the word you have already found and you are trying to remove the word you have already found from sentence. Do one or the other.
Can I recommend that you use the POSIX regular expression library or PCRE, which should make swapping the first and last letters of words simple.
A regex such as \b(\w)(\w+)(\w)\b could be replaced by swapping the first and last collection groups
Related
I need to write a sentence in Pig Latin form and I am almost done it successfuly except for 1 case and I almost give up
for example :
If my word starts at a\e\o\u\i the word will look like easy -> easyway , apple -> appleway
and if it doesnt start with a letter that I wrote above
it will look like that: box -> oxbay , king -> ingkay
I succeed with the bolded part but in the first part with a\e\o\u\i letter at the beginning , I dont know where to put the w before and need some help with it
This is my code , thanks in advance
#include <iostream>
//Since those are used in ALL function of program, it wont hurt to set it to global
//Else it is considered EVIL to declare global variables
const int maxLine = 100;
char phraseLine[maxLine] = { '\0' };
void pigLatinString();
using namespace std;
void main()
{
// Displayed heading of program
cout << "* You will be prompted to enter a string of *" << endl;
cout << "* words. The string will be converted into *" << endl;
cout << "* Pig Latin and the results displayed. *" << endl;
cout << "* Enter as many strings as you would like. *" << endl;
//prompt the user for a group of words or press enter to quit
cout << "Please enter a word or group of words. (Press enter to quit)\n";
cin.getline(phraseLine, 100, '\n');
cout << endl;
// This is the main loop. Continue executing until the user hits 'enter' to quit.
while (phraseLine[0] != '\0')
{
// Display the word (s) entered by the user
cout << "You entered the following: " << phraseLine << endl;
// Display the word (s) in Pig Latin
cout << "The same phrase in Pig latin is: ";
pigLatinString();
cout << endl;
//prompt the user for a group of words or press enter to quit
cout << "Please enter a word or group of words. (Press enter to quit)\n";
cin.getline(phraseLine, 100, '\n');
}
return;
}
void pigLatinString() //phraseLine is a cstring for the word, maxline is max length of line
{ //variable declarations
char tempConsonant[10];
tempConsonant[0] = '\0';
int numberOfConsonants = 0;
char previousCharacter = ' ';
char currentCharacter = ' ';
bool isInWord = 0;
// for loop checking each index to the end of whatever is typed in
for (int i = 0; i < maxLine; i++)
{
//checking for the end of the phraseline
if (phraseLine[i] == '\0')
{//checking to see if it's in the word
if (isInWord)
{//checking to see that there wasn't a space ahead of the word and then sending the cstring + ay to the console
if (previousCharacter != ' ')
cout << tempConsonant << "ay" << endl;
}
return;
}
// this covers the end of the word condition
if (isInWord)
{// covers the condition of index [i] being the space at the end of the word
if (phraseLine[i] == ' ')
{
// spits out pig latin word, gets you out of the word, flushes the temp consonants array and resets the # of consonants to 0
cout << tempConsonant << "ay";
isInWord = 0;
tempConsonant[0] = '\0';
numberOfConsonants = 0;
}
cout << phraseLine[i] ;
}
else
{//this covers for the first vowel that makes the switch
if (phraseLine[i] != ' ')
{// sets the c string to what is in the phraseline at the time and makes it capitalized
char currentCharacter = phraseLine[i];
currentCharacter = toupper(currentCharacter);
// this takes care of the condition that currentCharacter is not a vowel
if ((currentCharacter != 'A') && (currentCharacter != 'E') &&
(currentCharacter != 'I') && (currentCharacter != 'O') && (currentCharacter != 'U'))
//this sets the array to temporarily hold the consonants for display before the 'ay'
{//this sets the null operator at the end of the c string and looks for the next consonant
tempConsonant[numberOfConsonants] = phraseLine[i];
tempConsonant[numberOfConsonants + 1] = '\0';
numberOfConsonants++;
}
else
{// this sets the boolean isInWord to true and displays the phraseline
isInWord = 1;
cout << phraseLine[i];
}
}
else
{
cout << phraseLine[i] ;
}
}
previousCharacter = phraseLine[i];
}
return;
}
You have two conditions to consider. if your word starts with a vowel, just add "way" to the end of the word, else move the first letter and add "ay" to the end.
This is a task that can be made a lot simpler by using std::string instead of C-strings. This is because you are now no longer concerned with exceeding your length or losing the null character. It also allows easier access to the Standard Library algorithms.
#include <algorithm>
#include <iostream>
#include <string>
std::string make_pig_latin(const std::string& word) {
std::string vowels("aeiou");
std::string newWord(word);
if (newWord.find_first_not_of(vowels) == 0) {
// Word starts with a consanant
std::rotate(newWord.begin(), newWord.begin() + 1, newWord.end());
newWord += "ay";
} else {
newWord += "way";
}
return newWord;
}
int main() {
std::cout << make_pig_latin("apple") << '\n'
<< make_pig_latin("box") << '\n'
<< make_pig_latin("king") << '\n'
<< make_pig_latin("easy") << '\n';
}
The function above highlights how you can go about structuring your conversion. You just need to know if your word starts with a vowel or not, and take the appropriate action.
Output:
appleway
oxbay
ingkay
easyway
I did not get the impression that you have to care about words like 'phone'.
Looking through your code, you should try to do a better job at separating your concerns. Pig Latin is easier done one word at a time, but you have string splitting code and a lot of "not Pig Latin" code in your Pig Latin function. Your main can handle getting input. You should probably have a separate function to break the line up into individual words, using std::vector to hold the words would be best since it can grow on demand and doesn't have to know a specific capacity up front. You then iterate through your array of words and translate them individually. Depending on what your actual requirements are, it's possible that you don't even have to store the translated words, just print them directly to the screen.
Here's the same program, but now it can separate words. Note how the pig latin function doesn't have to change (much, I added upper-case vowels just because I didn't want to bothered converting words) in order for the added functionality to be added.
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>
std::string make_pig_latin(const std::string& word) {
std::string vowels("aeiouAEIOU");
std::string newWord(word);
if (newWord.find_first_not_of(vowels) == 0) {
// Word starts with a consanant
std::rotate(newWord.begin(), newWord.begin() + 1, newWord.end());
newWord += "ay";
} else {
newWord += "way";
}
return newWord;
}
int main() {
std::string phrase(
"A sentence where I say words like apple box easy king and ignore "
"punctuation");
std::istringstream sin(phrase);
std::vector<std::string> words(std::istream_iterator<std::string>(sin), {});
for (auto i : words) {
std::cout << make_pig_latin(i) << ' ';
}
}
Output:
Away entencesay hereway Iway aysay ordsway ikelay appleway oxbay easyway ingkay andway ignoreway unctuationpay
I want to remove 3 characters after a full stop (.) and would like to exclude the last full stop in my string as well as all full stops that end a sentence (defined as full stop + space (. )).
My code thus far removes all full stops + 3 chars:
string test = "I would .asdlike to.aed remove a.thell these inserts.";
string target = ".";
int found=-1;
do{
found = test.find(target,found+1);
if(found!=-1){
test=test.substr(0,found)+test.substr(found+4);
}
}
while(found != -1);
cout << test << endl;
Unfortunately, I keep on getting an error with the final full stop in a string and it removes 3 chars when a string includes more than one sentence separated by a full stop (identified as (. )).
Any Thoughts?
The string class has a useful erase function for you, which I demonstrate here:
std::string test = "I would .asdlike to.aed remove a.thell these inserts. And also keep.asd mult.weriple sentences.";
char target = '.';
std::string::iterator stringIter;
for(stringIter = test.begin(); stringIter != test.end(); stringIter++) {
if (*stringIter == target && stringIter < test.end() - 3 && *(stringIter+1) != ' ') {
test.erase(stringIter, stringIter+4);
}
}
std::cout << test << std::endl;
Really simple and put together relatively quickly.
And the output is:
I would like to remove all these inserts. And also keep multiple sentences.
I'd do like this:
#include <string>
#include <iostream>
void solve(std::string &str, char target) {
std::string s;
for (int i = 0; i < str.size();) {
if (str[i] == target) {
if (i + 4 >= str.size() and str[i] == target) s.push_back(str[i]);
i += 4;
} else {
s.push_back(str[i]);
i++;
}
}
str = s;
}
int main() {
std::string test = "I would .asdlike to.aed remove a.thell these inserts.";
solve(test, '.');
std::cout << test << std::endl;
return 0;
}
Outut:
I would like to remove all these inserts.
I'm new to c++ and coding in general and I ran into a bit of an issue in one of my assignments. I'm just looking for some input and hopefully an explanation on why my code isn't working.
I'm trying to get input from a user and use a cin.get() function to count all the characters in that string. I do this because I want to determine the letters in each word of the string. Now my issues are I can't get it to print the result correctly.
My question is: Why can't I get a result when I try to determine if my variable chr is a '\n' character? chr is the variable that hold the value of the current character being read by the cin.get() function) is a '\n'.
I want to be able to update the parameters (word1, word2.....) of my function countWordsByLegth() when the current value of chr is '\n' or in other words the end of the string.
The following code, for example, won't run and it's the only way I know how to update my parameter for a string that contains no spaces (one word strings):
if (counter == 5 && chr == '\n')
{
++word5;
counter =0;
}
Here's my code for reference. The function isWhitespace() just determines if the character is one of the following '\n' , '\r' , '\t'):
while (cin.get(chr) && chr != '\n')
{
counter++;
if (isWhitespace(chr))
{
--counter;
//test = true;
}
if (counter == 5 && chr == '\n')
{
++word5;
counter =0;
}
if (counter == 4 && chr =='\n')
{
++word4;
counter =0;
}
if (counter == 3 && chr =='\n')
{
++word3;
counter =0;
}
if (counter == 2 && chr == '\n')
{
++word2;
counter =0;
}
if (counter ==1 && chr == '\n')
{
++word1;
counter =0;
}
cout << counter << endl; // Test code {delete later}
}
cout << "This is the total of word5: " << word5 << endl;
}
You could use std::string.length() to get the amount of chars in a string.
The length() function returns the number of chars in the string.
#include <iostream>
#include <string>
int main()
{
std::string s;
s = "test";
std::cout << "The string has " << s.length() << " letters!";
}
http://www.cplusplus.com/reference/string/string/ here you can read about the different functions that you can use with strings.
What it's supposed to do
My piglatin program is supposed to take a phrase from user input and output it into pig latin. Basically it would turn a word such as "hello" into "ellohay".
My problem
When I input hello my man the output is ellohay y man an may and when I just input hello my the output is ellohay y may. As you can see, after it translates the first word successfully, it struggles on the second word. It places a space after the y and mayI cannot figure out for the life of me why this keeps happening. The output is even stranger when I input more than two words, as shown above. What I want to happen is for it to output ellohay ymay anmay when I input hello my man. Code is below. Thanks!
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
void phrase_Parser(string); // Goes through phrase and looks for ' ' to then pass to pigLatin_Translator()
void pigLatin_Translator(string);
int main()
{
string phrase; //used for user word or phrase to be translated to piglatin
cout << "Enter any word: ";
getline(cin, phrase);
phrase_Parser(phrase);
return 0;
}
void phrase_Parser(string phrase) {
int startCount = 0;
for (int i = 0; i < phrase.length(); i++) {
if (phrase[i] == ' ') {
string word = phrase.substr(startCount, i);
startCount = (i + 1); // decides where to start the word next time it is ran through
pigLatin_Translator(word); // runs word through translator
}
}
}
void pigLatin_Translator(string word) {
string partOne;
string partTwo;
for (int x = 0; x < word.length(); x++) {
if (word[0] == 'q' && word[1] == 'u') {
cout << word.substr(2, word.length()) << word.substr(0, 2) << "ay ";
break;
}
else if ((word[x] == 'a') || (word[x] == 'e') || (word[x] == 'i') || (word[x] == 'o') || (word[x] == 'u') || (word[x] == 'y')) {
partOne = word.substr(x, word.length()); //from first vowel to end of word
partTwo = word.substr(0, x); // from first letter to first vowel, not including the vowel
cout << partOne << partTwo << "ay "; // adding "ay" to the end of the word
break;
}
}
}
Your problem is in the line string word = phrase.substr(startCount, i);
You are using substr incorrectly. The second argument to substr is the length of the substring you wish to extract. Replace i with i-startCount and you should be good to go.
Alternatively, search for a nicer way to split strings. There are a number of options that are much easier than doing it manually.
This snippet of code include the string I want to display and a helper method that's sole function is to display the string, entering the text on a new line when it finds a colon. However, it is only doing that for the last colon, not the other colons
string list = ":hello:chris:";
void displayEntry(){char *colon = ":";
for (int i = 0; i<list.length(); i++) {
char *letter = &list.at(i);
if (strcmp(letter, colon) != 0) {
cout << list[i];
continue;
}
cout << "\n";
}
cout << "\n";
}
It's because strcmp is not used for comparing single characters, it compares a whole string up until it finds a NUL character.
You don't actually need char* for any of this, just use char and ==.
if (list.at(i) != ':')