Discussion:
using std::system
(too old to reply)
Edo
2004-10-20 02:02:47 UTC
Permalink
Hello

I need some help please, I have now idea why I am getting the error
error: 'wc' undeclared (first use this function)

#include <cstdlib>
using std::system;

int main(){

//some code
system(wc -l infile > outfile);
}
wc is a shell command to get the line count of a file.

thanks
Alwyn
2004-10-19 09:39:45 UTC
Permalink
Post by Edo
I need some help please, I have now idea why I am getting the error
error: 'wc' undeclared (first use this function)
#include <cstdlib>
using std::system;
int main(){
//some code
system(wc -l infile > outfile);
}
wc is a shell command to get the line count of a file.
'system' takes a 'const char *' parameter. So:
system("wc -l infile > outfile");
should pass the command to the shell to execute.


Alwyn
Edo
2004-10-20 03:53:40 UTC
Permalink
Post by Alwyn
Post by Edo
I need some help please, I have now idea why I am getting the error
error: 'wc' undeclared (first use this function)
#include <cstdlib>
using std::system;
int main(){
//some code
system(wc -l infile > outfile);
}
wc is a shell command to get the line count of a file.
system("wc -l infile > outfile");
should pass the command to the shell to execute.
Alwyn
one more point, infile and outfile are string variables which hold the
actual file path. is this formate above correct, I am not getting it to
work but not sure if there is a problem here.

thanks
Edo
2004-10-20 04:01:16 UTC
Permalink
Post by Edo
Post by Alwyn
Post by Edo
I need some help please, I have now idea why I am getting the error
error: 'wc' undeclared (first use this function)
#include <cstdlib>
using std::system;
int main(){
//some code system(wc -l infile > outfile);
}
wc is a shell command to get the line count of a file.
system("wc -l infile > outfile");
should pass the command to the shell to execute.
Alwyn
one more point, infile and outfile are string variables which hold the
actual file path. is this formate above correct, I am not getting it to
work but not sure if there is a problem here.
thanks
I should rewrite this... I understand what the system rutine takes, but
how can I pass variables as filenames here.

thanks
Alwyn
2004-10-19 11:23:38 UTC
Permalink
Post by Edo
I should rewrite this... I understand what the system rutine takes, but
how can I pass variables as filenames here.
That shouldn't be too difficult.

string infile = "somefile";
string outfile = "someotherfile";

system("wc -l " + infile + " > " + outfile);

should do the trick, I think.


Alwyn
Chris ( Val )
2004-10-19 12:53:49 UTC
Permalink
"Alwyn" <***@mac.com.invalid> wrote in message news:191020041223380836%***@mac.com.invalid...
| In article <cl2sit$3ta$***@news-02.connect.com.au>, Edo
| <***@eddododod.dod> wrote:
| >
| > I should rewrite this... I understand what the system rutine takes, but
| > how can I pass variables as filenames here.
|
| That shouldn't be too difficult.
|
| string infile = "somefile";
| string outfile = "someotherfile";
|
| system("wc -l " + infile + " > " + outfile);
|
| should do the trick, I think.

You said it yourself, it takes 'const char *':

Better to build up the command, I think.

std::string infile = "somefile";
std::string outfile = "someotherfile";

std::string Command( "wc -l " + infile + " > " + outfile );
std::system( Command.c_str() );

To the OP - Be sure to check the return type, as well
as 'errno' for the 'system' function.

Cheers.
Chris Val
Alwyn
2004-10-19 13:09:03 UTC
Permalink
Post by Chris ( Val )
| >
| > I should rewrite this... I understand what the system rutine takes, but
| > how can I pass variables as filenames here.
|
| That shouldn't be too difficult.
|
| string infile = "somefile";
| string outfile = "someotherfile";
|
| system("wc -l " + infile + " > " + outfile);
|
| should do the trick, I think.
Oh, you're quite right! My apologies for that.


