C++ Using auto, enchanced For Loops - c++

So, the goal of this function is for the user to give a array of strings, then using a previously defined function, determine if each individual string is a valid sentence. Unfortunately, I am completely lost about how to go about this.
int validSentences(const std::vector<std::string> paragraph)
{
char* str;
for (auto a : paragraph)
{
std::cout << a << " ";
strcat(str, a.c_str);
}
std::cout << str << std::endl;
}
Here is what I have as a prototype, but I'm sure this is way off base.
I think a good start to my question would be this:
How would I go about taking each string within the given vector, and converting it to a cstring using an enhanced for loop that utilizes the auto keyword?

Related

cout operator << doesn't work for vector<char> [duplicate]

This question already has answers here:
How do I print out the contents of a vector?
(31 answers)
Closed 1 year ago.
Why doesn't this vector print out?
void str_read(std::vector<char> str);
int main() {
std::vector<char> str;
str_read(str);
std::cout << str << std::endl;
return -1;
}
void str_read(std::vector<char> str) {
while (1) {
char ch;
scanf("%c", &ch);
if (ch == '\n');
break;
}
}
I get an error:
error: no type named 'type' in 'struct std::enable_if<false, void>'
You get the error because there is no standard operator<< defined for std::vector. If you want that, you have to implement it yourself.
Even so, str_read() takes in a std::vector by value, so it receives a copy of the caller's vector, and thus any modifications it makes will be to that copy and thus lost when str_read() exits. That means the vector in main() is never populated.
Try this instead:
#include <iostream>
#include <vector>
#include <string>
std::ostream operator<<(std::ostream &out, const std::vector<char> &vec) {
for(auto ch : vec) {
out << ch;
}
return out;
/* alternatively:
return out.write(vec.data(), vec.size());
*/
}
void str_read(std::vector<char> &str) {
char ch;
while (cin.get(ch) && ch != '\n') {
str.push_back(ch);
}
}
int main() {
std::vector<char> str;
str_read(str);
std::cout << str << std::endl;
}
That being said, why not just use std::string instead of std::vector<char>? There is a standard operator<< defined for std::string, and a standard std::getline() function for reading characters into std::string until '\n':
#include <iostream>
#include <string>
int main() {
std::string str;
std::getline(cin, str);
std::cout << str << std::endl;
}
There are 3 BIG problems here.
You are passing the vector by value, not by reference. As a result, any changes made to the vector in the function will stay local to the vector initialised as a part of that function call stack. It will be deleted by the time you return. so change the signature to str_read(std::vector<char>& str).
You are going through the stdin capture character by character. AFAIK scanf although will read the new line character, will leave it in the buffer not appending it to your string. From the looks of it, all you are trying to do is read a string from stdin, store it in a char array, and print that char array out. Don't overengineer stuff. just use std::cin and store it in a string, to begin with, like
std::string captured_string;
std::getline(std::cin, captured_string);
You can then std:cout << captured_string << "\n"; directly
If you insist on storing characters in a vector, which I do not understand why would you need to, you can just do std::vector<uint8_t> char_array(captured_string.begin(), captured_string.end()). However, std::cout << char_array << "\n" will still not work. That is for 2 reasons, the first one being that std::vector<T, allocator> does not have an overload for << of std::ostream. The second is that the moment you convert your string to an array of characters, they do not mean the same thing.
I think you misunderstood what you were taught in class about strings being stored as arrays of characters. They are indeed stored as arrays, but an array type and a string type are fundamentally different and are not equivalent.
Capturing the string from stdin will anyway store it in a char* or a std::string as I have shown above. You can use that directly without having to convert a string to an array of characters.
In essence, your program decays to this
#include <iostream>
#include <string>
int main()
{
std::string captured_string;
std::getline(std::cin, captured_string);
std::cout << captured_string << "\n";
return EXIT_SUCCESS;
}
EDIT
I just realised that your objective may have been to print the string character by character. In that case, you don't need to convert it to an array. There are multiple ways of doing this, but the least confusing and probably the easiest way of doing this would be to use the range-based for loop.
int main()
{
std::string captured_string;
std::getline(std::cin, captured_string);
for (auto& ch: captured_string) // containers in the standard library support range based for loops.
std::cout << ch << "\n"; // print each character in the string on a new line
return EXIT_SUCCESS;
}
First, explain
error: no type named 'type' in 'struct std::enable_if<false, void>'
cout is character-oriented stream output and does not accept output formats of the vector<char> type.
Vector is an array of elements of the specified type. If you want to use a vector, you can store values in it first:
vector<char> str;
str.push_back('H');
An element of the array is then printed to standard output cout
cout << str[0] <<endl;
The second problem is that your function str_read is defined as void, which has no value, so it cannot be located in cout's standard output either.
It looks like you want to put the characters as input into a vector and print them out. If you position the function as void, you will need to change the value of str by reference
Next question, I see that your while loop break is mistimed and does not combine with if. You should not add a semicolon after an if statement.
if (ch == '\n')break;
Finally, if you choose to change the value of str by reference, you need to implement this in the function, as mentioned above, when you type a value of ch, you need to use str.push_back(ch) to store it.
Your 'str' variable doesn't have anything in it when you try to display it. You also don't initialize your vector to any variables for the function to read anyways.

