Whats the C++ equivalent of reading from stdin or a file

A

Adrian

What is the best was to do this in c++. This is going to be used for
unix util that should be able to have input piped to it or file name
spec

#include <stdio.h>

int main(int argc, char *argv[])
{
FILE *fp;
int c;
if(argc==2)
{
fp=fopen(argv[1], "r");
}
else
{
fp=stdin;
}

while((c=fgetc(fp))!=EOF)
{
printf("%c",c);
}
return 0;
}

I assume it has something to do with the underlying buffer and have
tried this but it wont compile.
#include <iostream>
#include <fstream>

int main(int argc, char *argv[])
{
std::ifstream in;

if(argc==2)
{
in.open(argv[0]);
}
else
{
in.rdbuf(std::cin.rdbuf());
}

int c;
while(c==in.get())
{
std::cout << c;
}

return 0;
}
 
V

Victor Bazarov

Adrian said:
What is the best was to do this in c++. This is going to be used for
unix util that should be able to have input piped to it or file name
spec

#include <stdio.h>

int main(int argc, char *argv[])
{
FILE *fp;
int c;
if(argc==2)
{
fp=fopen(argv[1], "r");
}
else
{
fp=stdin;
}

while((c=fgetc(fp))!=EOF)
{
printf("%c",c);
}
return 0;
}

I assume it has something to do with the underlying buffer and have
tried this but it wont compile.
#include <iostream>
#include <fstream>

int main(int argc, char *argv[])
{
std::ifstream in;

if(argc==2)
{
in.open(argv[0]);

You probably meant argv[1]...
}
else
{
in.rdbuf(std::cin.rdbuf());
}

int c;
while(c==in.get())
{
std::cout << c;
}

Wrap the input in a function that takes 'std::istream&'. Then
call this function like so:

if (argc > 1) {
std::ifstream f(argv[1]);
my_input_function(f);
}
else {
my_input_function(cin);
}
return 0;
}

V
 
R

red floyd

Adrian said:
What is the best was to do this in c++. This is going to be used for
unix util that should be able to have input piped to it or file name
spec

#include <stdio.h>

int main(int argc, char *argv[])
{
FILE *fp;
int c;
if(argc==2)
{
fp=fopen(argv[1], "r");
}
else
{
fp=stdin;
}

while((c=fgetc(fp))!=EOF)
{
printf("%c",c);
}
return 0;
}

I assume it has something to do with the underlying buffer and have
tried this but it wont compile.
#include <iostream>
#include <fstream>

int main(int argc, char *argv[])
{
std::ifstream in;

if(argc==2)
{
in.open(argv[0]);
}
else
{
in.rdbuf(std::cin.rdbuf());
}

int c;
while(c==in.get())
{
std::cout << c;
}

return 0;
}


maybe something like:

int main()
{

std::ifstream in;
std::istream* in_p = &std::cin;

if (argc == 2)
{
in.open(argv[1]);
if (in.good())
in_p = &in;
else
in.close();
}

std::istream& is = *in_p;

// yada yada yada
}

}
 
A

Adrian

You probably meant argv[1]...
I did
Wrap the input in a function that takes 'std::istream&'. Then
call this function like so:

Should have thought of that, but to stuck in trying to do it the C way

Thanks - works well.


Adrian
 
K

Kira Yamato

What is the best was to do this in c++. This is going to be used for
unix util that should be able to have input piped to it or file name
spec

#include <stdio.h>

int main(int argc, char *argv[])
{
FILE *fp;
int c;
if(argc==2)
{
fp=fopen(argv[1], "r");
}
else
{
fp=stdin;
}

while((c=fgetc(fp))!=EOF)
{
printf("%c",c);
}
return 0;
}

I assume it has something to do with the underlying buffer and have
tried this but it wont compile.
#include <iostream>
#include <fstream>

int main(int argc, char *argv[])
{
std::ifstream in;

if(argc==2)
{
in.open(argv[0]);
}
else
{
in.rdbuf(std::cin.rdbuf());
}

int c;
while(c==in.get())
{
std::cout << c;
}

return 0;
}

I tried to implement a STL solution below, but it won't compile:

#include <iostream>
#include <fstream>
#include <iterator>
#include <algorithm>

using namespace std;

int main(int argc, char **argv)
{
copy(istream_iterator<char>(argc >= 2 ? ifstream(argv[1]) : cin),
// this line won't compile!
istream_iterator<char>(),
ostream_iterator<char>(cout));

return 0;
}