Alwyn
Anand Hariharan
2004-10-19 21:20:47 UTC
Permalink
Post by Chris ( Val )
| >
| > I should rewrite this... I understand what the system rutine takes, but
| > how can I pass variables as filenames here.
|
[bunches of good advice pertinent to OP's question snipped]

To the OP -
Why not simply write code that counts the number of lines in 'infile'?
wc may be faster, but having to execute that command, and open the
outfile to read the result, and parse it for the number all is going
to offset the speed-gains.

my $0.02,
- Anand
Edo
2004-10-20 19:00:57 UTC
Permalink
Post by Anand Hariharan
Post by Chris ( Val )
| >
| > I should rewrite this... I understand what the system rutine takes, but
| > how can I pass variables as filenames here.
|
[bunches of good advice pertinent to OP's question snipped]
To the OP -
Why not simply write code that counts the number of lines in 'infile'?
wc may be faster, but having to execute that command, and open the
outfile to read the result, and parse it for the number all is going
to offset the speed-gains.
my $0.02,
- Anand
sure, I tried, it worked only if the file size is with in a limit, but
say you have a file with 2000000 lines or 400Mb the loop to count would
take a loooooooong time.
James Dennett
2004-10-20 03:45:53 UTC
Permalink
Post by Edo
Post by Anand Hariharan
Post by Chris ( Val )
| >
| > I should rewrite this... I understand what the system rutine takes, but
| > how can I pass variables as filenames here.
|
[bunches of good advice pertinent to OP's question snipped]
To the OP -
Why not simply write code that counts the number of lines in 'infile'?
wc may be faster, but having to execute that command, and open the
outfile to read the result, and parse it for the number all is going
to offset the speed-gains.
my $0.02,
- Anand
sure, I tried, it worked only if the file size is with in a limit, but
say you have a file with 2000000 lines or 400Mb the loop to count would
take a loooooooong time.
That's what wc does, and it's generally written in C.

-- James
Karl Heinz Buchegger
2004-10-20 08:43:30 UTC
Permalink
Post by Edo
Post by Anand Hariharan
Post by Chris ( Val )
| >
| > I should rewrite this... I understand what the system rutine takes, but
| > how can I pass variables as filenames here.
|
[bunches of good advice pertinent to OP's question snipped]
To the OP -
Why not simply write code that counts the number of lines in 'infile'?
wc may be faster, but having to execute that command, and open the
outfile to read the result, and parse it for the number all is going
to offset the speed-gains.
my $0.02,
- Anand
sure, I tried, it worked only if the file size is with in a limit, but
say you have a file with 2000000 lines or 400Mb the loop to count would
take a loooooooong time.
Show your code. You must have done something terribly wrong.
One thing is very clear: The whole file needs to be read in order
to determine that count. If your program does it or 'wc' does it
makes no difference. I think it is fair to expect that most of
the used time goes into the actual file reading. Since both programs,
yours or 'wc', need to do the very same thing, it is reasonable to expect
both of them to take nearly the same amount of time.
--
Karl Heinz Buchegger
***@gascad.at
Edo
2004-10-21 04:10:45 UTC
Permalink
Post by Karl Heinz Buchegger
Post by Edo
Post by Anand Hariharan
Post by Chris ( Val )
| >
| > I should rewrite this... I understand what the system rutine takes, but
| > how can I pass variables as filenames here.
|
[bunches of good advice pertinent to OP's question snipped]
To the OP -
Why not simply write code that counts the number of lines in 'infile'?
wc may be faster, but having to execute that command, and open the
outfile to read the result, and parse it for the number all is going
to offset the speed-gains.
my $0.02,
- Anand
sure, I tried, it worked only if the file size is with in a limit, but
say you have a file with 2000000 lines or 400Mb the loop to count would
take a loooooooong time.
Show your code. You must have done something terribly wrong.
#include <fstream>
using std::ifstream;

#include <iostream>
using std::cout;
using std::endl;

int main() {
ifstream is(filename.c_str());
string s;
int count = 0;
while(getline(is, s)) {
++count;
}
cout << count << endl;
}
Chris ( Val )
2004-10-20 13:40:08 UTC
Permalink
"Edo" <***@eddododod.dod> wrote in message news:cl5hgp$967$***@news-02.connect.com.au...
| Karl Heinz Buchegger wrote:
| > Edo wrote:
| >
| >>Anand Hariharan wrote:
| >>
| >>>"Chris \( Val \)" <***@bigpond.com.au> wrote in message news:<***@uni-berlin.de>...
| >>>
| >>>
| >>>>"Alwyn" <***@mac.com.invalid> wrote in message
| >>>>news:191020041223380836%***@mac.com.invalid...
| >>>>| In article <cl2sit$3ta$***@news-02.connect.com.au>, Edo
| >>>>| <***@eddododod.dod> wrote:
| >>>>| >
| >>>>| > I should rewrite this... I understand what the system rutine takes, but
| >>>>| > how can I pass variables as filenames here.
| >>>>|
| >>>
| >>>
| >>>[bunches of good advice pertinent to OP's question snipped]
| >>>
| >>>To the OP -
| >>>Why not simply write code that counts the number of lines in 'infile'?
| >>> wc may be faster, but having to execute that command, and open the
| >>>outfile to read the result, and parse it for the number all is going
| >>>to offset the speed-gains.
| >>>
| >>>my $0.02,
| >>>- Anand
| >>
| >>sure, I tried, it worked only if the file size is with in a limit, but
| >>say you have a file with 2000000 lines or 400Mb the loop to count would
| >>take a loooooooong time.
| >
| >
| > Show your code. You must have done something terribly wrong.
| #include <fstream>
| using std::ifstream;
|
| #include <iostream>
| using std::cout;
| using std::endl;

#include <string>
using std::string;
using std::getline;

| int main() {
| ifstream is(filename.c_str());

if( !is )
return EXIT_FAILURE; // <cstdlib>

| string s;
| int count = 0;
| while(getline(is, s)) {
| ++count;
| }

if( is.eof() )

| cout << count << endl;

else
// Handle failed read...

| }

Btw, there is no need to actually read data into an
buffer, if you only need to count the number of lines:

You will need to include <limits>, then try the following:

std::size_t NrLines( 0 );
while( InFile.ignore( std::numeric_limits<
std::streamsize>::max(), '\n' ) )
{
++NrLines;
}

Cheers.
Chris Val
Karl Heinz Buchegger
2004-10-20 13:49:59 UTC
Permalink
Post by Chris ( Val )
std::size_t NrLines( 0 );
while( InFile.ignore( std::numeric_limits<
std::streamsize>::max(), '\n' ) )
{
++NrLines;
}
Actually that's a good solution.

Edo's version (using getline): 0.9 seconds
my Version (using single character reads): 0.35 seconds
Your version 0.29 seconds

(Same input in all cases, VC++ 6.0, maximize for speed )
--
Karl Heinz Buchegger
***@gascad.at
Chris ( Val )
2004-10-20 14:07:53 UTC
Permalink
"Karl Heinz Buchegger" <***@gascad.at> wrote in message news:***@gascad.at...
| "Chris ( Val )" wrote:
| >
| >
| > You will need to include <limits>, then try the following:
| >
| > std::size_t NrLines( 0 );
| > while( InFile.ignore( std::numeric_limits<
| > std::streamsize>::max(), '\n' ) )
| > {
| > ++NrLines;
| > }
|
| Actually that's a good solution.
|
| Edo's version (using getline): 0.9 seconds
| my Version (using single character reads): 0.35 seconds
| Your version 0.29 seconds
|
| (Same input in all cases, VC++ 6.0, maximize for speed )

Yes - There is certainly no need to use an buffer
for this kind of operation.

Cheers.
Chris Val
Edo
2004-10-20 22:36:45 UTC
Permalink
Post by Chris ( Val )
Btw, there is no need to actually read data into an
std::size_t NrLines( 0 );
while( InFile.ignore( std::numeric_limits<
std::streamsize>::max(), '\n' ) )
{
++NrLines;
}
here is my finding on my system:
"Linux debian 2.6.8 i686 GNU/Linux"
gcc (GCC) 3.3.4 (Debian 1:3.3.4-13)
the presents '\n' at the end of the last line in the file is UNKNOWN
need the correct line_count.

***************Solution 1***************
string s;
while( getline( iFile, s ) ) {
++count;
}
Post by Chris ( Val )
1m48s
correct count


***************Solution 2***************
char c;
while( iFile.read( &c, 1 ) ) {
if( c == '\n' ) {
++count;
}
}
Post by Chris ( Val )
1m37s
correct count


***************Solution 3***************
system( wc -l ... etc )
Post by Chris ( Val )
44s
correct count


***************Solution 4***************
size_t NrLines( 0 ); //#include <limits>
while( is.ignore( numeric_limits<
streamsize>::max(), '\n' ) ) {
NrLines++;
}
Post by Chris ( Val )
44s "44 seconds only" good BUT
incorrect count = correct count + 1

who can I get the correct count from this last solution?
e.g. getting a read True regardless of '\n' at end of line, so maybe I
could play arond with a condition flow.

thanks
Alwyn
2004-10-20 23:13:42 UTC
Permalink
Post by Edo
***************Solution 4***************
size_t NrLines( 0 ); //#include <limits>
while( is.ignore( numeric_limits<
streamsize>::max(), '\n' ) ) {
NrLines++;
}
44s "44 seconds only" good BUT
incorrect count = correct count + 1
who can I get the correct count from this last solution?
e.g. getting a read True regardless of '\n' at end of line, so maybe I
could play arond with a condition flow.
Um, to get the 'correct' count, you only need to subtract one from the
'incorrect' one. :-) :-)

Have you tried the solution involving 'fread' suggested by Bacon in
this thread? It may well be that the functions in the C library are
faster than those in the C++ one. But it really depends on the
implementation.


Alwyn
Edo
2004-10-21 18:33:24 UTC
Permalink
Post by Alwyn
Post by Edo
***************Solution 4***************
size_t NrLines( 0 ); //#include <limits>
while( is.ignore( numeric_limits<
streamsize>::max(), '\n' ) ) {
NrLines++;
}
44s "44 seconds only" good BUT
incorrect count = correct count + 1
who can I get the correct count from this last solution?
e.g. getting a read True regardless of '\n' at end of line, so maybe I
could play arond with a condition flow.
Um, to get the 'correct' count, you only need to subtract one from the
'incorrect' one. :-) :-)
no you can't because the correct count "of '\n'" is UNKNOWN as I indicated.
Post by Alwyn
Have you tried the solution involving 'fread' suggested by Bacon in
this thread?
no, I wish I know how, still crawling my way around c++.
Alwyn
2004-10-21 05:40:22 UTC
Permalink
Post by Edo
Post by Alwyn
Um, to get the 'correct' count, you only need to subtract one from the
'incorrect' one. :-) :-)
no you can't because the correct count "of '\n'" is UNKNOWN as I indicated.
I don't think so. The method involving 'ignore' will execute one more
time than the number of linefeeds. It will execute once, even on an
empty file.
Post by Edo
Post by Alwyn
Have you tried the solution involving 'fread' suggested by Bacon in
this thread?
no, I wish I know how, still crawling my way around c++.
Something like this?