C++ Adding to a string (Output)

Below is a cout of a c++ statement:
cout << "TESTING" + 2 << endl;
I understand why this statement will print out sting. But the question I have is if I do the code below it will cause an error. I don't understand why as this is the same thing. Sorry for a basic question I am new to c++.
string t = "TESTING";
cout << t + 2 << endl;
Thanks in advance for any help. :)
This is an interesting case. I'm not sure if you've actually printed the result of your first statement or not, but if you do you see that you are actually getting "STING" and not "TESTING2", or something like that!
There are a few things going on here. In your first statement, you are constructing a string using a string literal. In this case, C++ create a const char[N] and put your string into it. Since char[N] is technically an array (and array is a pointer), the operator + acts as increment and the result of "TESTING" + 2 is actually a pointer to the second element of "TESTING", which is "STING". You'll not see any errors, because C++ thinks that what's you wanted to do.
In your second statement, you are telling C++ that I want a std::string object. The std::string is by design safer and will nag at you if you try to add anything other than a string to it. So, when you do, you get an error. For your second statement to work as intended, you should write t + std::to_string(2).
It is important to know the difference between string and char types. String is a class that manages string of characters. And char[] is an array of characters. Refer this question for the explanation. In your case the code will work if you do:
#include <iostream>
int main ()
{
char t[] = "TESTING";
std::cout << t + 2 << std::endl;
return 0;
}
If you want to concatenate string with int then you should explicitly convert it:
#include <iostream>
int main ()
{
std::string m = "Testing ";
std::cout << m + std::to_string(2) << std::endl;
return 0;
}

Using string array as function argument

