cin.getline : no matching function for call - c++

In many answers and questions such as this one, it is recommended to use cin.getline from <string> and not getline(cin, variable):
#include <iostream>
#include <string>
using namespace std;
int main() {
string name;
cin.getline(name);
}
But in my case I have build issue:
g++ foo.cpp
foo.cpp: In function ‘int main()’:
foo.cpp:8:21: error: no matching function for call to
‘std::basic_istream<char>::getline(std::string&)’
8 | cin.getline(name);
| ^

From the error told by the compiler, it is evident that there is no such function overload that accepts a type reference to std::string (for cin.getline()). Rather, it accepts parameters like:
const int MAX = 100;
char input[MAX];
cin.getline(input, MAX);
// Or better
// cin.getline(input, sizeof input);

Related

Can't write to ostream in gnu linux c++ error: invalid operands of types ofstream and ‘const char [2]’ to binary ‘operator

Can't compile this small code on Linux:
#include <fstream>
#include <string>
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
char fileName[512];
sprintf(fileName, "test");
ofstream iriFile(string(fileName));
iriFile<<",";
return 0;
}
I am compiling like this: g++ test.cpp and am getting this:
test.cpp:12:11: error: invalid operands of types
‘std::ofstream(std::__cxx11::string) {aka
std::basic_ofstream(std::__cxx11::basic_string)}’ and
‘const char [2]’ to binary ‘operator<<’ iriFile<<",";
What might be the reason?
Ok, the solution is to remove implicit string() creation:
string sFileName(fileName)
ofstream iriFile(sFileName);
First of all you do not need to explicitly convert const char * to std::string there is std::ifstream constructor for it:
std::ofstream iriFile(fileName);
but if you want to be extra safe and verbose use proper C++ then:
std::ofstream iriFile( static_cast<std::string>(fileName) );
not C style cast.
As you pointed out, removing the explicit string creation fixes it.
It could be worth to add that this can also be fixed for types with explicit constructors by using list initialization, like so:
ofstream iriFile(string{sFileName});

Receiving error when using push_back with a struct data type c++

