-3

I want to take several integers as input until newline ('\n', not EOF) occurs then put them into an array or a vector. How can I do that using keywords that are exclusive to C++?

Meraj al Maksud
  • 1,528
  • 2
  • 22
  • 36
  • 3
    Model your code after answer 1 option 2 of [Read file line by line](https://stackoverflow.com/questions/7868936/read-file-line-by-line) – user4581301 Jul 06 '18 at 17:49
  • `#include #include ` and then `std::scanf ` and `std::printf` or `std::cin` and `std::cout` – Victor Gubin Jul 06 '18 at 17:50
  • When I see this code I want to provide 10,016 integers before the newline. Be careful of buffer overflows. – Daniel H Jul 06 '18 at 18:04
  • Can you [edit] your question to clarify the priorities for _memory usage_, _speed_, and _similarity for edge cases_? Different languages prioritize those things differently and the posted answers are all assuming different priorities for those details. – Drew Dormann Jul 06 '18 at 18:13
  • I have edited the question. Is the question now clear enough to have the **closed** flag removed? – Meraj al Maksud Jun 01 '19 at 09:16

3 Answers3

5

Here is something that uses more C++ functions and data structures:

#include <string>
#include <sstream>
#include <iostream>

int main()
{
  std::vector<int> database;
  std::string text_line;
  std::getline(std::cin, text_line);
  std::istringstream input_stream(text_line);
  int value;
  while (input_stream >> value)
  {
    database.push_back(value);
  }
// Edit 1: printing the vector
  for (auto&& v:database)
  {
     std::cout << v << " ";
  }
  std::cout << "\n";
  return EXIT_SUCCESS;
}

In the above program, a line of text (i.e. text until newline), is read into the string variable.

The string is then treated as an input stream and all the numbers in the string are placed into the vector.

The string helps to limit to only numbers input from the line of text.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
  • Need to print out the list of numbers. – Richard Chambers Jul 06 '18 at 18:08
  • 2
    This double-buffers the input; it could easily use 5x the memory of the C version. – Yakk - Adam Nevraumont Jul 06 '18 at 18:08
  • 4
    There was no efficiency requirement, only to write this in "C++ Style". Usually, efficiency is only applied when necessary. In this case, waiting for User input outweighs any double buffering execution. Unless a User types in a *lot* of data, there is no need to worry about the extra memory consumption. – Thomas Matthews Jul 06 '18 at 18:24
  • 2
    @ThomasMatthews There is premature optimization and premature pessimization. And cin isn't "the user", it is the input stream for your program. Double buffering data needlessly is premature pessimization, not a microoptimization. And you are doing it, allocating possible gigabytes of extra memory... in order to detect a `\n`. And even without that, your program is 5x slower because you forgot to turn off iostream sync with C library. I'm just saying that if the C++ way is to use 5x the memory and 5x the time to solve a simple problem, just use Java. Or write C++ that doesn't suck. – Yakk - Adam Nevraumont Jul 06 '18 at 18:29
  • @ThomasMatthews The original code eats the non-integer character that follows each integer, and then stops reading when it reaches EOL. Your code is not eating the non-integer characters, which will cause `operator>>` to fail prematurely. – Remy Lebeau Jul 06 '18 at 23:28
4
int main(){
  std::vector<int> arr;

  do {
    int v;
    char sep;
    auto code = std::scanf("%d%c", &v, &sep);
    if (code >= 1)
      arr.push_back(v);
    if (code < 2 || sep == '\n')
      break;
  } while(true);

  for (auto&& v:arr)
    std::printf("%d ", v);
}

I am using std::scanf and std::printf because the problem is specified in terms of them, and they are quite reasonable io functions if used properly. They aren't the safest, so I wouldn't use them for brand new code in a real new project, but I would also be tempted not to use cin and cout either.

Naive replacement with std::stream based IO will result in a 5x slowdown. Naive line-based parsing causes 5x increase in memory usage.

More careful std::stream based IO can remove that performance hit, if you sweep your entire program to never use printf or scanf again anywhere in its entire run.

But because you specified the probem in terms of scanf/printf you'd have to audit how the std::cin >> x parses integers by reading a document like this: https://en.cppreference.com/w/cpp/locale/num_get/get

Then you'd have to determine (A) is there any difference, and (B) does it matter. Reading integers from a text stream is full of many tiny complicated decisions; unless much care it taken, two versions will not act exactly the same.

(Do you treat 010 as 8 or 10? Do you handle 0xFF? How about -0xFF? Is 3.2 two integers separated by a . or a floating point that is rounded when parsed as an integer? How about 3,2 -- is that a , as a decimal separator? What characters are whitespace, and which are not? Where do you store the state that indicated what locale you are in?)

Good C++ that is updating C code should replace the parts of the C code that are fundamentally broken -- like your fixed size buffer -- and it up. It shouldn't replace the low-level IO routines used unless absolutely required.

And that is what I did.

If you really want to use cin, can you guarantee without checking that an input of:

\t0x123 012 \t33 \n-3.-0x33\n

would result in the same integers loaded in both the scanf and cin version? I don't know personally.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
1

Here is what I would consider a simple C++ equivalent. It is not identical in functionality, but it shows the general C++ way:

#include <iostream>
#include <vector>

int main(){
    std::vector<int> arr;
    int temp;
    while(std::cin >> temp)
        arr.push_back(temp);
    for(auto i : arr)
        std::cout << i << " ";
    std::cout << '\n';
}

In this case input must end with a an EOF signal from the user. Typically generated with CTRL+D (for *nix) or CTRL+Z (for Windows).

wally
  • 10,717
  • 5
  • 39
  • 72