Hello I am learning C++ from a book and am on a exercise question below
Write a function that takes and returns an istream&. The function should read the stream until it hits end-of-file. The function should print what it reads to the standard output. Reset the stream so that it is valid before returning the stream.
#include "stdafx.h"
#include <iostream>
#include <istream>
#include <string>
#include <string.h>
#include <list>
#include <vector>
#include <fstream>
std::istream ReadFile(std::istream &iStream)
{
std::string word;
while (iStream >> word)
{}
std::cout << "I read value " << word << std::endl;
iStream.setstate(std::ios::goodbit);
return iStream;
}
int _tmain(int argc, _TCHAR* argv[])
{
ReadFile(std::cin);
system("pause");
return 0;
}
The above is my attempt, however I am getting errors at the "return iStream" line.
Error1 error C2280: 'std::basic_istream<char,std::char_traits<char>>::basic_istream(const std::basic_istream<char,std::char_traits<char>> &)' : attempting to reference a deleted function
2 IntelliSense: function "std::basic_istream<_Elem, _Traits>::basic_istream(const std::basic_istream<_Elem, _Traits>::_Myt &) [with _Elem=char, _Traits=std::char_traits<char>]" (declared at line 77 of "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\istream") cannot be referenced -- it is a deleted function
I don't really know what these errors are, I am aware you can delete stuff but I am not onto that topic in the book yet. As far as I know I have not at all touched the istream file... Can someone help me please?
Thanks!
You can’t return an istream by value because it’s not copyable.
Since it’s not copyable the copy constructor has been deleted (to enforce the non-copyability), and that’s the direct technical cause of the diagnostic.
So, instead of
std::istream ReadFile(std::istream &iStream)
… do
std::istream& ReadFile(std::istream& iStream)
In other news, …
Instead of
#include "stdafx.h"
just turn off precompiled headers in the Visual Studio project settings.
This also gives you more standard-conforming behavior for header inclusions.
If you don’t do that, then configure the project so that any warning about skipping an include, yields a hard compilation error.
Instead of
iStream.setstate(std::ios::goodbit);
… do
istream.clear();
Instead of the non-portable Microsoft monstrosity
int _tmain(int argc, _TCHAR* argv[])
just use standard
int main()
or in C++11 trailing return type syntax,
auto main() -> int
Instead of
system("pause");
simply run your program via Ctrl+F5 in Visual Studio. Or, place a breakpoint on the last right brace of main and run in the debugger. Or, run the program from the command line.
The exercise formulation
” should read the stream until it hits end-of-file
is ambiguous, but anyway reading words, as you’re doing, does not faithfully reproduce whitespace in the stream. For a more accurate reproduction of the stream contents you can either read character by character, or (via getline) line by line. Or, you can use a special mechanism for this task, namely outputting the read buffer, which does everything in one little statement.
Finally, you don’t need all those headers. You only need <iostream>, and if you choose to read lines, also <string>. Also, you don’t need the return 0; at the end of main, because that’s the default.
A deleted function is a special function (constructor, destructor, operator) that has been explicitly disabled. If you look carefully at the error you can see that the function is the basic_istream copy-constructor, which is disabled because istreams cannot be copied. You are attempting to copy the istream when you return istream, since your function is declared as returning an istream (rather than e.g. returning a reference to an istream).
Related
If I set a string as a filename, it doesn't work and I have no idea why. (I'm using codeblocks and it seems to work on other IDEs)
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
string FileName="Test.txt";
ofstream File;
File.open(FileName);
}
This does not work,while this next one does:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ofstream File;
File.open("Test.txt");
}
Error message:
no matching function for call to std::basic_ofstream::open(std::string&)
Can someone help a bit with this problem, I cannot understand why this error occurs.
Due to what should be considered a historical accident in the early era of C++ standardisation, C++ file streams originally didn't support std::string for filename parameters, only char pointers.
That's why something like File.open(FileName), with FileName being a std::string, didn't work and had to written as File.open(FileName.c_str()).
File.open("Test.txt") always worked because of the usual array conversion rules which allow the "Test.txt" array to be treated like a pointer to its first element.
C++11 fixed the File.open(FileName) problem by adding std::string overloads.
If your compiler doesn't support C++11, then perhaps you should get a newer one. Or perhaps it does support C++11 and you just have to turn on the support with a flag like -std=c++11.
So this is the code:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
void print_file(const ifstream& dat_in)
{
if(!dat_in.is_open())
throw ios_base::failure("file not open");
string buffer;
while(getline(dat_in, buffer)); //error here
}
int main()
{
ifstream dat_in("name_of_the_file.txt");
try{
print_file(dat_in);
}
catch(ios_base::failure exc){
cout << exc.what() << endl;
}
}
And I get an error that no instance of overloaded function std::getline matches the argument list.
I did this line of code a thousand of times, what is the problem now ...
3 IntelliSense: no instance of overloaded function "getline" matches the argument list
argument types are: (const std::ifstream, std::string)
Error 1 error C2665: 'std::getline' : none of the 2 overloads could convert all the argument types
The culprit is the const:
void print_file(const std::ifstream& dat_in)
// ^^^^^
Of course the std::ifstream's state is changed when reading data from it, thus it cannot be const in that context. You should simply change your function signature to
void print_file(std::ifstream& dat_in)
to get this working.
BTW the function name print_file is pretty confusing for a function that actually reads from a file.
the problem is here
void print_file(const ifstream& dat_in)
getline necessarily changes the stream that is passed-in. So change the above to (remove const)
void print_file(ifstream& dat_in)
Your code is passing a reference to a const ifstream parameter as the first parameter to std::getline(). Since std::getline() modifies its input stream parameter, it cannot have a const reference as the first parameter.
The error message from the compiler included a list of all the parameters, and it should've indicated that the first parameter is a const reference.
As a rule of thumb, pass and return all streams types as reference, neither const or by-value. Remember that const refers to the object, not the file and the object has many things that could change even if the file is a read-only file.
When I try using cout, it outputs a random number rather then the sentence I want. There is not compiler error, the program runs fine.
Here is my code:
//question.h
#ifndef _QUESTION_H_
#define _QUESTION_H_
using namespace std;
int first()
{
cout<<"question \n";
return 0;
}
#endif
//main.cpp
#include <iostream>
#include "question.h"
using namespace std;
void main(){
cout<<""<<first<<""<<endl;
cin.ignore();
cin.get();
}
I'm fairly new to writing my own header files, so I'm not sure if I did something wrong with that or if there's a problem with visual studio.
You're printing the address of the function. You need to call it:
cout<<""<<first()<<""<<endl;
^^
As mentioned in the comments, this doesn't have to output what you expect, either. The order in which arguments to functions (and that is just a bunch of function calls) is unspecified, so your function output could be in any position the compiler chooses. To fix this, put separate statements:
cout<<"";
cout<<first(); //evaluated, so output inside first() printed before return value
cout<<""<<endl;
It might not matter with the empty strings, but it will when you replace those with something visible.
Also, don't use void main. Use int main() or int main(int, char**) (see here). Don't use using namespace std;, especially in headers, as std has a lot of crap in it that is pulled in with that statement, leading to easy and confusing conflicts (see here). Finally, choose a name that does not conflict with identifiers reserved for the implementation as your include guard.
You are printing the address of the function first rather than calling it. But changing the function call won't fix your problem all by itself, because first writes to cout internally and then returns a number, which will be printed, which doesn't appear to be what you want.
If you want first to act like an <iomanip> thingie you have to jump through a few more hoops -- read that header to see how it's done.
Use cout<<""<<first()<<""<<endl; you need to actually call the function, not print its address
I just got this book "Exploring C++" and I'm on my first lesson. I've been doing C# for a couple years as a hobby so i though why not give C++ a try.
In the book it says i need to setup my compiler to use standard C++. I am using visual studio 2010 so i did. http://msdn.microsoft.com/en-us/library/ms235629.aspx
but when i go to compile the code it all works fine except for one if statement.
i have triple checked just as instructed so it must be something with the tools.
specifically
if (not in) // this line here
{
std::perror(argv[1]);
return EXIT_FAILURE;
}
The full sample
#include <algorithm>
#include <fstream>
#include <iostream>
#include <iterator>
#include <ostream>
#include <string>
#include <vector>
void read(std::istream& in, std::vector<std::string>& text)
{
std::string line;
while (std::getline(in, line))
text.push_back(line);
}
int main(int argc, char* argv[])
{
std::vector<std::string> text;
if (argc <2)
read(std::cin, text);
else
{
std::ifstream in(argv[1]);
if (not in)
{
std::perror(argv[1]);
return EXIT_FAILURE;
}
read(in,text);
}
std::sort(text.begin(), text.end());
std::copy(text.begin(), text.end(),
std::ostream_iterator<std::string>(std::cout, "\n"));
}
I would really like to continue with this book so any help is greatly appreciated.
And I apologize if this is awfully noobish of me.
not is an "alternative token" for the boolean operator !.
Perhaps your compiler doesn't support it.
Try this instead:
if (!in)
Indeed, here's exactly the same issue on another site.
VC compiler doesn't by default recognize alternative tokens (they are exceedingly rare nowadays), but I believe this support may be turned on with a compiler switch.
In fact, Visual Studio requires that you #include <ciso646> to get support for alternative tokens, even though the C++ Standard states that this should have no effect1. Naughty Visual Studio!
In any case, you might want to find a better, more modern textbook.
I recommend these resources.
1 [n3290: footnote 176]: In particular, including the standard header <iso646.h> or <ciso646> has no effect.
Try
if (!in)
instead of
if (not in)
as this is the code style that most C++ programmers are used to.
You shouldn't use /za. The thing is that it causes numerous compiler bugs when switched on and more important compiler problems like SFINAE aren't resolved anyway, and some headers like Windows headers won't compile.
Technically, the not keyword is used for the ! operator. You may find that MSVC doesn't support it, so just use ! directly.
I am writing a file splitting program, to assist with using large files with iPod notes. I want to use tmpfile() in cstdio but it returns a file* not an fstream object. I know it's not possible in standard C++ but does anyone know any libraries that work well with the standard that have the ability to convert a FILE* to an std::fstream object? Or, if not is tmpfile() functionality available in the standard, or another library?
Thanks!
My OS is Windows XP and I use either Dev-C++ 4.9.9.2 or MS Visual Studio 2008 as my compiler.
If all you want is a temporary file, use tmpnam() instead. That returns char* name that can be used for a temporary file, so just open a fstream object with that name.
Something like:
#include <cstdio>
#include <fstream>
...
char name[L_tmpnam];
tmpnam(name);
//also could be:
//char *name;
//name = tmpnam(NULL);
std::fstream file(name);
You do have to delete the file yourself, though, using remove() or some other method.
You can use the benefits of c++ streams by pumping your data via the << syntax into a std::stringstream
and later write it the .str().c_str() you get from it via the the C-API to the FILE*.
#include <sstream>
#include <cstdio>
#include <string>
using namespace std;
int main()
{
stringstream ss;
ss << "log start" << endl;
// ... more logging
FILE* f_log = fopen("bar.log", "w");
string logStr = ss.str();
fwrite(logStr.c_str(), sizeof(char), logStr.size(), f_log);
fclose(f_log);
return 0;
}
Even if you manage to convert a FILE* to an std::fstream, that won't work as advertised. The FILE object returned by tmpfile() has a special property that, when close()'d (or when the program terminates), the file is automatically removed from the filesystem. I don't know how to replicate the same behavior with std::fstream.
You could use tmpnam mktmp to obtain a temporary file name, open it with a stream and then delete it with remove.
char *name;
ifstream stream;
name = mktmp("filename");
stream.open(name);
//do stuff with stream here.
remove(name);//delete file.
Instead of using std::fstream, you could write a simple wrapper class around FILE*, which closes it on destruction. Should be quite easy. Define operators like << as necessary.
Be sure to disallow copying, to avoid multiple close() calls.
g++ has __gnu_cxx::stdio_filebuf and __gnu_cxx::stdio_sync_filebuf, in ext/stdio_filebuf.h and ext/stdio_sync_filebuf.h. It should be straight-forward to extract them from libstdc++ if your compiler is not g++.