Convert to Pig Latin - c++

Need some help with converting string to PigLatin. Write a program that inputs two string variables, first and last, each of which the user should enter with his or her name. First, convert both strings to all uppercase. Your program should then create a new string that contains the full name in pig latin.
Here is my main func:
char* first = new char[MAX];
char* last = new char[MAX];
char* full = new char[MAX*2];
cout << "Enter first name: ";
cin.getline(first, MAX, '\n');
cout << "Enter last name: ";
cin.getline(last, MAX, '\n');
for(int i = 0; first[i]; i++)
{
first[i] = toupper(first[i]);
}
for(int i = 0; last[i]; i++)
{
last[i] = toupper(last[i]);
}
transformPigLatin(first);
transformPigLatin(last);
int offset = 0;
int i;
for (i=0; i<MAX && first[i]!=0; i++)
full[offset++]=first[i];
full[offset++]=' ';
for (i=0; i<MAX && last[i]!=0; i++)
full[offset++]=last[i];
transformPigLatin(full);
cout << full << endl;
And piglatin func (need help only with this function):
char* transformPigLatin(char* word)
{
int length = strlen(word);
char ch;
for (int i = 0; i < length; i++){
if((length > 1) && (ch == 'a' || ch == 'A' ||ch =='e'||ch =='E'||ch =='i'||ch == 'I'||ch =='o'||ch =='O'||ch =='u'||ch =='U'))
{
strcat(word, "WAY");
}
else
{
strcat(word, "AY");
}
return word;
}
}
These are two things I can't figure out how to do with c-string:
1)If the first letter is a consonant, move it to the end and add “ay” to the end.
2)If the first letter is a vowel, add “way” to the end.
Any tips will be appreciated. Thanks

You are coding in C++, so you should use C++ strings rather than C strings. Things are much easier with C++ strings. The std::string class has many methods for manipulating the string content, including erase() and append().
Try this:
#include <string>
#include <algorithm>
std::string first;
std::string last;
std::string full;
std::cout << "Enter first name: ";
std::getline(std::cin, first);
std::cout << "Enter last name: ";
std::getline(std::cin, last);
std::transform(first.begin(), first.end(), first.begin(), ::toupper);
std::transform(last.begin(), last.end(), last.begin(), ::toupper);
transformPigLatin(first);
transformPigLatin(last);
full = first + " " + last;
std::cout << full << std::endl;
void transformPigLatin(std::string &word)
{
if (word.empty()) return;
char ch = word[0];
if ((ch < 'A') || (ch > 'Z')) return;
if (std::string("AEIOU").find(ch) != std::string::npos)
{
word += "WAY";
}
else
{
if (word.length() > 1)
{
word.erase(0, 1);
word.append(&ch, 1);
}
word += "AY";
}
}
Update: if you must stick with C strings only, then try something more like this:
int getLine(char *prompt, char *word, int maxlen)
{
if (prompt != NULL)
{
printf("%s", prompt);
fflush(stdout);
}
if (fgets(word, maxlen, stdin) == NULL)
{
*word = '\0';
return 0;
}
int length = strlen(word);
if (word[length-1] == '\n')
{
word[length-1] = '\0';
--length;
}
else
{
int ch;
while (((ch = getchar()) != '\n') && (ch != EOF));
}
return length;
}
char* first = new char[MAX];
char* last = new char[MAX];
char* full = new char[(MAX*2)+1];
getLine("Enter first name: ", first, MAX);
getLine("Enter last name: ", last, MAX);
for(int i = 0; first[i]; i++)
{
first[i] = toupper(first[i]);
}
for(int i = 0; last[i]; i++)
{
last[i] = toupper(last[i]);
}
transformPigLatin(first);
transformPigLatin(last);
strcpy(full, first);
strcat(full, " ");
strcat(full, last);
printf("%s\n", full);
void transformPigLatin(char* word)
{
int length = strlen(word);
if (length == 0) return;
char ch = word[0];
if ((ch < 'A') || (ch > 'Z')) return;
if (strchr("AEIOU", ch) != NULL)
{
if ((length+3) >= MAX) return;
strcat(word, "WAY");
}
else
{
if ((length+2) >= MAX) return;
if (length > 1)
{
for (int i = 1; i < length; ++i)
word[i-1] = word[i];
word[length-1] = ch;
}
strcat(word, "AY");
}
}

Related

a+= b faster than a = a+b. The logic behind the two operations

