How to Duplicate a file pointer [duplicate] - c++

This question already has answers here:
Duplicating file pointers?
(3 answers)
Closed 7 years ago.
I want to use fgets twice on the same stream. I have defined two file pointer pointing to the same file but when I use fgets on one of the pointer, the other also gets modified.
fun(FILE * input) {
FILE * input_dup=input;
char str[2];
fgets(str, 2, input);
fgets(str, 2, input_dup);
}
On the second call to fgets, why is it reading the next character.. It should give the same output as they both are pointing to the same location

Well, you are laboring under a fundamental mis-understanding:
If you copy a pointer, that does not copy the object it points to.
As it happens, there's no standard way for duplicating a FILE (though there are nonstandard ones, see: Duplicating file pointers?).
Which doesn't happen you are SOL, you can just use ftell to get the current position, and fseek to get back there (provided the stream is seekable, like a file).

As with all C++ coding, it is doing exactly what you told it to do. If you want another copy, you could make an overriding function that tells the system to read and act and copy the stream and return a pointer to an array. That would accomplish your goal.
Asecond solution would be to unget the stream's last char, then read again.

Related

What does the g stand for in gcount, tellg and seekg?

What does the g stand for in std::iostream's gcount, tellg and seekg members? And the p in pcount, tellp and seekp?
Why aren't they called just count, tell and seek?
In streams supporting both read and write, you actually have two positions, one for read (i.e. "get" denoted by "g") and one for write (i.e. "put" denoted by a "p").
And that's why you have a seekp (inherited from basic_ostream), and a seekg (inherited from basic_istream).
Side note: The language C has - in contrast to C++ - only one such function fseek for both pointers; There it is necessary to re-position the pointer when switching from read to write and vice versa (cf., for example, this answer). To avoid this, C++ offers separate functions for read and write, respectively.
C++ offers two pointers while navigating the file: the get pointer and the put pointer. The first one is used for read operations, the second one for write operations.
seekg() is used to move the get pointer to a desired location with respect to a reference point.
tellg() is used to know where the get pointer is in a file.
seekp() is used to move the put pointer to a desired location with respect to a reference point.
tellp() is used to know where the put pointer is in a file.
Main source: Quora, answer by Gunjan B. Yadav on Dec 1, 2017.

Reading in one byte at a time with .get() [duplicate]

This question already has answers here:
Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
(5 answers)
Closed 7 years ago.
So i'm reading in a input file that contains:
lololololololol
I need to read it in using binary one byte at a time for something I'm doing later on. To do this i'm using get() to read it in then storing it into a char. It seems to be working correctly except for the last char that it reads in. The vector that it is reading into contains:
lololololololol
�
I'm not quite sure what this last value is but it's totally throwing off my finial output. So my question is, is there a reason get() would read in a value or byte from my text document that is not there? Or is it reading in something that I don't know of?
code:
while(istr.good()) {
temp = istr.get();
input.push_back(temp);
}
It's reading the EOF (end of file) character. You need to do the check after reading it to avoid it being inserted to the vector:
while(temp = istr.get(), istr.good()) // comma operator
input.push_back(temp);
Or you might use the 2nd std::istream_base::get overload and let istr implicitly convert to bool:
while(istr.get(temp))
input.push_back(temp);
Or try more advanced approaches. operator>> and std::getline would also work fine for this kind of input.

What is the purpose of buffer = "\0" [duplicate]

This question already has answers here:
What is a null-terminated string?
(7 answers)
Closed 9 years ago.
I remember reading the explanation on the use of this line of code, but I've read so many books on sockets for the past week that I can't find it anymore.
I do remember in the book, they wrote their code using =\0, then said it would be better to have it at 1
I tried searching it, but had no luck, this is a piece of the code I'm reading where it is used
nread = recv(newsock, buffer, 25, 0);
buffer[nread] = '\0';
It turns the received buffer into a NUL-terminated C-string, that you can use with strlen, strcpy, etc.
I assume the code you show is for illustrative purposes only, not production code, because you're not checking the return value of recv, which can be -1. If that happens it will cause memory corruption.
This is the C/C++ null terminator which indicates the end of content in a character array.
http://en.wikipedia.org/wiki/Null-terminated_string
It is to signify that the string ends at that byte. In this case the last one.
\0 is the null character.
So you don't get garbage like "This is my message.aG¤(Ag4h98av¤"G#¤". Just imagine there's a \0 at the end of that string.
When dealing with networking, you usually want to send data like integers, and the most common practice is to send it in binary and not plaintext. An integer may look like "$%\0n" for example. 4 bytes, but the third one is a \0. So you have to take into account that there can be a \0. Therefore you should not store binary representation of data as a string, but rather as a buffer/stringstream.
Of course, maybe you don't want to print out the binary representation of it. But you have to keep it in mind. Maybe you want to print it out, who knows.