I meant to write program which will simply delete single letters from the input given by user, let's say we've got some text like: "monkey eat banana" and we supposed to delete the letter 'a' from the text above.
The final output supposed to look like this:
'monkey et bnn'
I've got the code which works pretty much flawlessly with single strings, but I have to use getline() function to obtain some longer texts, that is why I have to declare array of string, in order to pass it's size in the second argument of getline() function, like so:
string text[256];
getline(text, 256);
I would like to use getline() function without giving a size of an array, but I think it's impossible, therefore I need to stick with string array instead of a string.
The problem I've got is that I don't know how to correctly pass array of string, to use it as function's argument. Here's my code;
#include <iostream>
#include <string>
using namespace std;
void deleteLetter(string &text[], char c)
{
size_t positionL = text.find(c);
if(positionL == string::npos)
cout << "I'm sorry, there is no such letter in text" << endl;
else
text.erase(positionL, positionL);
cout << "After your character removed: " << text << endl;
}
int main()
{
string str1[256];
char a = 'a';
cin.getline(str1, 256);
deleteLetter(str1, a);
}
I know it's elementary stuff, but still I can't figure it out on my own.
Perhpahs I should reach out for your help.
It sounds to me like you don't need an array of strings. Just to read as many characters the user types, into a string. getline should deal fine with this.
int main()
{
std::string str1; // just a string here, not an array.
std::getline (std::cin,str1);
deleteLetter(str1, 'a');
}
Now you should change the signature of DeleteLetter to take a single string as argument.
void deleteLetter(std::string& text, char c);
How your are going to implement deleteLetter is another question. The way you have it, it will delete only the first occurence of 'a'.
To read a string from console input (cin), you can use the getline() function:
std::string line;
std::getline(std::cin, line);
To remove all the occurrences of a given letter from a string, you can use the so called erase-remove idiom, with a combination of the string::erase() method and the std::remove() algorithm.
(Note that this idiom is usually showed applied to std::vector, but don't forget that a std::string can also be viewed as a "container of characters" stored in sequence, similar to vector, so this idiom can be applied to string content as well.)
To pass a std::string to functions/methods, use the usual C++ rules, i.e.:
If the function is observing the string (without modifying it), pass using const reference: const std::string &
If the function does modify the content of the string, you can pass using non-const reference: std::string &
A simple compilable code follows:
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
//
// NOTE:
// Since the content of 'text' string is changed by the
// removeLetter() function, pass using non-const reference (&).
//
void removeLetter(string& text, char letter)
{
// Use the erase-remove idiom
text.erase(remove(text.begin(), text.end(), letter),
text.end());
}
int main()
{
string line;
getline(cin, line);
cout << "Read string: " << line << endl;
removeLetter(line, 'a');
cout << "After removing: " << line << endl;
}
This is what I got with MSVC:
C:\Temp\CppTests>cl /EHsc /W4 /nologo test.cpp
test.cpp
C:\Temp\CppTests>test.exe
monkey eats banana
Read string: monkey eats banana
After removing: monkey ets bnn
It's not very clear to me from your question if you also want to pass vectors of strings around (probably in other parts of your code)...
Anyway, if you want a vector of strings (i.e. you want to store some strings in a vector container) you can simply combine these STL class templates like this:
std::vector<std::string> strings;
To pass that to functions/methods, use the usual C++ rules, i.e.:
If the function is observing the array of strings (without modifying it), pass using const references (const &): vector<string> &
If the function does modify the content of the vector, you can pass using non-const references (&): vector<string> &

Different types of input using template function

I'm try to get input from a user using a templated function. I want to be able to input int, doubles, floats, and strings. So here's the code I have so far:
template<class DataType>
void getInput(string prompt, DataType& inputVar)
{
cout << prompt;
cin >> inputVar;
}
int main()
{
string s;
int i;
float f;
double d;
getInput("String: ", s);
getInput("Int: ", i);
getInput("Float: ", f);
getInput("Double: ", d);
cout << s << ' ' << i << ' ' << f << ' ' << d << endl;
return 0;
}
The basic types all work, but the problem I have lies with inputting strings. I'd like to be able to input more than one word, but to the fact that I'm using cin I can't. So is it possible input multi-word strings as well the basic types in a manner similar to what I'm doing?
I think you want to use getline anyway, as you don't want to leave stuff in your input buffer after each prompt. To change the behaviour only for strings, though, you can use a template specialisation. After your template function:
template<>
void getInput(string prompt, string& inputVar)
{
cout << prompt;
getline(cin, inputVar);
}
Overload the function for string (or do template specialization).
void getInput(string prompt, string& inputVar) // <--- overloaded for 'string'
{
cout << prompt;
getline(cin, inputVar); //<-- special treatment for 'string' using getline()
}
I believe you will need to special-case strings. cin will get just one word, and you'll need to get the whole line using getline(). See this page for reference. You can then manipulate the line as you see fit: split it, parse it, whatnot.
Unfortunately that clobbers the entire line, and if you have something like "one two three 123 3.1415", then the entire line will be consumed.
Also see the example here for a better way to decide between numbers/strings/words/floats. But that does not utilise templates to the full.
The way this is written you could get some probably unexpected results. For example, you could have a session that goes like this:
String: Foo 12 3.14159 1.5 <enter>
Int: Float: Double: Foo 12 3.14159 1.5
I know you just gave an example, but this is almost certainly not what you want to do. cin will never register any input until enter is pressed, so you probably want to go line by line anyway, using getline. Otherwise things will get funky like above.
Even if you had access to each keypress, you probably couldn't accomplish this inline like it seems you want to.

In C++, using operator<< to construct input for a function

I would like to be able write code that looks like this:
int n;
std::string s = "some string";
SomeFunction("hello world" << n << " " << s << std::endl);
Where SomeFunction() is a method of some other class. The point is that I would like to be able to construct input for certain method using operator<<, just the way one'd do when writing to standard output in C++. How can I do that?
Thanks.
Your first parameter would have to be a home-made type that overloads operator<< and builds some kind of parameter list.
Your class would probably contain an ostream and would forward the operator<< to it.
If the function takes a string rather than your mysterious string-building object, you would then need to convert your object back to a string.
You could do it aleady with ostringstream like this:
int n;
std::string s;
std::ostringstream oss;
SomeFunction( ( oss << "hello world " << n << " " << s << '\n' ).str() );
Thanks, but this solution is way too obvious. I am looking for the code to remain the same as in the sample. – Alexander Sandler 54 secs ago
A surprising bias against obvious solutions?
Your syntax just cannot be achieved (in general[1]) without the macro that you describe in the first comment. Period.
[1] In specific cases you might be able to force the issue by overloading to ostream& operator<<(std::string, myspecifictype). In practice this will give you nothing but headaches because just about every use of the << operator will subsequently result in ambiguous overload resolutions