I was working on a leetcode problem to reverse a string such that such that if Input is The boy is mad, the output should be mad is boy The. I solved it but the solution seemed poor as I was running through the string a lot of times. On submitting the code, the time taken to compute all the test cases was ~250ms, and I believed it as I knew this was the worst possible code. I looked up one of the answers and ran that code, it ran in like 4ms. I wrote the same code again, but this time I used a = a + b; instead of a += b;, and the test cases again took around 250ms. So, I want to know what is the difference between these two and why does it take a long time on one when compared to the other.
PS - In my original (poor) code, on changing a = a + b to a += b, the code ran in like 8ms.
Here are the codes:
1. slow code(runtime - ~250 ms)
string reverseWords(string s) {
if(s.length() == 0)
{
return s;
}
int itr = 0;
// Remove white spaces from front
while(s[itr] == ' ')
{
itr++;
}
s = s.substr(itr,s.length()-itr);
if(s.length() == 0)
{
return s;
}
// Remover white spaces from back
for(int i = s.length()-1; i>= 0 ;i--)
{
while(s[i] == ' ')
{
s = s.substr(0,i);
i--;
//cout << s << endl;
}
break;
}
if(s.length() == 0)
{
return s;
}
cout << s << endl;
// Remove more than one space in the middle
for(int i = 0;i<s.length()-1;i++)
{
if(s[i] == ' ' && s[i+1] == ' ')
{
string temp;
temp = s.substr(0,i);
s = s.substr(i+1,s.length());
s = temp + s;
i--;
//cout << s <<endl;
}
}
string res = "";
reverse(s.begin(),s.end());
int start = 0;
for(int i = 0;i <s.length();i++)
{
start = i;
if(s[i] == ' ')
continue;
while(s[i] != ' ' && i < s.length())
{
i++;
// cout << i << " ";
}
// cout << endl;
string temp = s.substr(start,i-start);
reverse(temp.begin(),temp.end());
if(i != s.length())
res = res + temp + " ";
else
res = res + temp;
//cout << temp << endl;
}
return res;
}
Fast code(4ms)
string reverseWords(string s)
{
stack<string> elements;
std::istringstream stream(s);
std::string word;
while (stream >> word)
{
elements.push(word);
}
string strReturn("");
int stackSize = elements.size();
int i = 0;
while( !elements.empty())
{
i++;
strReturn += elements.top();
elements.pop();
if( i != stackSize)
{
strReturn += " ";
}
}
return strReturn;
}
Re written Fast code(250ms)
string reverseWords(string s) {
// Check the first available Accepted solution to see the shitiest solution for the code
stack<string> availableWords;
istringstream stream(s);
string word;
while(stream >> word)
{
availableWords.push(word);
}
int len = availableWords.size();
string res = "";
int i = 0;
while(!availableWords.empty())
{
res += availableWords.top();
availableWords.pop();
i++;
if(i != len)
{
res += " ";
}
}
return res;
}

Find character in a string

