Why the following code have compilation error?
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str="abc";
string result=str[0];
cout<<result<<endl;
return 0;
}
However, the following code works fine:
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str="abc";
str=str[0];
cout<<str<<endl;
return 0;
}
I works in unix and compilation command is: "g++ -g test.cpp -std=c++11 -o a", thenm ./a
The error for the first test.cpp after compile is:
test.cpp:9:21: error: invalid conversion from 'char' to 'const char*' [-fpermissive]
string result=str[0];
^
In file included from /usr/um/gcc-4.8.2/include/c++/4.8.2/string:52:0,
from /usr/um/gcc-4.8.2/include/c++/4.8.2/bits/locale_classes.h:40,
from /usr/um/gcc-4.8.2/include/c++/4.8.2/bits/ios_base.h:41,
from /usr/um/gcc-4.8.2/include/c++/4.8.2/ios:42,
from /usr/um/gcc-4.8.2/include/c++/4.8.2/ostream:38,
from /usr/um/gcc-4.8.2/include/c++/4.8.2/iostream:39,
from test.cpp:1:
/usr/um/gcc-4.8.2/include/c++/4.8.2/bits/basic_string.h:490:7: error: initializing argument 1 of 'std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]' [-fpermissive]
basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
^
std::basic_string doesn't have any constructor that takes a single CharT argument. This means that std::string (i.e. std::basic_string<char>) cannot be constructed from a single char.
The class does, however, have an assignment operator overload that takes a single CharT argument, which is why your second example compiles.
The difference between the two cases is because in the first you're performing copy initialization, which means technically you're first attempting to construct a temporary std::string instance from the char argument, and then copy it over to result. In the second you're performing assignment, which means assigning a new value to an existing std::string instance.
basic_string does have a constructor that takes a count followed by a character:
basic_string(size_type count, CharT ch, const Allocator& alloc = Allocator());
so your original example would compile if you changed the offending line to
string result = {1, str[0]};
The following code works fine as well:
string result;
result=str[0];
That means the difference is between initialization and simple assignment and, if you examine the error:
error: invalid conversion from ‘char’ to ‘const char*’
it should be clear that the initialization is not as "full-featured" as assignment - the is no string constructor that takes a char argument (there is an assignment that takes a char which is why your second example works).
You can fix it (in one way, there's no doubt others as well) by ensuring you initialize with a string rather than a character:
string result = str.substr(0,1);
str[0] returns a char&, but there is no conversion from char& to std::string
try thins instead
string result = string(1, str[0]);
Related
The below program tries to open a rom file and loads it to std::array.
#include <array>
#include <fstream>
#include <iostream>
const std::string ROM_FILE = "cpu_instrs.gb";
int main()
{
std::array<uint8_t, 0x8000> m_Cartridge;
std::ifstream istream(ROM_FILE, std::ios::in | std::ios::binary);
istream.seekg(0, std::ios::end);
size_t length = istream.tellg();
istream.seekg(0, std::ios::beg);
if (length > m_Cartridge.size())
{
length = m_Cartridge.size();
}
istream.read(m_Cartridge.data(), length);
for (const uint8_t& b : m_Cartridge)
{
std::cout << b << std::endl;
}
return 0;
}
When I ran the program above using g++, I got the following error
test.cpp: In function 'int main()':
test.cpp:21:34: error: invalid conversion from 'std::array<unsigned char, 32768>::pointer' {aka 'unsigned char*'} to 'std::basic_istream<char>::char_type*' {aka 'char*'} [-fpermissive]
21 | istream.read(m_Cartridge.data(), length);
| ~~~~~~~~~~~~~~~~^~
| |
| std::array<unsigned char, 32768>::pointer {aka unsigned char*}
In file included from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/9.2.0/include/c++/fstream:38,
from test.cpp:2:
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/9.2.0/include/c++/istream:486:23: note: initializing argument 1 of 'std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::read(std::basic_istream<_CharT, _Traits>::char_type*, std::streamsize) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_istream<_CharT, _Traits>::char_type = char; std::streamsize = long long int]'
486 | read(char_type* __s, streamsize __n);
| ~~~~~~~~~~~^~~
It seems to me that std::istream only works with char not unsigned char. When I change type from uint8_t to char. The program compiles and ran without problems. Is there any way to make std::istream work with uint8_t?
std::istream is written in terms of char_type being simply char, and similarly, std::istream::read is the same.
The conventional approach would be to reinterpret_cast<char*> the pointer that you are reading to:
istream.read(reinterpret_cast<char*>(m_Cartridge.data()), length);
Although using reinterpret_cast is often frowned upon in many cases, this is one such case where it's both necessary and also safe to perform, since pointers to char are capable of aliasing any object with the same reachability as the parent object (in this case, the same reachability as the entire array object).
In fact, if you check the std::istream::read page on cppreference, even it uses a similar example to read the raw binary:
std::uint32_t n;
if(raw.read(reinterpret_cast<char*>(&n), sizeof n)) { ... }
That said, there is technically an alternative way you can do this -- though it's not recommended. The various stream classes are templated on the character type (basic_*stream<...>), of which std::ifstream is an alias of. Technically you could try to instantiate std::basic_ifstream<unsigned char> and read from this without a cast. However, in doing so, you may need to implement a custom std::char_traits -- as this is not required by the C++ standard to work with signed or unsigned character types (e.g. std::char_traits<unsigned char> is not guaranteed to be valid)
I'm using a Unix shell compiler and need to import a Windows .dat file for input. Unfortunately this means there exists native '\r\n' components for carriage returns in the input file.
I'm hoping to scrub these out with something along the lines of the following:
#include <fstream>
#include <string>
using namespace std;
int main()
{
ifstream inputFile;
inputFile.open("myFile.dat");
string array[100];
int i = 0;
while(getline(dataIn, str))
{
str.erase(remove(str.begin(), str.end(), '\n'), str.end());
str.erase(remove(str.begin(), str.end(), '\r'), str.end());
array[0] = str;
i++;
}
return 1;
}
However this is providing the following error:
error: cannot convert ‘__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >’ to ‘const char*’ for argument ‘1’ to ‘int remove(const char*)’
for the first erase(), followed by
error: request for member ‘erase’ in ‘temp.std::basic_string<_CharT, _Traits, _Alloc>::c_str [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]()’, which is of non-class type ‘const char*’
for the second.
I've attempted str.c_str().erase but this has resulted in duplicates of the second error. Any suggestions would be greatly appreciated...
Two problems in the code:
You if you want to use the algorithm function remove, you need to add #include <algorithm>.
To ensure the ::remove (which is a function that removes the file named by the char * argument) isn't picked up, use std::remove.
I have been trying to learn C++ recently, but I have stumbled across some errors. For example, when I try to run this code to ask the user what they want outputted to a file:
#include <iostream>
#include <cstdio>
using namespace std;
main() {
string output; //Declare variables before starting
FILE * file = fopen("newfile.txt","w"); //creates file
cout << "Entire something that you want to be written to the file: " << endl;
cin.getline(output, 256); //Asks what you want to put into file
fprintf(file, output); //Puts output into file
fclose(file); //closes file
return 0;
}
using
g++ -o main test.cpp
I get this error:
test.cpp: In function ‘int main()’:
test.cpp:10:25: error: no matching function for call to ‘std::basic_istream<char>::getline(std::string&, int)’
cin.getline(output, 256);
^
test.cpp:10:25: note: candidates are:
In file included from /usr/include/c++/4.8/iostream:40:0,
from test.cpp:1:
/usr/include/c++/4.8/istream:618:5: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::getline(std::basic_istream<_CharT, _Traits>::char_type*, std::streamsize, std::basic_istream<_CharT, _Traits>::char_type) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_istream<_CharT, _Traits>::char_type = char; std::streamsize = long int]
basic_istream<char>::
^
/usr/include/c++/4.8/istream:618:5: note: candidate expects 3 arguments, 2 provided
/usr/include/c++/4.8/istream:427:7: note: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::getline(std::basic_istream<_CharT, _Traits>::char_type*, std::streamsize) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_istream<_CharT, _Traits>::__istream_type = std::basic_istream<char>; std::basic_istream<_CharT, _Traits>::char_type = char; std::streamsize = long int]
getline(char_type* __s, streamsize __n)
^
/usr/include/c++/4.8/istream:427:7: note: no known conversion for argument 1 from ‘std::string {aka std::basic_string<char>}’ to ‘std::basic_istream<char>::char_type* {aka char*}’
test.cpp:11:22: error: cannot convert ‘std::string {aka std::basic_string<char>}’ to ‘const char*’ for argument ‘2’ to ‘int fprintf(FILE*, const char*, ...)’
fprintf(file, output);
^
Could someone please help me? And please forgive me if this is something that can be easily solved, I am fairly new to C++ and do not quite understand it yet.
The header for string is missing:
#include <string>
Without it, sring isn't defined, and everywhere you use output, you'll have errors
With the include you'll have a lot less errors. But this line has another issue (as πάντα ῥεῖ already pointed out):
cin.getline(output, 256);
because cin.getline() expects a char* and the length. If you want to use a string, you have to use the function getline(), without size (limited to strings maximume size) and on an istream:
getline(cin, output);
Last remark: you are of course free to mix c-style io and streams. But you could win from getting used to streams for all your file io.
The error occurs at the line
cin.getline(output, 256);
According to the documentation for std::istream::getline, the first argument for cin.getline() should be a char * and not a std::string as you have declared it.
Try changing the declaration of output to a char * like so
char[256] output;
Edit: Using std::getline as the others have said would be a better idea though.
I'm trying to convert a character from a c string to an int but I keep running into an error.
Here's my code
while(std::getline(file, line)){
if(std::isdigit(line[0]) && std::isspace(line[1]) && std::isdigit(line[2])){
SequenceArray.push_back(line);
if(std::stoi(line[2])== (SequenceArray.size() -1)){
std::cout<< "Success" << std::endl;
The error that I keep getting is as follows:
a1.cpp: In function ‘int main(int, char**)’:
a1.cpp:30:25: error: call of overloaded ‘stoi(char&)’ is ambiguous
if(std::stoi(line[2])== (SequenceArray.size() -1)){
^
a1.cpp:30:25: note: candidates are:
In file included from /usr/include/c++/4.8/string:52:0,
from /usr/include/c++/4.8/bits/locale_classes.h:40,
from /usr/include/c++/4.8/bits/ios_base.h:41,
from /usr/include/c++/4.8/ios:42,
from /usr/include/c++/4.8/ostream:38,
from /usr/include/c++/4.8/iostream:39,
from a1.cpp:1:
/usr/include/c++/4.8/bits/basic_string.h:2823:3: note: int std::stoi(const string&, std::size_t*, int) <near match>
stoi(const string& __str, size_t* __idx = 0, int __base = 10)
^
/usr/include/c++/4.8/bits/basic_string.h:2823:3: note: no known conversion for argument 1 from ‘char’ to ‘const string& {aka const std::basic_string<char>&}’
/usr/include/c++/4.8/bits/basic_string.h:2926:3: note: int std::stoi(const wstring&, std::size_t*, int) <near match>
stoi(const wstring& __str, size_t* __idx = 0, int __base = 10)
^
/usr/include/c++/4.8/bits/basic_string.h:2926:3: note: no known conversion for argument 1 from ‘char’ to ‘const wstring& {aka const std::basic_string<wchar_t>&}’
a1.cpp:35:6: warning: label ‘std’ defined but not used [-Wunused-label]
std:exit(EXIT_FAILURE);
A char implicit converts to a int, you don't need to use extra functions.
'a' = 97, 'b' = 98, 'c'=99, etc., following the ASCII table
So if you write,
char a_char = 'a';
int a_val = a_char;
cout << a_val << endl;
you have:
97
For std::stoi missing, try #include <string> (and enable C++11). However see also this thread - the Windows ports of g++ have had a long-standing issue with support of stoi and to_string.
The second error is that std:exit should be std::exit.
The third error is because of line[2].c_str(). You have not told us what line is but the error message suggests it is a std::string. So line[2] is a char and char does not have any member functions. If you explain what you are trying to do in the code std::atoi(line[2].c_str()) someone will be able to help. Maybe you meant line[2] - '0' which will give an integer between 0 and 9 if the third character in the line was a digit.
std::stoi() is C++11. Not all compilers enable C++11 by default.
The first error is because you haven't enabled C++11 support. GCC currently chooses C++03 by default, and stoi didn't exist in that version.
Add -std=c++11 to the compiler's arguments. If that doesn't work, try -std=c++0x, and think about getting a more up-to-date compiler. If you're stuck with an ancient compiler, then use atoi as in the code you originally posted (or perhaps something involving strtol, if you want to detect errors).
Also make sure you've included <string> for the declaration of that function.
The second error is because you wrote : instead of ::.
This question already has an answer here:
No matching function - ifstream open()
(1 answer)
Closed 7 years ago.
void searchString(const string selection,const string filename)
{
ifstream myfile;
string sline;
string sdata;
myfile.open(filename);
while(!myfile.eof())
{
getline(myfile,sline);
sdata = sdata + sline;
}
How do i use string filename as myfile.open(filename)
Initially i was using file.txt instead, but if i use a variable that pass in by the function, like string filename, it give me an error
myfile.open("file.txt");
Error message is as followed:
main.cpp:203:25: error: no matching function for call to ‘std::basic_ifstream<char>::open(const string&)’
main.cpp:203:25: note: candidate is:
/usr/include/c++/4.6/fstream:531:7: note: void std::basic_ifstream<_CharT, _Traits>::open(const char*, std::ios_base::openmode) [with _CharT = char, _Traits = std::char_traits<char>, std::ios_base::openmode = std::_Ios_Openmode]
/usr/include/c++/4.6/fstream:531:7: note: no known conversion for argument 1 from ‘const string {aka const std::basic_string<char>}’ to ‘const char*’
make: *** [main.o] Error 1
The constructor for std::ifstream::open (for the particular standard of C++ that you're using) doesn't allow a std::string argument, so you have to use:
myfile.open(filename.c_str());
The constructor expects type const char * which you can obtain from a std::string object using its c_str() member function.