-2

On the CPlusPlus website for std::istream::ignore, it says

istream& ignore (streamsize n = 1, int delim = EOF);

Extract and discard characters

Extracts characters from the input sequence and discards them, until either n characters have been extracted, or one compares equal to delim.

Why does it say it discards them rather than returns them?

EDIT

As requested, here is the particular code in question. It is a callback function, server-side, processing the client file that was sent (_data)

static void loadFile (const std::string &_fileName, std::vector<char> &_data)                                                                                            
{
    std::ifstream ifs;
    ifs.exceptions(std::ifstream::failbit);
    ifs.open(_fileName, std::ifstream::in | std::ifstream::binary);
    auto startPos = ifs.tellg();
    ifs.ignore(std::numeric_limits<std::streamsize>::max());
    auto size = static_cast<std::size_t>(ifs.gcount());
    ifs.seekg(startPos);
    _data.resize(size);
    ifs.read(_data.data(), size);
    std::cout << "loaded " << size << " bytes" << std::endl;
}   
puk
  • 14,848
  • 25
  • 101
  • 181
  • because "returns" would be wrong. It returns the `istream` not the characters – 463035818_is_not_a_number Feb 22 '18 at 07:52
  • 3
    I don't think I understand the question... It **discards** them, in the sense that they are **thrown away**, you don't get to see or use them in any code you write. – BoBTFish Feb 22 '18 at 07:53
  • 1
    agree that the question is a bit unclear. Maybe you can explain why you think "returns them" would be more appropriate – 463035818_is_not_a_number Feb 22 '18 at 07:54
  • 1
    That's even part of the function *name*, to *ignore* things. – Some programmer dude Feb 22 '18 at 07:57
  • @user463035818 I want to read the contents of a file (`std::ifstream ifs`, `ifs.open(...)`) then I want to read it (`ifs.read(...)`). I am reviewing someone else's code and they have a `ifs.ignore(std::numeric_limits...)` in there. I assumed it was just telling the compiler to read the whole file. So my question is why is it "discarding" anything – puk Feb 22 '18 at 07:57
  • 2
    It's a common way to read the beginning of a line, and then *ignore* (and discard) the rest of the line. It makes sense with text files when using formatted input (the `>>` operator) but not for general "binary" files or when using `read` to read larger blocks. Without more context we can only guess badly, and even with context we can still only guess. The only person that can reliably answer your question is the one who wrote the code. – Some programmer dude Feb 22 '18 at 08:01
  • @puk - You should probably show a snippet of code to provide some context. Maybe the file is a set of records with formatting, so you can safely skip (read and discard) sequences of characters. But the immediate answer to the question is, there is no way to return them, so they get discarded after being read. – jww Feb 22 '18 at 08:41
  • @jww Will modify the question shortly – puk Feb 22 '18 at 08:42
  • @Someprogrammerdude to me, a non expert, it seems rather strange to specify that it discards something just because it doesn't return. Like saying ping discards the website content because it doesn't return it, or a tax audits discards the entire corporation. – puk Feb 22 '18 at 08:59
  • What the `ignore` call in the code snippet you show does, is to find out the number of bytes in the file. The `ignore` reads (and discards) the whole file, updating the value returned by `gcount`. This value is used to preallocate the vector that stores the data, and then the whole file is read into the vector in a single `read` call. – Some programmer dude Feb 22 '18 at 09:03
  • @Someprogrammerdude I understand now, you need to *dummy read* it so you know the size, so you can resize the target (`data`) so you can read it for real – puk Feb 22 '18 at 09:05
  • Correct. The reason `ignore` is used is because [`seekg`](http://en.cppreference.com/w/cpp/io/basic_istream/seekg) does not update the counters, so you can't just seek to the end and get the size but have to actually read the whole file. And since it's hard to read the whole file without knowing the size (it's a catch-22) and there is a function which *can* do that and also discard the irrelevant data at the same time the author just uses that funciton: `ignore`. – Some programmer dude Feb 22 '18 at 09:08
  • 1
    I think this question has the potential to be a good one if you reformulate it to ask about the use of `ignore` in the snippet you posted (rather than why a function named `ignore`, well, ignores the input). – T.C. Feb 22 '18 at 09:31
  • Agree with @T.C. Its not a bad question. The presentation has room for improvement. It is probably a lot easier to do now that you understand what is going on. – jww Feb 22 '18 at 10:40

2 Answers2

1

Why does it say it discards them rather than returns them?

Because there are other functions to return them. See std::istream::getline and std::getline


Update

The whole purpose of the following lines in your updated post is to obtain the size of the file.

auto startPos = ifs.tellg();
ifs.ignore(std::numeric_limits<std::streamsize>::max());
auto size = static_cast<std::size_t>(ifs.gcount());

This is the first time I have seen use of istream::ignore() to do that. You could also use the following to get the size of the file.

// Find the end of the file
ifs.seekg(0, std::ios::end);

// Get its position. The returned value is the size of the file.
auto size = ifs.tellg();
R Sahu
  • 196,807
  • 13
  • 136
  • 247
  • Then would a line like `ifs.ignore(std::numeric_limits::max());` do nothing? – puk Feb 22 '18 at 07:59
  • @puk, it would do something. It would read the characters and discard them. That is not doing nothing. – R Sahu Feb 22 '18 at 08:01
  • 3
    At most `std::numeric_limits::max()` chars. (which is a lot!) This may be an **XY Problem** -- why are you discarding them to begin with? – David C. Rankin Feb 22 '18 at 08:02
  • @DavidC.Rankin its not "at least" but "at most" ;) – 463035818_is_not_a_number Feb 22 '18 at 08:03
  • @user463035818 -- good eye. It was somewhat a lackadaisical comment to begin with, but you are correct. – David C. Rankin Feb 22 '18 at 08:04
  • 2
    Actually, it would discard all of them, regardless of the size of the file. `istream::ignore` treats `std::numeric_limits::max()` as a special value that means ignore the whole stream (up until the specified delimiter). – Benjamin Lindley Feb 22 '18 at 08:05
  • If you do `ifs.open()...ifs.seekg(ifs.tellg())...ifs.read()` what purpose does `ignore` serve? – puk Feb 22 '18 at 08:08
  • @puk, `ignore` can be used to ignore only up to a delimiter. `ignore(size, '\n')` is probably the most often used scenario. – R Sahu Feb 22 '18 at 08:13
  • @RSahu I fully understand, which makes it all the more difficult for me to understand why the author chose to do this. I will expand on the question shortly – puk Feb 22 '18 at 08:42
1
auto startPos = ifs.tellg();

This stores the position at the beginning of the (just-opened) file.

ifs.ignore(std::numeric_limits<std::streamsize>::max());

This reads through the entire file (until EOF) and discards the content read.

auto size = static_cast<std::size_t>(ifs.gcount());

gcount returns the number of characters read by the last unformatted input operation, in this case, the ignore. Since the ignore read every character in the file, this is the number of characters in the file.

ifs.seekg(startPos);

This repositions the stream back to the beginning of the file,

_data.resize(size);

...allocates enough space to store the entire file's content,

ifs.read(_data.data(), size);

and finally reads it again into _data.

T.C.
  • 123,516
  • 14
  • 264
  • 384