I cant get the char search to work. The substring function is working but the char search won't provide the right location of the char it is looking for
#include<iostream>
#include <string>
using namespace std;
int charsearch(string searchInto, char ch, int start = 0)
{
int x = 0;
long n = searchInto.length();
for (int i = 1; i < n; i++)
{
cout << ch;
if (searchInto[i] == ch)
{
i = x;
}
else
i++;
}
cout<< x;
return x;
}
int substr(string src, string tosearch, int start = 0)
{
string searchInto = src;
long n = searchInto.size();
long m = tosearch.size();
int ans = -1;
for (int i = start; i < n; ++i)
{
int p = i;
int q = 0;
bool escape = false;
while (p < n && q < m) {
if (searchInto[p] == tosearch[q]) {
if (tosearch[q] == '/' && !escape) {
++q;
} else {
++p; ++q;
}
escape = false;
} else if (!escape && tosearch[q] == '*') {
++q;
while (q < m && p < n && searchInto[p] != tosearch[q]) ++p;
escape = false;
} else if (!escape && tosearch[q] == '?') {
++p; ++q;
escape = false;
} else if (tosearch[q] == '/' && !escape) {
escape = true;
++q;
} else break;
}
if (q == m) {
return i;
}
if (q == m - 1 && tosearch[q] == '*') {
if (q > 0 && tosearch[q - 1] == '/') continue;
else return i;
}
}
return ans;
}
int main()
{
string searchInto, tosearch;
cout<< "Enter string:";
getline(cin, searchInto);
cout << "Looking for :";
getline(cin, tosearch);
if (tosearch.length() < 2)
{
char ch = tosearch.at(0);
cout << "Found at: " <<charsearch(searchInto, ch) << endl;
cout << "Used Char" << endl;
}
else
cout << "Found at: " <<substr(searchInto, tosearch) << endl;
return 0;
}
To find a character in a string, you have two interfaces.
std::string::find will return the position of a character you find:
auto pos = yourStr.find('h');
char myChar = yourStr[pos];
If the character does not exist, then std::string::npos will be returned as the std::size_t returned for position.
stl algorithm std::find, in header algorithm returns an iterator:
auto it = std::find(yourStr.begin(), yourStr.end(), 'h');
char myChar = *it;
If the character does not exist, then it == yourStr.end().
There are some silly mistakes in your CharSearch method. First of all, You have to break the loop when you got your target character. And most importantly you are not assigning x when you are finding the target. Furthermore, there is extra increment of value i inside the loop. I have modified the function. Please check it below
int charsearch(string searchInto, char ch, int start = 0) {
int x = -1;
long n = searchInto.length();
for (int i = start; i < n; i++)
{
cout << ch;
if (searchInto[i] == ch)
{
x = i; // previously written as i = x which is wrong
break; // loop should break when you find the target
}
}
cout<< x;
return x;
}
Please note that,you can either also use find method of string or std::find of algorithm to search in string.
You need to make changes as per this code
int charsearch(string searchInto, char ch, int start = 0)
{
int x = -1; // : change, if return -1, means not found
long n = searchInto.length();
for (int i = start; i < n; i++) // : change
{
cout << ch;
if (searchInto[i] == ch)
{
x = i; // : change
break; // : change
}
}
cout<< x;
return x;
}
Note : This function will return 1st match.

Deleting Duplicate chars from a string

Hello I'm kind of new to coding and I am writing a code that deletes any duplicate characters on a string. Let's say the input string was ABBA, then the output should be "empty" since all of the duplicates were deleted. Another example would be if the input string was KKCCD, then the output should be "D" as the code would remove the K and C duplicates. The problem with my code is that when I type KKCCD, it returns KCD and it doesnt delete the duplicates entirely. Also if I we're to type "AA" the result comes back as "A" instead of "Empty". Any help in fixing my code will be much apreciated. Thanks.
include
#include <string.h>
using namespace std;
string deduplicate(string input){
int i;
int x;
int len= input.length();
string outputStr;
string strEmpty = "Empty";
if (input.length() == 1)
{return input;}
for(i = 0; i<len;i++){
for(x = i+1; x<len; x++){
if(input[i] == input[x]){
input.erase(x,1);
x--;}
}
len = input.length();
}
return outputStr = input;
if (input.length() == 0)
{return strEmpty;}
return outputStr = input;
}
int main()
{
string input;
cout << "Enter a string: " << endl;
cin >> input;
cout << deduplicate(input);
return 0;
}
Change your duplicate function to this
string deduplicate(string input){
int i;
int x;
int len= input.length();
string outputStr;
string strEmpty = "Empty";
if (input.length() == 1)
{return input;}
for(i = 0; i<len;i++){
for(x = i+1; x<input.length(); x++){ // This line
if(input[i] == input[x]){
input.erase(x,1);
input.erase(i,1); // and this line
x--;
}
}
len = input.length();
}
return outputStr = input;
if (input.length() == 0)
{return strEmpty;}
return outputStr = input;
}
You did delete the duplicate character but not original, so the second erase statement does it.
You are deleting the duplicate you find, but you never delete the original character. The most efficient way to achieve your goal is to use STL algorithms. You might want to check out this link: Remove all duplicate characters from a string (STL)
Generally speaking I do not think if that is a good idea to delete characters from a string you are iterating. It would be much better and cleaner to construct your output instead:
#include <string>
#include <iostream>
using namespace std;
string deduplicate(string input) {
string outputStr;
if (input.length() == 1) {
return input;
}
for ( int i = 0; i < input.length(); i++ ) {
// try to find character at the rest of the string
if ( input.find( input[i], i+1 ) == string::npos ) {
// try to find character in the front
if ( ( i > 0 ) && ( input.rfind( input[i], i-1 ) == string::npos ) ) {
outputStr += input[i];
}
}
}
return outputStr;
}
int main()
{
string input;
cout << "Enter a string: " << endl;
cin >> input;
cout << deduplicate(input) << endl;
return 0;
}
Here is a "brute force" implementation.
string deduplicate(string str)
{
size_t l = str.length();
bool bFound = false;
char character = 0;
for (int i = 0; i < l; i++)
{
character = str[i];
while (true)
{
size_t next = str.rfind(character);
if (next != std::string::npos)
{
if (bFound || (!bFound && next != i))
{
str.erase(next, 1);
bFound = true;
l--;
}
}
if (next == i)
{
if (bFound == true)
{
i--;
}
bFound = false;
break;
}
}
}
return str;
}

