scanf on an istream object
Based on @tmyklebu's comment, I implemented streamScanf which wraps istream as FILE* via fopencookie: https://github.com/likan999/codejam/blob/master/Common/StreamScanf.cpp
overriding `istream operator` vs using `sscanf`
Since you are reading from a file, the performance is going to be I/O-bound. Almost no matter what you do in memory, the effect on the overall performance is not going to be detectable.
I would prefer the operator>>
route, because this would let me use the input iterator idiom of C++:
std::istream_iterator<Person> eos;
std::istream_iterator<Person> iit(inputFile);
std::copy(iit, eos, std::back_inserter(person_vector));
or even
std::vector<Person> person_vector(
std::istream_iterator<Person>(inputFile)
, std::istream_iterator<Person>()
);
What is the cin analougus of scanf formatted input?
Use the >> operator to read from cin.
int number1, number2;
std::string text;
char plus, equals;
std::cin >> number1 >> plus >> number2 >> equals >> text;
if (!std::cin.fail() && plus == '+' && equals == '=' && !text.empty())
std::cout << "matched";
It's not as good as scanf because you'd have to verify any literals that were in the scanf string yourself. Doing it with streams will almost certainly be a lot more lines of code than scanf.
I would use scanf.
Skipping expected characters like scanf() with cin
You could create your own stream manipulator. It is fairly easy.
#include <ios>
#include <iostream>
using namespace std;
// skips the number of characters equal to the length of given text
// does not check whether the skipped characters are the same as it
struct skip
{
const char * text;
skip(const char * text) : text(text) {}
};
std::istream & operator >> (std::istream & stream, const skip & x)
{
ios_base::fmtflags f = stream.flags();
stream >> noskipws;
char c;
const char * text = x.text;
while (stream && *text++)
stream >> c;
stream.flags(f);
return stream;
}
int main()
{
int a, b;
cin >> a >> skip(" # ") >> b;
cout << a << ", " << b << endl;
return 0;
}
In C++, how to construct an object referencing to different istream object depending on runtime condition?
You might simply create a function for // work on reader
:
void do_work(LineReader& reader)
{
// work on reader
}
int main(int argc, char *argv[]) {
if (argc > 1) { //read from file
std::ifstream in_f(argv[1]);
if (in_f) {
LineReader reader(in_f);
do_work(reader);
}
}
else { //read from console (standard input)
LineReader reader(std::cin);
do_work(reader);
}
}
or reorganize your code to got reference to std::istream
:
std::istream& get_istream(std::ifstream& in_f, int argc, char* argv[])
{
if (argc > 1) { //read from file
in_f.open(argv[1]);
}
if (in_f) {
return in_f;
} else {
return std::cin;
}
}
int main(int argc, char *argv[]) {
std::ifstream in_f;
LineReader reader(get_istream(in_f, argc, argv));
// work on reader
}
Does cout/cin internally call printf() / scanf() like `new` calls malloc?
The C++ standard does not specify how standard library facilities such as std::cin
and std::cout
are implemented, only how they should behave. Whether the C++ I/O functions call their C counterparts is up to the implementation.
As an example of how the C++ I/O streams can be implemented, we can look at the source code of libstdc++, which is GCC's standard library implementation. The std::basic_istream& operator>>(int&)
function which is the one called when you use std::cin >> x
to read an int calls some functions which call other functions and it eventually reaches this _M_extract_int
function that actually parses the integer. Therefore, libstdc++ does not implement the stream extraction operator for ints using C I/O functions. Still, remember that this is only one example and other standard library implementations may be different.
Using scanf() in C++ programs is faster than using cin?
Here's a quick test of a simple case: a program to read a list of numbers from standard input and XOR all of the numbers.
iostream version:
#include <iostream>
int main(int argc, char **argv) {
int parity = 0;
int x;
while (std::cin >> x)
parity ^= x;
std::cout << parity << std::endl;
return 0;
}
scanf version:
#include <stdio.h>
int main(int argc, char **argv) {
int parity = 0;
int x;
while (1 == scanf("%d", &x))
parity ^= x;
printf("%d\n", parity);
return 0;
}
Results
Using a third program, I generated a text file containing 33,280,276 random numbers. The execution times are:
iostream version: 24.3 seconds
scanf version: 6.4 seconds
Changing the compiler's optimization settings didn't seem to change the results much at all.
Thus: there really is a speed difference.
EDIT: User clyfish points out below that the speed difference is largely due to the iostream I/O functions maintaining synchronization with the C I/O functions. We can turn this off with a call to std::ios::sync_with_stdio(false);
:
#include <iostream>
int main(int argc, char **argv) {
int parity = 0;
int x;
std::ios::sync_with_stdio(false);
while (std::cin >> x)
parity ^= x;
std::cout << parity << std::endl;
return 0;
}
New results:
iostream version: 21.9 seconds
scanf version: 6.8 seconds
iostream with sync_with_stdio(false): 5.5 seconds
C++ iostream wins! It turns out that this internal syncing / flushing is what normally slows down iostream i/o. If we're not mixing stdio and iostream, we can turn it off, and then iostream is fastest.
The code: https://gist.github.com/3845568
Linux, scanf in loop, while stdin already loaded
When you call
scanf(" %s", s);
for the first time, it sets s
to lol
, and returns 1
. When you call it for the second time, there is no further input, so scanf
returns zero without setting your variable. However, your code ignores the return value of scanf
, and prints s
anyway.
Adding a check and a break
should fix this problem:
if (scanf(" %254s", s) != 1) break;
Note the size limiter in the format string, it will prevent scanf
from causing buffer overruns.
Related Topics
Warning: Returning Reference to Temporary
How to Enable Experimental C++11 Concurrency Features in Mingw
What the Heque Is Going on with the Memory Overhead of Std::Deque
Overriding Static Variables When Subclassing
Private Inheritance VS Composition:When to Use Which
How Performing Multiple Matrix Multiplications in Cuda
Creating a New C++ Project in Eclipse Cdt with the Same Settings as Another Project
Using Boost::Iostreams::Mapped_File_Source with Std::Multimap
How to Break When a Specific Exception Type Is Thrown in Gdb
Why Doesn't Delete Destroy Anything
Printf Rounding Behavior for Doubles
Is There a Limit of Stack Size of a Process in Linux
Write a File in a Specific Path in C++
Why Void_T Doesnt Work in Sfinae But Enable_If Does