How to read any file safely into a string? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the best way to slurp a file into a std::string in c++?
I'm trying to imitate PHP's file_get_contents() function for C++.
However, when I convert a char array into a string, it stops at nullbyte:
fread(charbuf, 1, file_size, fp);
string str(charbuf);
How can I initialize the string as a static size array, and read the file contents directly to that container? Also, how do I check the errors for it, for example if there is not enough memory for initializing that string. This would also get me rid of the temporary memory allocation I'm currently using, which I would like to get rid of.
How about safety? Is it possible that many processes read the same file at same time and/or one of them writes in it at same time when I am reading it? How do I avoid such things happening?
I hope you can answer other way than "string isn't binary container".
I ask to reopen this question for the fact: "Apparently, this question is as relevant as ever: two years later, the two most efficient solutions still copy the whole file contents in memory, and this copy cannot be elided by the optimizer. This is a quite unsatisfactory state of affairs. – Konrad Rudolph Oct 25 '10 at 6:25" at What is the best way to read an entire file into a std::string in C++? Or do you want me to create new question that asks to read a file without having extra copy of the string?
std::ifstream fin("somefile.txt");
std::stringstream buffer;
buffer << fin.rdbuf();
std::string result = buffer.str();
This snippet will put all your file into std::string
I hope you can answer other way than "string isn't binary container.
std::string is a binary container, but the constructor you chose takes a C-style string as an argument. Try a different constructor:
std::fread(charbuf, 1, file_size, fp);
std::string str(charbuf, file_size);
EDIT: Taking into account requirement to avoid memory allocations:
std::string str(file_size, 0);
std::fread(&str[0], 1, file_size, fp);

Overloading operator>> to a char buffer in C++ - can I tell the stream length?

I'm on a custom C++ crash course. I've known the basics for many years, but I'm currently trying to refresh my memory and learn more. To that end, as my second task (after writing a stack class based on linked lists), I'm writing my own string class.
It's gone pretty smoothly until now; I want to overload operator>> that I can do stuff like cin >> my_string;.
The problem is that I don't know how to read the istream properly (or perhaps the problem is that I don't know streams...). I tried a while (!stream.eof()) loop that .read()s 128 bytes at a time, but as one might expect, it stops only on EOF. I want it to read to a newline, like you get with cin >> to a std::string.
My string class has an alloc(size_t new_size) function that (re)allocates memory, and an append(const char *) function that does that part, but I obviously need to know the amount of memory to allocate before I can write to the buffer.
Any advice on how to implement this? I tried getting the istream length with seekg() and tellg(), to no avail (it returns -1), and as I said looping until EOF (doesn't stop reading at a newline) reading one chunk at a time.
To read characters from the stream until the end of line use a loop.
char c;
while(istr.get(c) && c != '\n')
{
// Apped 'c' to the end of your string.
}
// If you want to put the '\n' back onto the stream
// use istr.unget(c) here
// But I think its safe to say that dropping the '\n' is fine.
If you run out of room reallocate your buffer with a bigger size.
Copy the data across and continue. No need to be fancy for a learning project.
you can use cin::getline( buffer*, buffer_size);
then you will need to check for bad, eof and fail flags:
std::cin.bad(), std::cin.eof(), std::cin.fail()
unless bad or eof were set, fail flag being set usually indicates buffer overflow, so you should reallocate your buffer and continue reading into the new buffer after calling std::cin.clear()
A side note: In the STL the operator>> of an istream is overloaded to provide this kind of functionality or (as for *char ) are global functions. Maybe it would be more wise to provide a custom overload instead of overloading the operator in your class.
Check Jerry Coffin's answer to this question.
The first method he used is very simple (just a helper class) and allow you to write your input in a std::vector<std::string> where each element of the vector represents a line of the original input.
That really makes things easy when it comes to processing afterwards!