Splitting char array

I have a char **names array that basically stores names from a file.
This is my .txt file
Mike, Sam, Stuart
Andre, Williams, Phillips
Patels, Khan, Smith
Basically, I want to split and store the names before the , character.
For example, Mike, Sam, Stuart will become...
newName[0] = Mike
newName[1] = Sam
newName[2] = Stuart
I have something like this...
for (int i=0; i<3; i++)
{
for (int j=60, j>0; j--)
{
if(names[i][j] == ',')
{
cout << j << endl; //THIS PRINTS OUT THE POSITION. HOW CAN I STORE THE POSITION AND DO SOMETHING?
}
}
}
I would appreciate it if someone could help me with my code, it is in the right direction. I don't want to use any vectors classes
I have attempted to store marks of these students, however I want to add it to a double *marks[2] array.
This is my .txt file...
69.9, 56.5
29.8, 20.0
35.6, 45.0
This is my code...
char **values;
char * pch;
pch = strtok (values[i], " ,");
while (pch != NULL)
{
sscanf(pch, "%f, %f", &marks[i][0], &marks[i][1]);
pch = strtok (NULL, " ,");
}
I am getting random values such as 1.28277e-307 and 1.96471e+257
look up the strtok command it will be very helpful to you.
This code looks for hyphen characters and prints stuff... change it to commas
#include <string.h>
#include <stdio.h>
int main()
{
const char str[80] = "This is - www.tutorialspoint.com - website";
const char s[2] = "-";
char * newName[100]; /* at most 100 names */
int iCurName = 0;
char *token;
/* get the first token */
token = strtok(str, s);
/* walk through other tokens */
while( token != NULL )
{
printf( " %s\n", token );
newName[iCurName] = malloc (char *) (strlen(token) + 1);
strcpy(newName[iCurName],token);
iCurrName ++;
token = strtok(NULL, s);
}
return(0);
}
Use function strtok() to split input line into tokens; use strcpy_s() to copy each token into name buffer.
Note 1: The strtok() function replaces each separator with '\0' character, so the line variable cannot be declared with const. If your input buffer must be constant, for example if you want to use the whole line for something else, make a copy of it before calling strtok() function.
Note 2: You might want to trim space in addition to splitting your input line.
#define MAX_LINE_LENGTH 80
#define MAX_NAME_LENGTH 20
#define MAX_NAMES_PER_LINE 3
const char constInput = "Mike, Sam, Stewart";
char line[MAX_LINE_LENGTH];
strcpy_s(line, MAX_LINE_LENGTH, constInput);
char *separator = ",";
char newName[MAX_NAMES_PER_LINE][MAX_NAME_LENGTH];
int i = 0;
char *token = strtok(line, separator);
while ((i < MAX_NAMES_PER_LINE) && ((token = strtok(NULL, separator)) != NULL))
{
strcpy_s(newName[i++], MAX_NAME_LENGTH, token);
}
char newName[3][60];
for (int i=0; i<3; i++){
int r=0, c=0;
for (int j=0; j<60; j++){
if(names[i][j] == ',' || names[i][j] == '\0'){
newName[r++][c] = '\0';
c = 0;
if(names[i][j] == '\0'){
cout << newName[0] << '\n'
<< newName[1] << '\n'
<< newName[2] << '\n' << endl;
break;
}
while(names[i][++j] == ' ')
;
--j;
} else {
newName[r][c++] = names[i][j];
}
}
}
#include <fstream>
#include <iostream>
using namespace std;
int main() {
ifstream inf("data.txt");
double marks[2];
char ch;
while(inf.good()){
inf >> marks[0] >> ch >> marks[1];
cout << "mark1:" << marks[0] << endl;
cout << "mark2:" << marks[1] << endl;
}
}
I don't know if this function works fast enough, but here it is:
char** split_quotes(char *input, char separator = ' ', bool keep_quotes = false)
{
if (&input && input)
{
size_t length = strlen(input);
char **chunks = new char*[length];
bool inQuotes = false;
size_t count = 0, from = 0;
for (size_t i = 0; i < length; i++)
{
if (input[i] == '"')
{
inQuotes = !inQuotes;
}
else if (input[i] == separator && !inQuotes)
{
size_t strlen = i - from;
if (strlen > 0)
{
if (!keep_quotes && input[from] == '"' && input[i - 1] == '"')
{
from++; strlen -= 2;
}
chunks[count] = new char[strlen + 1]();
strncpy(chunks[count], &input[from], strlen);
count++;
}
from = i + 1;
}
}
if (from < length)
{
size_t strlen = length - from;
if (!keep_quotes && input[from] == L'"' && input[length - 1] == L'"')
{
from++; strlen -= 2;
}
chunks[count] = new char[strlen + 1]();
strncpy(chunks[count], &input[from], strlen);
count++;
}
// Save chunks to result array //
char **result = new char*[count + 1]();
memcpy(result, chunks, sizeof(char*) * count);
// free chunks //
delete[] chunks;
return result;
}
return NULL;
}
Usage:
wchar_t **name = split_quotes(L"Mike,Donald,\"My Angel\",Anna", L',');
if (name)
{
while (*name++)
{
std::wcout << "Person: " << *name << std::endl;
}
}

