Pig Latin Program

I had an assignment to create a Pig Latin translator in my Intro to Programming Class ( C++ ) and I have created the code below, but when ran with the sample sentences given it doesn't read "y" as it should. I can't figure out where I am going wrong.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
 #include <iostream>
#include <fstream>
#include <string>
#include <cctype>

using namespace std;

const string UC_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string LC_LETTERS = "abcdefghijklmnopqrstuvwxyz";
const string LETTERS = UC_LETTERS + LC_LETTERS;
const string VOWELS = "AEIOUaeiou";

/**
   Determine if a given character is a vowel or not.

   @param c  the character to check
   @param y_is_vowel  true if 'y' is considered a vowel, false otherwise
   @return  true if c is a vowel, false if not
 */
bool is_vowel(char c, bool y_is_vowel)
{
   int v_index;
    cerr << "Step1" << endl;
   if (y_is_vowel)
   {
       cerr << "Wrong1" << endl;
       v_index = (VOWELS + "y").find(c);
   }
   else
   cerr << "Step2" << endl;
   {
       cerr << "Wrong2" << endl;
       v_index = VOWELS.find(c); 
   }
    cerr << "Wrong3" << endl;
   return (v_index != string::npos);
}

/**
   Find first vowel in a string, starting at a given index
   (Y's are considered to be vowels here).

   @param s  the string to search
   @param start  the index at which to start looking
   @return  the index of the first vowel at position start or
            later, -1 if there are no vowels
 */
int first_vowel_pos(string s, int start)
{
   for (int i = start; i < s.length(); i++)
   {
       cerr << "Test1" << endl;
      if (is_vowel(s[i], true)) 
      {
          cerr << "Test2" << endl;
          return i;
      }
   }
   return -1;
}

/**
   Translate a single word into Pig Latin.

   @param w  the word to be translated
   @return  the Pig Latin equivalent of w
 */
string translate_word(string w)
{
   if (is_vowel(w[0], false))
   { 
       return w + "hay";
   }
   else if (toupper(w[0]) == 'q' or tolower(w[1]) == 'u')
   {
      return w.substr(2) + w.substr(0, 2) + "ay";
   }
   else
   {
      int vpos = first_vowel_pos(w, 0);
      return w.substr(vpos) + w.substr(0, vpos) + "ay";
   }
}

/**
   Translate the words in a given line into Pig Latin.

   @param line  the line to be translated
   @return  the Pig Latin equivalent of line
 */








string translate_line(string line)
{
   string result = "";
   int word_end = 0;

   // find start of first word
   int word_start = line.find_first_of(LETTERS);

   // continue as long as there are words to process
   while (word_start != string::npos)
   {
      // pass along non-letters before word

      result = result + line.substr(word_end, word_start - word_end);

      // extract and process word

      word_end = line.find_first_not_of(LETTERS, word_start);

      if (line[word_end] =='\'' and isalpha(line[word_end]))
      {  // consider apostrophe in a contraction part of the word
         word_end = line.find_first_not_of(LETTERS, word_end + 1); 
      }

      if (word_end == string::npos)
      {
          word_end = line.length();
      }

      string word = line.substr(word_start, word_end - word_start);

      result = result + translate_word(word);

      // find start of next word
      word_start = line.find_first_of(LETTERS, word_end);
   }

   // pass along non-letters after last word
   result = result + line.substr(word_end);

   return result;
}











/**
   Translate an input stream into Pig Latin; output goes to specified
   output stream

   @param in  the input stream to be translated
   @param out  the translated output stream
 */
void translate_stream(istream& in, ostream& out)
{
   string line;
   while (getline(in, line))
   {
      out << translate_line(line) << endl;
   }
}

int main(int argc, char* argv[])
{
   if (argc == 1)          // no filenames on command line
   {
      translate_stream(cin, cout);
   }
   else
   {
      for (int i = 1; i < argc; i++)
      {
         string arg = argv[i];
         ifstream infile;
         infile.open(arg);
         if (infile.fail())
         {
            cout << "Unable to open input file:  " << argv[i] << endl;
         }
         else
         {
            ofstream outfile;
            outfile.open(arg + ".pig");
            if (outfile.fail())
            {
               cout << "Unable to open output file:  " << arg + ".pig" << endl;
               infile.close();
            }
            else
            {
               translate_stream(infile, outfile);
               infile.close();
               outfile.close();
            }
         }
      }
   }
}

Ouyay owknay erethay existyay anslatorstray eadyray otay useyay ?
esyay

but this was an assignment I was given, so that's what I did lol
In the whole, you got it, but your code is very complicated.

it doesn't read "y"

Firstly, you should tell us which rules you’re complying with, since it doesn’t seem you need to manage special cases like ‘y’ or apostrophe (as you do).:
https://en.wikipedia.org/wiki/Pig_Latin#Rules

Anyway, your is_vowel() function can be simplified:
- if y_is_vowel is true
is ‘c’ an y or an Y ?
If so, return true.

- if y_is_vowel is false or ‘c’ is neither y nor Y, return if the result of searching ‘c’ inside VOWELS is std::string::npos or not.

- - -

Let’s have a look at your main() function.
The logic is
- argc == 1 ? Ask user for input, then exit.
- argc == 2 ? Wrong: there’s the input file, but not the output file (or you can decide to read the sentence and to output it to std::cout) - then exit.
- argc > 2 ? Ok.

Once you have performed the above check, start opening the files. Do not open them inside the for loop. As a matter of fact, you don’t need a loop at all.

- - -
To split a std::string into tokens... Please, take it easy :-)
Just initialize a std::istringstream from the ‘line’ and then output (>>) into another std::string, untill it is empty.

There are other issues, but let’s start from here.
Happy coding!
Thank you!! I will get to fixing them, again thanks for the help
Topic archived. No new replies allowed.