#include <stdio.h>

int countLines(const char *fileName)
{
int lineCount = 0;
const size_t bufferLength = 1024; /* You can make this as big as you
like */
char readBuffer[bufferLength];
FILE *inputFile = fopen(fileName, "r");
if (inputFile == NULL) {
perror("Could not open input file");
return -1;
}
size_t bytesRead = fread(readBuffer, 1, bufferLength, inputFile);
while (bytesRead > 0) {
for (size_t i = 0; i < bytesRead; i++)
if (readBuffer[i] == '\n') lineCount++;
bytesRead = fread(readBuffer, 1, bufferLength, inputFile);
}
return lineCount;
}

I haven't tested the above, but it should give you some idea.


Alwyn
Edo
2004-10-22 17:07:21 UTC
Permalink
Post by Alwyn
Post by Edo
Post by Alwyn
Um, to get the 'correct' count, you only need to subtract one from the
'incorrect' one. :-) :-)
no you can't because the correct count "of '\n'" is UNKNOWN as I indicated.
I don't think so. The method involving 'ignore' will execute one more
time than the number of linefeeds. It will execute once, even on an
empty file.
Post by Edo
Post by Alwyn
Have you tried the solution involving 'fread' suggested by Bacon in
this thread?
no, I wish I know how, still crawling my way around c++.
Something like this?
#include <stdio.h>
int countLines(const char *fileName)
{
int lineCount = 0;
const size_t bufferLength = 1024; /* You can make this as big as you
like */
char readBuffer[bufferLength];
FILE *inputFile = fopen(fileName, "r");
if (inputFile == NULL) {
perror("Could not open input file");
return -1;
}
size_t bytesRead = fread(readBuffer, 1, bufferLength, inputFile);
while (bytesRead > 0) {
for (size_t i = 0; i < bytesRead; i++)
if (readBuffer[i] == '\n') lineCount++;
bytesRead = fread(readBuffer, 1, bufferLength, inputFile);
}
return lineCount;
}
I haven't tested the above, but it should give you some idea.
Alwyn
Thanks for your help with fread().
I got it to work using fread() as suggested by Bacon
the results:

Real 0m39s
User 0m25s
Sys 0m4s
Alwyn
2004-10-20 13:42:21 UTC
Permalink
Post by Edo
#include <fstream>
using std::ifstream;
#include <iostream>
using std::cout;
using std::endl;
int main() {
ifstream is(filename.c_str());
string s;
int count = 0;
while(getline(is, s)) {
++count;
}
cout << count << endl;
}
That won't even compile.

If I were writing this, I wouldn't use IOStreams at all but rather the
must faster C library file-handling functions. I'd read each character
in turn and increment 'count' each time I came across and end-of-line.
I'm pretty sure that's what 'wc' does.


Alwyn
Edmund Bacon
2004-10-20 15:41:17 UTC
Permalink
Post by Alwyn
If I were writing this, I wouldn't use IOStreams at all but rather the
must faster C library file-handling functions. I'd read each character
in turn and increment 'count' each time I came across and end-of-line.
I'm pretty sure that's what 'wc' does.
I think you would do better to fread() a buffer (say 4 k) and then
use strchr(), or walk the input buffer yourself.

comparing a buffer read to individual char read on a 5M file gives the
following times

wc -l 0.015 sec
buff_read 0.015 sec
char_read 0.795 sec
--
Remove -42 for email
Alwyn
2004-10-20 16:37:03 UTC
Permalink
Post by Edmund Bacon
Post by Alwyn
If I were writing this, I wouldn't use IOStreams at all but rather the
must faster C library file-handling functions. I'd read each character
in turn and increment 'count' each time I came across and end-of-line.
I'm pretty sure that's what 'wc' does.
I think you would do better to fread() a buffer (say 4 k) and then
use strchr(), or walk the input buffer yourself.
comparing a buffer read to individual char read on a 5M file gives the
following times
wc -l 0.015 sec
buff_read 0.015 sec
char_read 0.795 sec
That seems plausible enough. If the OP needs speed on large files, he
should investigate which method is fastest on his system. Like others
in this thread, I believe that running 'wc' from 'system' is not
necessarily the best solution.


