Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Re: getting perl and C working together in a way that makes sense (http://www.velocityreviews.com/forums/t957195-re-getting-perl-and-c-working-together-in-a-way-that-makes-sense.html)

Jens Schweikhardt 02-01-2013 06:28 PM

Re: getting perl and C working together in a way that makes sense
 
Cal Dershowitz <cal@example.invalid> wrote
in <uoqdne1G4pD08ZbMnZ2dnUVZ_oKdnZ2d@supernews.com> :

# FILE *fp = fopen ("capture3.pl", "r");
# int i = 0;
# while (feof (fp))
# text[i++] = fgetc (fp);

This is a bug. Even when the conditional is negated. The end-of-file
flag is only set *after* an input operation. See the FAQ.

Regards,

Jens
--
Jens Schweikhardt http://www.schweikhardt.net/
SIGSIG -- signature too long (core dumped)

BartC 02-01-2013 07:40 PM

Re: getting perl and C working together in a way that makes sense
 


"Jens Schweikhardt" <usenet@schweikhardt.net> wrote in message
news:an2fr2Fqk5oU1@mid.individual.net...
> Cal Dershowitz <cal@example.invalid> wrote
> in <uoqdne1G4pD08ZbMnZ2dnUVZ_oKdnZ2d@supernews.com> :
>
> # FILE *fp = fopen ("capture3.pl", "r");
> # int i = 0;
> # while (feof (fp))
> # text[i++] = fgetc (fp);
>
> This is a bug. Even when the conditional is negated. The end-of-file
> flag is only set *after* an input operation. See the FAQ.


The number of people getting this wrong suggests that that is how many
expect to use an end-of-file function!

Certainly I do, and I use a special eof() function that works that way. Then
file-reading loops look like this:

fp=fopen(...);
....
while (!eof(fp)) {
....
}
fclose(fp);

It makes the logic far simpler, and I don't even need to know at this point
exactly what I'm going to do in the loop.

--
Bartc


Keith Thompson 02-01-2013 07:57 PM

Re: getting perl and C working together in a way that makes sense
 
"BartC" <bc@freeuk.com> writes:
> "Jens Schweikhardt" <usenet@schweikhardt.net> wrote in message
> news:an2fr2Fqk5oU1@mid.individual.net...
>> Cal Dershowitz <cal@example.invalid> wrote
>> in <uoqdne1G4pD08ZbMnZ2dnUVZ_oKdnZ2d@supernews.com> :
>>
>> # FILE *fp = fopen ("capture3.pl", "r");
>> # int i = 0;
>> # while (feof (fp))
>> # text[i++] = fgetc (fp);
>>
>> This is a bug. Even when the conditional is negated. The end-of-file
>> flag is only set *after* an input operation. See the FAQ.

>
> The number of people getting this wrong suggests that that is how many
> expect to use an end-of-file function!
>
> Certainly I do, and I use a special eof() function that works that way. Then
> file-reading loops look like this:
>
> fp=fopen(...);
> ...
> while (!eof(fp)) {
> ....
> }
> fclose(fp);
>
> It makes the logic far simpler, and I don't even need to know at this point
> exactly what I'm going to do in the loop.


How does your eof() function work? It would have to return true only if
the next input operation is going to fail; how do you determine that?

(I'd recommend using the usual C idioms described in the FAQ rather than
inventing your own, especially if you expect other C programmers to look
at your code.)

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

BartC 02-01-2013 08:30 PM

Re: getting perl and C working together in a way that makes sense
 
"Keith Thompson" <kst-u@mib.org> wrote in message
news:ln8v77x0x4.fsf@nuthaus.mib.org...
> "BartC" <bc@freeuk.com> writes:


>> Certainly I do, and I use a special eof() function that works that way.
>> Then
>> file-reading loops look like this:
>>
>> fp=fopen(...);
>> ...
>> while (!eof(fp)) {
>> ....
>> }
>> fclose(fp);
>>
>> It makes the logic far simpler, and I don't even need to know at this
>> point
>> exactly what I'm going to do in the loop.

>
> How does your eof() function work? It would have to return true only if
> the next input operation is going to fail; how do you determine that?


I used to compare the current position with a file size obtained at file
open, or with the current eof position. This involved lots of fseek and
ftell calls.

Now I use this:

/* return 1 if positioned at eof, otherwise 0 */
int eof(FILE* handle) {
int c;

c=getc(handle);
if (c==EOF) {
return 1;
}
ungetc(c,handle);
return 0;
}

however it only works reliably for simple cases (when not writing to the
file at the same time for example). It's also necessary to understand that
false return value might mean that there is just one byte left to read in
the file. So other checks can be needed.

> (I'd recommend using the usual C idioms described in the FAQ rather than
> inventing your own, especially if you expect other C programmers to look
> at your code.)


Which idiom have I used that isn't standard? The way of using eof()? That's
how I learnt to do it in Pascal.

--
Bartc


James Kuyper 02-01-2013 08:48 PM

Re: getting perl and C working together in a way that makes sense
 
On 02/01/2013 03:30 PM, BartC wrote:
> "Keith Thompson" <kst-u@mib.org> wrote in message
> news:ln8v77x0x4.fsf@nuthaus.mib.org...

....
>> How does your eof() function work? It would have to return true only if
>> the next input operation is going to fail; how do you determine that?

>
> I used to compare the current position with a file size obtained at file
> open, or with the current eof position. This involved lots of fseek and
> ftell calls.
>
> Now I use this:
>
> /* return 1 if positioned at eof, otherwise 0 */
> int eof(FILE* handle) {
> int c;
>
> c=getc(handle);
> if (c==EOF) {
> return 1;
> }


I'd recommend changing that to

return feof(handle);

Otherwise, you're confusing file I/O errors with end-of-file. For some
applications that might be acceptable, but that's certainly not the case
for most of my programs.

That same change also deals correctly with the unlikely but still
possible case that CHAR_MAX>INT_MAX, which would really mess up your
version.

> ungetc(c,handle);
> return 0;
> }


That seems excessively expensive, just so you can pretend you're doing
Pascal-style I/O instead of C I/O. Still, it's probably a lot cheaper
than the approach involving fseek() and ftell().

> however it only works reliably for simple cases (when not writing to the
> file at the same time for example). It's also necessary to understand that
> false return value might mean that there is just one byte left to read in
> the file. So other checks can be needed.
>
>> (I'd recommend using the usual C idioms described in the FAQ rather than
>> inventing your own, especially if you expect other C programmers to look
>> at your code.)

>
> Which idiom have I used that isn't standard? The way of using eof()? That's
> how I learnt to do it in Pascal.


He specified "the usual C idioms". Doing unnecessary I/O just so you can
catch the end of file early is definitely not a "usual C idiom".


James Kuyper 02-01-2013 08:50 PM

Re: getting perl and C working together in a way that makes sense
 
On 02/01/2013 02:40 PM, BartC wrote:
....
> Certainly I do, and I use a special eof() function that works that way. Then
> file-reading loops look like this:
>
> fp=fopen(...);
> ...
> while (!eof(fp)) {
> ....
> }
> fclose(fp);
>
> It makes the logic far simpler, and I don't even need to know at this point
> exactly what I'm going to do in the loop.


How does your logic deal with the possibility of I/O errors when reading
from a stream? The usual C idioms allow you to defer checks of ferror()
until after the loop exits, but it seems to me you'd have to do it
inside your loop.


BartC 02-01-2013 11:10 PM

Re: getting perl and C working together in a way that makes sense
 
"James Kuyper" <jameskuyper@verizon.net> wrote in message
news:510C2A0C.8060901@verizon.net...
> On 02/01/2013 03:30 PM, BartC wrote:


>> ungetc(c,handle);
>> return 0;
>> }