I have the following code, where I am generating a deck of cards.
First, I determine the suit with the function convertIntToSuit, which then goes into the next loop to populate the Card deck. But I keep getting the following error:
Running /home/ubuntu/workspace/A5/Assignment5/main.cpp
make: Entering directory `/home/ubuntu/workspace/A5/Assignment5'
Compiling main.o
g++ -Wall -g -O3 -std=c++11 -I/usr/include -c -o main.o main.cpp
main.cpp: In function ‘int main()’:
main.cpp:39:33: error: no matching function for call to ‘std::vector<Card>::push_back(<brace-enclosed initializer list>)’
deck.push_back({i,s});
Here is my code:
// The include section adds extra definitions from the C++ standard library.
#include <iostream> // For cin, cout, etc.
#include <iomanip> // For text formatting (setprecision, setw, etc.)
#include <cmath> // For math functions (sin, cos, pow, etc.)
#include <cstdlib>
#include <vector>
#include <string>
#include"convertIntToSuit.h"
#include"printCard.h"
//#include"shuffleDeck.h"
using namespace std;
struct Card {
string suit;
int rank;
};
int main() {
vector<Card> deck;
for(int j = 0; j<4; ++j){
string s = convertIntToSuit(j);
for(int i=1; i<=13; ++i){
deck.push_back({i,s});
}
}
return 0;
}
The push_back function does not understand what you are sending to it. Enclosing the two properties of Card in curly brackets is not enough. You must construct the Card struct before sending it to push_back.
There are 2 options here:
Either to construct Card object explicitly: deck.push_back(Card{s,i});
Construct card object in-place inside vector. That could eliminate unneeded object copies though in this case the benefit is negligible. But for that you need to define an explicit c'tor that takes both arguments.
c++11 does not allow implicit construction of objects with just arguments.
Once you have the c'tor - you can use emplace_back member function which does exactly what you want: it takes the arguments to the constructor and constructs the object in-place with those arguments. In your case:
struct Card {
string suit;
int rank;
Card(string s = string(), int r = 0) : suit(std::move(s)), rank(r) {}
};
for (int i=1; i<=13; ++i){
deck.emplace_back(i,s);
}
Please note that you do not need curly brackets when using emplace_back.
Do it like this for every iteration:-
Card c1;
c1.suit=s;
c1.rank=i
deck.push_back(c1);
Or
what you are doing will be:-
deck.push_back({s,i});
string will come first before int because of your struct declaration.

std::isgraph is ambiguous when `using namespace std` is used

I tried to use std::isgraph from <cctype> as a predicate in find_if. But compiler errored out saying:
error: no matching function for call to ‘find_if(__gnu_cxx::__normal_iterator< const char*, std::basic_string< char> >, __gnu_cxx::__normal_iterator< const char*, std::basic_string< char> >, < unresolved overloaded function type>)’
I have used using namespace std; and from my understanding there will be two isgraph functions visible in the global namespace. So ::isgraph or simply isgraph should be ambiguous and std::isgraph should not be ambiguous. On the contrary, using ::isgraph is OK while std::isgraph is not.
Can someone explain what I missed? A few related questions are What are the function requirements to use as the predicate in the find_if from the <algorithm> library? and C++ using standard algorithms with strings, count_if with isdigit, function cast. But they didn't answer why explicitly specifying std:: still doesn't resolve to the function in the std namespace.
EDIT:
#include <cctype>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
int main()
{
string root_line = "hello";
auto ind = distance(root_line.begin(), find_if(root_line.begin(), root_line.end(), std::isgraph));
cout << ind;
return 0;
}
I compiled the above code with g++ -std=c++11 of version 4.8.4
std::isgraph is overloaded.
To resolve the ambiguity you could cast it to the relevant function pointer type.
But in order to use it correctly the argument should be converted to unsigned char, so better define a wrapper function:
using Byte = unsigned char;
auto is_graphical( char const ch )
-> bool
{ return !!isgraph( Byte( ch ) ); }
Note that this only works with single-byte encodings, and that it depends on the current locale at the C level (see setlocale).
There is a std::isgraph defined in <cctype> and a different std::isgraph defiend in <locale>. Using overloaded functions as functors can be a pain as the compiler has difficulty figuring out which version of the function you want. You can resolve the ambiguity by casting, or using a lambda or named wrapper function as suggested by #Cheersandhth.-Alf
#include <cctype>
#include <algorithm>
#include <string>
#include <iostream>
int main()
{
std::string root_line = "hello";
auto ind = std::distance(root_line.begin(), std::find_if(root_line.begin(), root_line.end(), static_cast<int(*)(int)>(std::isgraph)));
std::cout << ind;
}
Live example: http://ideone.com/heSSEZ

syntax error when using ifstream

It's been a long time since I've done any C++. What's wrong with this code?
#include <iostream>
#include <fstream>
using namespace std;
main()
{
ifstream& ifs("foo.txt");
}
Gives:
$ g++ foo.cc
foo.cc: In function ‘int main()’:
foo.cc:7:25: error: invalid initialization of non-const reference of type ‘std::ifstream& {aka std::basic_ifstream<char>&}’ from an rvalue of type ‘const char*’
ifstream& ifs("foo.txt");
You used a & when you should not have done.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream ifs("foo.txt");
}
Passing values by reference isn't done in the variable declaration, but instead in the parameter list of the function using the ifstream object. For example, your function main might look like this:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream ifs("foo.txt");
myFunction(ifs);
}
and your called function should look like this:
void myFunction(std::ifstream& in_stream)
{
// ...
}
If you need the C++11 reference type (which I doubt, but maybe), try this:
ifstream ifs("foo.txt.");
std::ref<std::ifstream> ifs_ref(ifs);
That works in a lot of cases where doing a regular by-ref wouldn't.
semantically, a reference is a pointer. so your code doesn't compile for the same reason this code doesn't:
main()
{
ifstream* ifs("foo.txt");
}
as others have said, you want to create an object of type ifstream. not a reference (nor a pointer) to it.

Read non constant c string into string class

I need to read a non-constant C string into a C++ string. However, I only see methods in the string class that read constant C strings into the string class.
Is there anyway to do this in C++?
Update:
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
string a;
// other code here
a(argv[0]);
cout << a << endl;
return 0;
}
error:
test.cpp: In function 'int main(int, char**)':
test.cpp:11:14: error: no match for call to '(std::string {aka std::basic_string<char>}) (char*&)'
a(argv[0]);
I did some more investigation, and replaced argv[0] with a constant string, and found that I still got a similar error message. A better question would now be: How can I declare an object and call its constructor later?
You're misinterpreting what the function signatures mean. The conversion takes its argument as a const char *, but that doesn't mean that you cannot pass a char* to it. It's just telling you that the function will not modify its input. Why don't you just try it out?
#include <iostream>
#include <string>
int main()
{
char str[] = "hello";
std::string cppstr = str;
std::cout << cppstr << endl;
return 0;
}