Reputation: 3218
I'm writing a "pig latin" program; read input from the users (first name and last name,) make the input lowercase and change the name depending upon what was in the name. If the first letter (of both the first and last name) was a vowel, we're supposed to add "way" to the end of it.
If the first letter was a consonant, we were to take the first letter, move it to the end of the string and add "ay" to the end of it.
My code has been giving me errors when trying to add text to the end of the string. It says it can't convert the string to a character, and I'm not exactly sure what that means. It also says I can't use the output operand << for strings, even though I've used it before.
The errors occur with "strcpy" and the final code where I output the names.
37: error: cannot convert
'std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >'
to'char*'
for argument'1'
to'char* strcpy(char*, const char*)'
47: error: cannot convert
'std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >'
to'char*'
for argument'1'
to'char* strcpy(char*, const char*)'
54: error: no match for
'operator<<'
in'std::cout << first'
I just need some help fixing the errors and seeing where I went wrong. The full code is included.
#include <iostream>
#include <vector>
#include <cstring>
#include <string>
using namespace std;
int main()
{
int q, s;
char shea[] = "way";
char gavin_stop_looking_at_ponies[] = "ay";
vector <string> first;
vector <string> last;
cout << "Please enter your first name." << endl;
for (int i = 0; i < first.size(); i++)
{
getline (cin, first[i]);
string nfirst = first[i];
while (nfirst[q])
{
nfirst[q] = tolower(nfirst[q]);
}
first[i] = nfirst;
}
cout << "Please enter your last name." << endl;
for (int j = 0; j < last.size(); j++)
{
getline (cin, last[j]);
string nlast = last[j];
while (nlast[s])
{
nlast[s] = tolower(nlast[s]);
}
last[j] = nlast;
}
if ( (first[0] == "a") ||( first [0] == "e") || (first [0] == "i") || (first [0] == "o") || (first [0] == "u"))
{
strcpy (first, "way");
}
else
{
first[first.size()] = first[0] + "ay";
}
if ( (last[0] == "a") ||( last [0] == "e") || (last [0] == "i") || (last [0] == "o") || (last [0] == "u"))
{
strcpy (last, "way");
}
else
{
last[last.size()] = last[0] + "ay";
}
cout << first << last << endl;
return 0;
}
Upvotes: 0
Views: 4835
Reputation: 1122
I took a quick stab at writing the code for this just to play with it a bit. Here's what I came up with -- I think it's pretty well simplified, clean, and easy to understand:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* simple pig-latin program ... converts a given "first name" and "last name"*/
/* from the user to pig latin translations. Obviously, the so-called names */
/* are really just any 2 random words, but that's the theme anyway. */
/* */
/* */
/* */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
string xlat_to_piglatin(const string source)
{
string result;
//
// translation: if word begins with a vowel, simply append "way" to
// it. Otherwise, move the initial consonant from the beginning to
// the end, and append "ay" to it.
//
if (source.find_first_of("aeiou") == 0) {
result = source;
result.append("way");
} else {
result = source.substr(1, source.size());
result.append(source.substr(0, 1));
result.append("ay");
}
return result;
}
int main()
{
string first;
string last;
//
// get the first and last names from the user on standard in ...
//
cout << "Please enter your first name:" << endl;
cin >> first;
cout << "Please enter your last name:" << endl;
cin >> last;
//
// convert strings to lower case ...
//
transform(first.begin(), first.end(), first.begin(), ptr_fun<int, int>(tolower));
transform(last.begin(), last.end(), last.begin(), ptr_fun<int, int>(tolower));
cout << xlat_to_piglatin(first) << " " << xlat_to_piglatin(last) << endl;
return 0;
}
Upvotes: 0
Reputation: 1122
I agree with some of the previous responders, but I don't want to get into a detailed code review because it would be large and might miss the point. I think the problem you're having is a symptom of a underlying fundamental misunderstanding of the correct use of the C++ standard library. Mostly, you're mixing standard C library string implementations with the C++ "string" object. In C, there is a collection of functions that take character pointers and operate on them as strings while in C++ there is a string object that encapsulates a string of characters and provides a collection of operations on it. In some cases, the C++ string can be used where a C char * would normally exist, but in most cases it cannot.
Even in the C++ STL (standard template library) you're getting things mixed up a bit. Based on your code, it looks like you want to retreive the user's first name and last name i.e. 2 separate strings. However, you are declaring 2 collections (vectors in this case) of strings rather than just two individual strings themselves. Many other problems in your program follow from that.
I think you might like the information found here: http://en.cppreference.com/w/
Upvotes: 0
Reputation: 54971
I have annotated your code with explanations of some problems and suggestions for solutions. If there’s anything you don’t understand, comment and I’ll try to clarify.
#include <iostream>
// You don't need 'vector' for this.
#include <vector>
// You won’t often need the C string header in C++.
#include <cstring>
#include <string>
using namespace std;
int main()
{
// These variables are unused.
int q, s;
char shea[] = "way";
char gavin_stop_looking_at_ponies[] = "ay";
// 'first' and 'last' are both names, not collections
// of names.
string first;
string last;
vector <string> first;
vector <string> last;
// 'endl' is unnecessary here; it outputs a newline and
// flushes the stream, but standard output is usually
// line-buffered, meaning that newline flushes the
// stream regardless.
cout << "Please enter your first name.\n"
cout << "Please enter your first name." << endl;
// If you just want to get one name, 'getline' is perfect.
getline(cin, first);
// This loop would run 0 times because 'first' is an
// empty vector.
for (int i = 0; i < first.size(); i++)
{
getline (cin, first[i]);
string nfirst = first[i];
while (nfirst[q])
{
nfirst[q] = tolower(nfirst[q]);
}
first[i] = nfirst;
}
// To make a string lowercase, use 'tolower' on each character.
// Here's one way to do it:
for (string::size_type i = 0; i < first.size(); ++i)
first[i] = tolower(first[i]);
// Here's another, with C++11 enabled:
for (auto& c : first)
c = tolower(c);
cout << "Please enter your last name.\n";
cout << "Please enter your last name." << endl;
// Same thing.
getline(cin, last);
for (int j = 0; j < last.size(); j++)
{
getline (cin, last[j]);
string nlast = last[j];
while (nlast[s])
{
nlast[s] = tolower(nlast[s]);
}
last[j] = nlast;
}
// Now 'first' is a string, and 'first[0]' is a 'char'.
// "a" is a string literal; 'a' is a character literal.
// You can compare each character individually:
if (first[0] == 'a' || first[0] == 'e' || first[0] == 'i' || first[0] == 'o' || first[0] == 'u')
// Or you can say "if the character was found in this
// set of vowels".
if (string("aeiou").find(first[0]) != string::npos)
if ( (first[0] == "a") ||( first [0] == "e") || (first [0] == "i") || (first [0] == "o") || (first [0] == "u"))
{
// This would try to copy "way" into 'first':
// formerly a vector of string objects, now just a
// string object. 'strcpy' wants a character buffer,
// and will overwrite characters in that buffer—
// probably not what you want:
//
// "aaron" => "wayon"
//
strcpy (first, "way");
// Instead, just append "way":
first += "way";
}
else
{
// This says "take the first first character of the
// string, add the value of that character to a
// pointer to a buffer containing "ay", then try to
// copy the resulting pointer past the end of the
// string. Again, not quite what you intended!
first[first.size()] = first[0] + "ay";
// Think of it instead like this: take everything
// after the first character, add a string consisting
// of the first character back onto the end, then add
// "ay" after that.
first = first.substr(1) + string(1, first[0]) + "ay";
}
// Duplicated code! You could move the above logic into
// a function to avoid this duplication. Then you only
// have to work on it in one place. :)
if ( (last[0] == "a") ||( last [0] == "e") || (last [0] == "i") || (last [0] == "o") || (last [0] == "u"))
{
strcpy (last, "way");
}
else
{
last[last.size()] = last[0] + "ay";
}
// I need a space between my first and last names!
cout << first << ' ' << last << '\n';
cout << first << last << endl;
return 0;
}
Upvotes: 5
Reputation: 275370
first
is a vector<string>
, not a string
. vector
doesn't support <<
with cout
. If you want to output each std::string
in the std::vector
, try iterating over the std::vector
and outputting them one character at a time.
Similarly, first
is a vector<string>
, which cannot be implicitly converted to a char*
. strcpy
operates on raw blocks of char
data, which first
is far removed from. strcpy
is for C-level operations on string buffers (and even then, is dangerous to use).
first[first.size()] = first[0] + "ay";
is undefined behavior, as you are accessing one-past-the-last-element of first
, which is invalid memory. If you want to push something into the back of first
, try first.push_back( first[0] + "ay" );
.
Quite probably you are confused as to the difference between std::string
, a char
and a char*
. These are completely different things. std::string
is a managed buffer of char
. char
is a single 8 bit value, often used to store literals like 'a'
(which is of type char
). char*
is a pointer to a single char
, often used as a pointer to the start of an unmanaged buffer of char
packed tightly.
Your std::vector<std::string>
is a managed buffer of managed char
buffers. Each element in the vector
is a complete buffer some unknown number of char
s, not a single char
.
Upvotes: 1