>
> That seems excessively expensive, just so you can pretend you're doing
> Pascal-style I/O instead of C I/O. Still, it's probably a lot cheaper
> than the approach involving fseek() and ftell().

.....
> He specified "the usual C idioms". Doing unnecessary I/O just so you can
> catch the end of file early is definitely not a "usual C idiom".


I'd never thought much about the performance aspect (as this kind of char-
or line-oriented i/o is expected to be slow; when that matters, then I might
just load the entire file in a single operation, for example).

But you're right: a character-at-a-time loop takes twice as long, and a
line-at-a-time loop takes 60% longer, using eof() at the start rather than
feof() at the end (ignoring eof statuses returned by the read functions
themselves).

However, I do like the approach, so it's easier to just overlook this! And
also, in my case, my eof() is used more often inside an interpreter where
the implemented language would naturally write such loops like this:

while not eof(f) do
readln ...
end

So there is not really any scope for C-style error checking at every step
(and the interpreter has its own overheads too, its not worried about slight
differences in file processing!).

(To put things into perspective, C+feof() could read files a line at a time
at 5M lines-per-second, C+eof() at 3M, and that bit of interpreted code at
2.5M.)

--
Bartc


Keith Thompson 02-02-2013 03:32 AM

Re: getting perl and C working together in a way that makes sense
 