how to check whether 2 strings are rotations to each other ?

Given 2 strings, design a function that can check whether they are rotations to each other without making any changes on them ? The return value is boolean.
e.g ABCD, ABDC, they are not rotations. return false
ABCD, CDAB or DABC are rotations. return true.
My solution:
shift one of them to right or left one position and then compare them at each iteration.
If they are not equal at all iterations, return false. Otherwise, return true.
It is O(n). Are there other more efficient solutions ?
What if the contents of them cannot be changed ?
thanks
Concatenate the given string with the given string.
Search for the target string in the concatenated string.
Example:
Given = CDAB
After step 1, Concatenated = CDABCDAB
After step 2, Success CDABCDAB
^^^^
Rather than shifting one of them, it might be more efficient to use two index variables. Start one at 0 each time and the other at each of the possible positions (0 to N-1) and increment it mod N.
If you can't modify the strings, just take the first character of string1 and compare it to each character of string2. When you get a match, compare the second char of string1 to the next char of string2, and so on.
Pseudocode:
len = strlen(string1);
len2 = strlen(string2);
if( len != len2 )
printf("Nope.");
for( int i2=0; i2 < len; i2++ ) {
for( int i1=0; i1<len; i1++ ) {
if( string1[i1] != string2[(i2+i1)%len] )
break;
}
if( i1 == len ) {
print("Yup.");
break;
}
}
A simple one would be:
(s1+s1).find(s2) != string::npos && s1.size() == s2.size();
#include <iostream>
#include <cstring>
#include<string>
using namespace std;
void CompareString(string, string, int);
int ComputeStringLength(string str);
int main()
{
string str = ""; string str1 = ""; int len = 0, len1 = 0;
cout << "\nenter string ";
cin >> str;
cout << "\nenter string 2 to compare:- ";
cin >> str1;
len = ComputeStringLength(str);
len1 = ComputeStringLength(str1);
if (len == len1)
CompareString(str, str1, len);
else
cout << "rotation not possible";
getchar();
return 0;
}
int ComputeStringLength(string str)
{
int len = 0;
for (int i = 0; str[i] != '\0'; i++)
{
len++;
}
return len;
}
void CompareString(string str, string str1, int n)
{
int index = 0, flag = 0, curr_index = 0, count1 = 0, flagj = 0;
for (int i = 0; i<n; i++)
{
for (int j = flagj; j<n; j++)
{
if (str[i] == str1[j])
{
index = j;
flagj =j;
count1++;
flag++;
if (flag == 1)
{
curr_index = index;
}
break;
}
}
}
int temp = count1;
if (count1 != n)
{
if (curr_index>=0)
{
int k = 0;
for (int i = n - 1; i>n - curr_index - 1; i--)
{
if (str[i] == str1[k])
{
temp++;
k++;
}
}
}
if (temp == n)
{
cout << "\n\nstring is same after rotation";
}
else
{
cout << "\n\nstring is not same after rotation";
}
}
else
{
cout << "\n\nstring is same after rotation";
}
}
https://dsconceptuals.blogspot.in/2016/10/a-program-to-check-if-strings-are.html