Alwyn
Karl Heinz Buchegger
2004-10-20 13:44:46 UTC
Permalink
Post by Edo
Post by Karl Heinz Buchegger
Show your code. You must have done something terribly wrong.
#include <fstream>
using std::ifstream;
#include <iostream>
using std::cout;
using std::endl;
int main() {
ifstream is(filename.c_str());
string s;
int count = 0;
while(getline(is, s)) {
++count;
}
cout << count << endl;
}
I see.
(If you post, please compile it prior. The above contains errors).

Anyway. The problem with this code is: it does a lot of things
that are not necessary for the goal: to count the number of lines:

getline enlarges the string as needed for holding a single line of text.
Well. You are not interested in the content of that text line, so it really
is unnecessary to go through the hassle of catanating characters until a whole
line is reached.

This version with an input file of the whole bible (the longest text file I have)
runs in 0.9 seconds when compiled with VC++ 6.0 / release / maximize for speed

Now consider this reading loop:

char c;
while( is.read( &c, 1 ) )
if( c == '\n' )
count++;

Here I just count how many '\n' characters are there in the file. No need
to assemble a whole line in a std::string just to throw that line away.

Same input: 0.3 seconds
3 times as fast then your version.

I haven't tried it, but if this is still to slow I would try to switch to
the C version of file managament using a FILE* variable. On a lot of systems
the C++ stream objects are slower then the C mechanism.

PS: The above isn't entirely correct. Think about the case where the last line
in the file is not terminated with a '\n'.
--
Karl Heinz Buchegger
***@gascad.at
Alwyn
2004-10-20 14:17:45 UTC
Permalink
Post by Karl Heinz Buchegger
char c;
while( is.read( &c, 1 ) )
if( c == '\n' )
count++;
Here I just count how many '\n' characters are there in the file. No need
to assemble a whole line in a std::string just to throw that line away.
<snip>
Post by Karl Heinz Buchegger
PS: The above isn't entirely correct. Think about the case where the last line
in the file is not terminated with a '\n'.
But, for what it's worth, it's exactly what 'wc' does. Make a file with
a single character in it and no newline, and 'wc -l' will tell you that
it contains no lines.