"BartC" <bc@freeuk.com> writes:
> "Keith Thompson" <kst-u@mib.org> wrote in message
> news:ln8v77x0x4.fsf@nuthaus.mib.org...
>> "BartC" <bc@freeuk.com> writes:
>>> Certainly I do, and I use a special eof() function that works that way.
>>> Then
>>> file-reading loops look like this:
>>>
>>> fp=fopen(...);
>>> ...
>>> while (!eof(fp)) {
>>> ....
>>> }
>>> fclose(fp);
>>>
>>> It makes the logic far simpler, and I don't even need to know at this
>>> point
>>> exactly what I'm going to do in the loop.

>>
>> How does your eof() function work? It would have to return true only if
>> the next input operation is going to fail; how do you determine that?

>
> I used to compare the current position with a file size obtained at file
> open, or with the current eof position. This involved lots of fseek
> and ftell calls.
>
> Now I use this:
>
> /* return 1 if positioned at eof, otherwise 0 */
> int eof(FILE* handle) {
> int c;
>
> c=getc(handle);
> if (c==EOF) {
> return 1;
> }
> ungetc(c,handle);
> return 0;
> }
>
> however it only works reliably for simple cases (when not writing to the
> file at the same time for example). It's also necessary to understand that
> false return value might mean that there is just one byte left to read in
> the file. So other checks can be needed.


It could also cause problems for interactive use.

>> (I'd recommend using the usual C idioms described in the FAQ rather than
>> inventing your own, especially if you expect other C programmers to look
>> at your code.)

>
> Which idiom have I used that isn't standard? The way of using eof()? That's
> how I learnt to do it in Pascal.


C is not Pascal, and C's I/O functions work quite differently than
Pascal's.

C's feof() function doesn't tell you that the next input oeration will
fail; it tells you that the previous one failed.

The usual idiom for reading a character at a time in C is:

FILE *handle;
...
int c;
while ((c = getc(handle) != EOF) {
/* c contains a character read from the file */
}

getc() returns either EOF (typically -1) to indicate that it wasn't able
to read a character, or the character it just read, treated as an
unsigned char and converted to int. It's a form of in-band signalling.
(The macro EOF is not to be confused with the feof() function.)

*After* getc() has returned EOF, you can call feof() and/or ferror() to
determine *why* it returned EOF.

Defining your own eof() function that works like Pascal's is similar to
defining your own macros like:

#define BEGIN {
#define END }
#define IF if(
#define THEN ) {

and so forth. Both make your code more difficult to read for people who
know C -- and not that much easier for people who know Pascal.

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

BartC 02-02-2013 11:45 AM

Re: getting perl and C working together in a way that makes sense
 
"Keith Thompson" <kst-u@mib.org> wrote in message
news:lnvcabv198.fsf@nuthaus.mib.org...
> "BartC" <bc@freeuk.com> writes:


>> int eof(FILE* handle) {
>> int c;
>>
>> c=getc(handle);
>> if (c==EOF) {
>> return 1;
>> }
>> ungetc(c,handle);
>> return 0;
>> }
>>


>> Which idiom have I used that isn't standard? The way of using eof()?
>> That's
>> how I learnt to do it in Pascal.

>
> C is not Pascal, and C's I/O functions work quite differently than
> Pascal's.


> C's feof() function doesn't tell you that the next input oeration will
> fail; it tells you that the previous one failed.


> The usual idiom for reading a character at a time in C is:


Yes, I know this stuff. But I sometimes want to deal with files in a quick,
informal manner, and and an eof() function that tells you if there's more
input waiting is useful for that purpose.

I'm superimposing a slightly higher level of file-handling than is provided
by the standard file functions (of which eof() is part); what's wrong with
that, or aren't people allowed to build libraries on top of C anymore? Next
you'll be telling us to stick to the standard string library!

> Defining your own eof() function that works like Pascal's is similar to
> defining your own macros like:
>
> #define BEGIN {
> #define END }
> #define IF if(
> #define THEN ) {
>
> and so forth. Both make your code more difficult to read for people who
> know C -- and not that much easier for people who know Pascal.


(Strange you should say that, because I now write my C code in just such a
manner. The above function in reality looks like the following (you may wish
to avert your eyes):

global function int eof(FILE* handle) =
int c;

c:=getc(handle);
if (c=EOF) then
return 1;
fi
ungetc(c,handle);
return 0;
end

This is converted to standard C code by a preprocessor, so the issue of C
people not understanding it doesn't arise. And the preprocessor is a small
program that uses a while-loop with, obviously, an eof() test at the
beginning! This transparent conversion to C only adds some 3% to compilation
times, so the extra overheads of such an eof are not a problem in this
case.)

--
Bartc


Keith Thompson 02-02-2013 08:22 PM

Re: getting perl and C working together in a way that makes sense
 
Cal Dershowitz <cal@example.invalid> writes:
[...]
> I'm amazed at how it always seems to begin here every time my life
> cruises through the lingua franca.
>
> Gosh, what I have right now just looks awful, but I think it's enough
> of a nifty idea to pursue it to the point of seeing what output will
> look like, with this very-flawed way of approaching interop.
>
> Now that I see this compile, I'm starting to wonder if there might be
> a less-tortured way of doing this.
>
> Say that *s represents a pointer to the beginning of code that will
> run in a C-compliant fashion. That entails that space for this string
> must already have been malloced. In this case, it will be a perl
> script. It can all be a one-liner.
>
> How do you use the stipulation that the OS is written in contemporary
> ISO C to fire this up using a system call?


I'm having difficulty understand what you're saying here.

I *think* what you're saying is that s points to a string containing
Perl code. For example:

char *s = "print 'hello';";

(s is a pointer to char, but a char* that points to the first
character of a string is said to be a pointer to the string.)

There should be no reason for you to care what language the OS is
written in.

So in the context of your program, where does this string of Perl
code come from? If it's in a file, why can't you just execute
that file as a Perl script? I can't think of any reason to have
Perl source code as the contents of a C string (outside the Perl
interpreter itself, which happens to be written in C -- but again,
there's no reason you should need to care about that).

C provides the standard function system(), which invokes an external
program. It's defined in section 7.22.4.8 of the latest C standard
(draft at http://www.open-std.org/jtc1/sc22/wg...docs/n1570.pdf).

If you need more control than system() gives you, you'll need
something specific to your OS, and you should probably ask in a
forum that deals with your OS rather than with the C language.

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"


All times are GMT. The time now is 04:21 PM.

Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57