Does anyone know why?
 
K

Kira Yamato

I tried to implement a STL solution below, but it won't compile:

#include <iostream>
#include <fstream>
#include <iterator>
#include <algorithm>

using namespace std;

int main(int argc, char **argv)
{
copy(istream_iterator<char>(argc >= 2 ? ifstream(argv[1]) : cin),
// this line won't compile!
istream_iterator<char>(),
ostream_iterator<char>(cout));

return 0;
}

Does anyone know why?

FYI, the error messages from g++ are

/usr/include/c++/4.0.0/iosfwd: In copy constructor
'std::basic_ios<char, std::char_traits<char> >::basic_ios(const
std::basic_ios<char, std::char_traits<char> >&)':
/usr/include/c++/4.0.0/bits/ios_base.h:779: error:
'std::ios_base::ios_base(const std::ios_base&)' is private
/usr/include/c++/4.0.0/iosfwd:55: error: within this context
/usr/include/c++/4.0.0/iosfwd: In copy constructor
'std::basic_istream<char, std::char_traits<char> >::basic_istream(const
std::basic_istream<char, std::char_traits<char> >&)':
/usr/include/c++/4.0.0/iosfwd:61: warning: synthesized method
'std::basic_ios<char, std::char_traits<char> >::basic_ios(const
std::basic_ios<char, std::char_traits<char> >&)' first required here
a.cpp: In function 'int main(int, char**)':
a.cpp:10: warning: synthesized method 'std::basic_istream<char,
std::char_traits<char> >::basic_istream(const std::basic_istream<char,
std::char_traits<char> >&)' first required here
a.cpp:10: error: no matching function for call to
'std::istream_iterator<char, char, std::char_traits<char>,
ptrdiff_t>::istream_iterator(std::basic_istream<char,
std::char_traits<char> >)'
/usr/include/c++/4.0.0/bits/stream_iterator.h:70: note: candidates are:
std::istream_iterator<_Tp, _CharT, _Traits,
_Dist>::istream_iterator(const std::istream_iterator<_Tp, _CharT,
_Traits, _Dist>&) [with _Tp = char, _CharT = char, _Traits =
std::char_traits<char>, _Dist = ptrdiff_t]
/usr/include/c++/4.0.0/bits/stream_iterator.h:66: note:
std::istream_iterator<_Tp, _CharT, _Traits,
_Dist>::istream_iterator(std::basic_istream<_CharT, _Traits>&) [with
_Tp = char, _CharT = char, _Traits = std::char_traits<char>, _Dist =
ptrdiff_t]
/usr/include/c++/4.0.0/bits/stream_iterator.h:62: note:
std::istream_iterator<_Tp, _CharT, _Traits, _Dist>::istream_iterator()
[with _Tp = char, _CharT = char, _Traits = std::char_traits<char>,
_Dist = ptrdiff_t]
 
J

James Kanze

What is the best was to do this in c++. This is going to be used for
unix util that should be able to have input piped to it or file name
spec
#include <stdio.h>

int main(int argc, char *argv[])
{
FILE *fp;
int c;
if(argc==2)
{
fp=fopen(argv[1], "r");
}
else
{
fp=stdin;
}
while((c=fgetc(fp))!=EOF)
{
printf("%c",c);
}
return 0;
}

The standard Unix convention allows for more than one filename.
What I usually do is something like:

int
main( int argc, char** argv )
{
Gabi::MultipleFileIStream source( argv + 1, argv + argc ) ;
process( source, std::cout ) ;
return EXIT_SUCCESS ;
}

(The MultipleFileIStream class is available at my site:
kanze.james.neuf.fr. It's actually one of the rare classes
there which hasn't undergone much modification since I put it
there.)

Otherwise, the standard Unix idiom is:

int
main( int argc, char** argv )
{
if ( argc <= 1 ) {
process( std::cin, std::cout ) ;
} else {
for ( int i = 1 ; i < argc ; ++ i ) {
std::ifstream source( argv[ i ] ) ;
if ( ! source ) {
std::cerr << argv[ 0 ] << ": cannot open "
<< argv[ i ] << std::endl ;
} else {
process( source, std::cout ) ;
}
}
}
return EXIT_SUCCESS ;
}

(There's also a singleton class, ProgramStatus, at my site which
can be used to manage the exit status. MultipleFileIStream is
in the IO subsystem, ProgramStatus in the Process subsystem.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top