Alwyn
Karl Heinz Buchegger
2004-10-20 14:57:49 UTC
Permalink
Post by Alwyn
Post by Karl Heinz Buchegger
char c;
while( is.read( &c, 1 ) )
if( c == '\n' )
count++;
Here I just count how many '\n' characters are there in the file. No need
to assemble a whole line in a std::string just to throw that line away.
<snip>
Post by Karl Heinz Buchegger
PS: The above isn't entirely correct. Think about the case where the last line
in the file is not terminated with a '\n'.
But, for what it's worth, it's exactly what 'wc' does. Make a file with
a single character in it and no newline, and 'wc -l' will tell you that
it contains no lines.
I guess it is a matter of definition of what constitutes a 'line'.

I am not familiar with 'wc'. All I know is that it does a word count.
But I have no idea what the definition of 'word' is in that context (nor
do I care :-) or what -l does. I have an educated guess, but I don't know
for sure.
--
Karl Heinz Buchegger
***@gascad.at
Alwyn
2004-10-20 18:24:28 UTC
Permalink
Post by Karl Heinz Buchegger
I guess it is a matter of definition of what constitutes a 'line'.
Yes.
Post by Karl Heinz Buchegger
I am not familiar with 'wc'. All I know is that it does a word count.
But I have no idea what the definition of 'word' is in that context (nor
do I care :-) or what -l does. I have an educated guess, but I don't know
for sure.
You are obviously not a Unix user. :-)

However, some of us studied with Kernighan and Plauger's 'Software
Tools' in one hand and Kernighan and Ritchie's 'The C Programming
Language' in the other. 'wc' is a typical example of such a 'software
tool'.


Alwyn
Anand Hariharan
2004-10-20 20:43:48 UTC
Permalink
Post by Karl Heinz Buchegger
I am not familiar with 'wc'. All I know is that it does a word count.
But I have no idea what the definition of 'word' is in that context (nor
do I care :-) or what -l does. I have an educated guess, but I don't know
for sure.
If your curiosity (for what wc is) gets better of you:

http://www.rt.com/man/wc.1.html

- Anand
Alwyn
2004-10-21 07:39:05 UTC
Permalink
Post by Anand Hariharan
Post by Karl Heinz Buchegger
I am not familiar with 'wc'. All I know is that it does a word count.
But I have no idea what the definition of 'word' is in that context (nor
do I care :-) or what -l does. I have an educated guess, but I don't know
for sure.
http://www.rt.com/man/wc.1.html
That wasn't terribly enlightening. Here is an extract for my manual
page:

The wc utility displays the number of lines, words, and bytes contained
in each input file (or standard input, by default) to the standard
out-
put. A line is defined as a string of characters delimited by a
<new-
line> character, and a word is defined as a string of characters
delim-
ited by white space characters. White space characters are the
set of
characters for which the iswspace(3) function returns true. If
more than
one input file is specified, a line of cumulative counts for all
the
files is displayed on a separate line after the output for the
last file.


Alwyn
Anand Hariharan
2004-10-22 14:29:38 UTC
Permalink
Post by Alwyn
Post by Anand Hariharan
http://www.rt.com/man/wc.1.html
That wasn't terribly enlightening. Here is an extract for my manual
To each his own.
Post by Alwyn
The wc utility displays the number of lines, words, and bytes contained
in each input file (or standard input, by default) to the standard
out-
put. A line is defined as a string of characters delimited by a
<new-
line> character, and a word is defined as a string of characters
delim-
ited by white space characters. White space characters are the
set of
characters for which the iswspace(3) function returns true. If
more than
one input file is specified, a line of cumulative counts for all
the
files is displayed on a separate line after the output for the
last file.
The man page I gave a link for (that purports to document the GNU
version of wc) as well as the one on my Solaris box both simply define
wc as ....

<quote>
wc counts the number of bytes, whitespace-separated words, and
newlines in each given file ...
</quote>

Man pages are known for their succinctness.

Like I said, to each his own,
- Anand

Loading...