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

Discussion in 'C Programming' started by Jens Schweikhardt, Feb 1, 2013.

  1. Cal Dershowitz <> wrote
    in <>:

    # 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)
     
    Jens Schweikhardt, Feb 1, 2013
    #1
    1. Advertising

  2. Jens Schweikhardt

    BartC Guest

    "Jens Schweikhardt" <> wrote in message
    news:...
    > Cal Dershowitz <> wrote
    > in <>:
    >
    > # 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
     
    BartC, Feb 1, 2013
    #2
    1. Advertising

  3. "BartC" <> writes:
    > "Jens Schweikhardt" <> wrote in message
    > news:...
    >> Cal Dershowitz <> wrote
    >> in <>:
    >>
    >> # 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) <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"
     
    Keith Thompson, Feb 1, 2013
    #3
  4. Jens Schweikhardt

    BartC Guest

    "Keith Thompson" <> wrote in message
    news:...
    > "BartC" <> 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
     
    BartC, Feb 1, 2013
    #4
  5. Jens Schweikhardt

    James Kuyper Guest

    On 02/01/2013 03:30 PM, BartC wrote:
    > "Keith Thompson" <> wrote in message
    > news:...

    ....
    >> 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, Feb 1, 2013
    #5
  6. Jens Schweikhardt

    James Kuyper Guest

    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.
     
    James Kuyper, Feb 1, 2013
    #6
  7. Jens Schweikhardt

    BartC Guest

    "James Kuyper" <> wrote in message
    news:...
    > 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
     
    BartC, Feb 1, 2013
    #7
  8. "BartC" <> writes:
    > "Keith Thompson" <> wrote in message
    > news:...
    >> "BartC" <> 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) <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"
     
    Keith Thompson, Feb 2, 2013
    #8
  9. Jens Schweikhardt

    BartC Guest

    "Keith Thompson" <> wrote in message
    news:...
    > "BartC" <> 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
     
    BartC, Feb 2, 2013
    #9
  10. Cal Dershowitz <> 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/wg14/www/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) <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"
     
    Keith Thompson, Feb 2, 2013
    #10
  11. Jens Schweikhardt

    Mark Bluemel Guest

    On Feb 2, 11:45 am, "BartC" <> wrote:
    >... 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.)


    You are Stephen Bourne and I claim my 5 curly braces.

    <http://oldhome.schmorp.de/marc/bournegol.html>
     
    Mark Bluemel, Feb 3, 2013
    #11
  12. Jens Schweikhardt

    Jorgen Grahn Guest

    On Sun, 2013-02-03, Mark Bluemel wrote:
    > On Feb 2, 11:45 am, "BartC" <> wrote:

    ....
    >> This is converted to standard C code by a preprocessor, so the issue of C
    >> people not understanding it doesn't arise.

    ....

    > You are Stephen Bourne and I claim my 5 curly braces.
    >
    > <http://oldhome.schmorp.de/marc/bournegol.html>


    /*
    * UNIX shell
    *
    * S. R. Bourne
    * Bell Telephone Laboratories
    *
    */

    #define LOCAL static
    #define PROC extern
    ...
    #define ELIF} else if (
    ...

    Ugh. Wonder what Dennis and the others at Bell Labs had to say about
    that?

    (Oddly, earlier today I edited source code which for some reason uses
    the LOCAL macro just like Bourne did ~40 years ago.)

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
     
    Jorgen Grahn, Feb 3, 2013
    #12
  13. Jens Schweikhardt

    BartC Guest

    "Jorgen Grahn" <> wrote in message
    news:...
    > On Sun, 2013-02-03, Mark Bluemel wrote:


    >> <http://oldhome.schmorp.de/marc/bournegol.html>

    >
    > /*
    > * UNIX shell
    > *
    > * S. R. Bourne
    > * Bell Telephone Laboratories
    > *
    > */
    >
    > #define LOCAL static
    > #define PROC extern
    > ...
    > #define ELIF} else if (
    > ...
    >
    > Ugh. Wonder what Dennis and the others at Bell Labs had to say about
    > that?


    Are these the same people who devised:

    #if
    #elif
    #endif

    for the preprocessor? If so why didn't they use the same style of syntax for
    the language itself? Then they could have got rid of all those annoying
    braces as obviously others have attempted to do!

    --
    Bartc
     
    BartC, Feb 3, 2013
    #13
  14. Jens Schweikhardt

    Shao Miller Guest

    On 2/3/2013 16:51, BartC wrote:
    >
    >
    > "Jorgen Grahn" <> wrote in message
    > news:...
    >> On Sun, 2013-02-03, Mark Bluemel wrote:

    >
    >>> <http://oldhome.schmorp.de/marc/bournegol.html>

    >>
    >> /*
    >> * UNIX shell
    >> *
    >> * S. R. Bourne
    >> * Bell Telephone Laboratories
    >> *
    >> */
    >>
    >> #define LOCAL static
    >> #define PROC extern
    >> ...
    >> #define ELIF} else if (
    >> ...
    >>
    >> Ugh. Wonder what Dennis and the others at Bell Labs had to say about
    >> that?

    >
    > Are these the same people who devised:
    >
    > #if
    > #elif
    > #endif
    >
    > for the preprocessor? If so why didn't they use the same style of syntax
    > for
    > the language itself? Then they could have got rid of all those annoying
    > braces as obviously others have attempted to do!
    >


    I'm sure you're already aware that the braces used with 'if' contribute
    to what's called a "compound statement". I guess that you would
    consider 'endif', 'endwhile' (remember BASIC's "wend"?), 'endswitch',
    'endfor' to be less annoying than the more general compound statement?
    What makes the braces annoying, exactly?

    --
    - Shao Miller
    --
    "Thank you for the kind words; those are the kind of words I like to hear.

    Cheerily," -- Richard Harter
     
    Shao Miller, Feb 3, 2013
    #14
  15. "BartC" <> writes:
    > "Jorgen Grahn" <> wrote in message
    > news:...
    >> On Sun, 2013-02-03, Mark Bluemel wrote:

    >
    >>> <http://oldhome.schmorp.de/marc/bournegol.html>

    >>
    >> /*
    >> * UNIX shell
    >> *
    >> * S. R. Bourne
    >> * Bell Telephone Laboratories
    >> *
    >> */
    >>
    >> #define LOCAL static
    >> #define PROC extern
    >> ...
    >> #define ELIF} else if (
    >> ...
    >>
    >> Ugh. Wonder what Dennis and the others at Bell Labs had to say about
    >> that?

    >
    > Are these the same people who devised:
    >
    > #if
    > #elif
    > #endif
    >
    > for the preprocessor? If so why didn't they use the same style of syntax for
    > the language itself? Then they could have got rid of all those annoying
    > braces as obviously others have attempted to do!


    The answer is simple: the designers of C did not consider the braces to
    be annoying.

    --
    Keith Thompson (The_Other_Keith) <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"
     
    Keith Thompson, Feb 3, 2013
    #15
  16. In article <kemq02$dq2$>,
    Shao Miller <> wrote:
    ....
    >I'm sure you're already aware that the braces used with 'if' contribute
    >to what's called a "compound statement". I guess that you would
    >consider 'endif', 'endwhile' (remember BASIC's "wend"?), 'endswitch',
    >'endfor' to be less annoying than the more general compound statement?
    >What makes the braces annoying, exactly?


    The reason is that when the "end" thingie is named such that it
    unambiguously matches up with control structure beginning thingie, then you
    can easily tell to which thing it is (or should be) matched. I.e., when you
    have FOR/NEXT, IF/ENDIF, WHILE/ENDWHILE (or whatever your particular
    language uses), you don't have to go searching for what it matches to. Yes,
    I know that nowadays we have syntax-checking editors and tools to sort it
    out, but it wasn't always like this.

    Further, if you have an editing slip-of-the-finger (or, in the old days,
    dropped a stack of punched cards), you could then be screwed good.

    So, there is clearly an advantage in having it matched up, instead of all
    the control structures using the same block-delimters.

    --
    Given Bush and his insanely expensive wars (*), that we will be paying for
    for generations to come, the only possible response a sensible person need
    ever give, when a GOPer/TeaBagger says anything about "deficits", is a
    polite snicker.

    (*) Obvious money transfers between the taxpayers and Bush's moneyed
    interests. Someday, we'll actually figure out a way to have a war where the
    money just gets moved around and nobody (on either side) gets injured or
    killed. That will be an accomplishment of which we will be justly proud.
     
    Kenny McCormack, Feb 3, 2013
    #16
  17. Jens Schweikhardt

    BartC Guest

    "Shao Miller" <> wrote in message
    news:kemq02$dq2$...
    > On 2/3/2013 16:51, BartC wrote:


    >> Are these the same people who devised:
    >>
    >> #if
    >> #elif
    >> #endif
    >>
    >> for the preprocessor? If so why didn't they use the same style of syntax
    >> for
    >> the language itself? Then they could have got rid of all those annoying
    >> braces as obviously others have attempted to do!
    >>

    >
    > I'm sure you're already aware that the braces used with 'if' contribute to
    > what's called a "compound statement". I guess that you would consider
    > 'endif', 'endwhile' (remember BASIC's "wend"?), 'endswitch', 'endfor' to
    > be less annoying than the more general compound statement?


    Those forms are a little annoying, but less so than braces!

    Together with 'then', if-statements become:

    if (...) then
    stmt1;
    stmt2;
    ...
    else
    stmt6;
    ...
    endif

    The need for a specific compound statement disappears. You don't need to
    keep adding and removing braces when the number of statements in each block
    changes between 1 and more than 1. The 'else' and 'endif' keywords are more
    likely to be where you might expect it (ie. lined up with 'if'). The 'endif'
    terminator will *always* be there (unlike a closing }). Writing 'endwhile'
    instead of 'endif' would be a more obvious error, and instantly picked up,
    than writing '}' instead of '}' (where the first '}' is supposed to close
    'while', and the second is for closing 'if').

    > What makes the braces annoying, exactly?


    Where do I start?! Let's take the 'else' statement, which appears in these
    different contexts:

    else
    } else
    else {
    } else {

    The trouble is each of those braces isn't positioned as consistently as I've
    shown. It can be difficult to tell at a glance which of these 4 else's
    you're dealing with. That's significant when you have the modify the 1 or N
    statements before or after the else. The fact that you have to be constantly
    aware that you have 1 or N statements is itself annoying!

    There are too many possibilities and styles for placement of a '{' and '}':

    if (... ) {
    stmt;

    if (...)
    { stmt;

    if (...)
    {
    stmt;

    with the additional options of whether they '{' an '}' line up with each
    other, and with 'if' and 'else.

    Then there is no distinction the various '}': the same symbol closes an if,
    for, while, do, switch, and even a function! (Initialisation data too.)
    You just can't tell them apart (see point I made above). With {,} often
    being optional, a missing or superfluous { or } can cause chaos (if you
    can't enlist help from a smart editor).

    Finally, they are just too flimsy a symbol to close something substantial
    such as a large switch or function body.

    --
    Bartc
     
    BartC, Feb 3, 2013
    #17
  18. Jens Schweikhardt

    Shao Miller Guest

    On 2/3/2013 18:43, Kenny McCormack wrote:
    > In article <kemq02$dq2$>,
    > Shao Miller <> wrote:
    > ...
    >> I'm sure you're already aware that the braces used with 'if' contribute
    >> to what's called a "compound statement". I guess that you would
    >> consider 'endif', 'endwhile' (remember BASIC's "wend"?), 'endswitch',
    >> 'endfor' to be less annoying than the more general compound statement?
    >> What makes the braces annoying, exactly?

    >
    > The reason is that when the "end" thingie is named such that it
    > unambiguously matches up with control structure beginning thingie, then you
    > can easily tell to which thing it is (or should be) matched. I.e., when you
    > have FOR/NEXT, IF/ENDIF, WHILE/ENDWHILE (or whatever your particular
    > language uses), you don't have to go searching for what it matches to. Yes,
    > I know that nowadays we have syntax-checking editors and tools to sort it
    > out, but it wasn't always like this.
    >
    > Further, if you have an editing slip-of-the-finger (or, in the old days,
    > dropped a stack of punched cards), you could then be screwed good.
    >
    > So, there is clearly an advantage in having it matched up, instead of all
    > the control structures using the same block-delimters.
    >


    Aha. Yes, I'll admit that in the past, if a compound statement followed
    one of these thingies and lasted for more than 24 lines, and if there
    were multiple such thingies nested, I'd sometimes throw a /* while */
    (or whatever the thingy was) after the closing brace. These days, I try
    to avoid these two criteria combined together and the indentation should
    be sufficient for the eye to line things up at a glance.

    For example, a function might have the majority of its body as a 'while'
    loop with a compound statement. That might be more than 24 lines, but
    any nested 'if's or other loops have to be really short to avoid
    confusion. Then after scrolling down to the bottom of the function,
    it's still obvious that the penultimate closing brace in the function is
    for the 'while' that was at the beginning, without a /* while */ note.

    But I can appreciate the point; thanks.

    void func(void) {
    while (1) {





    while (1) {
    int i = 42;
    break;
    }


















    }
    }

    --
    - Shao Miller
    --
    "Thank you for the kind words; those are the kind of words I like to hear.

    Cheerily," -- Richard Harter
     
    Shao Miller, Feb 4, 2013
    #18
  19. "BartC" <> writes:
    > "Shao Miller" <> wrote in message
    > news:kemq02$dq2$...
    >> On 2/3/2013 16:51, BartC wrote:

    >
    >>> Are these the same people who devised:
    >>>
    >>> #if
    >>> #elif
    >>> #endif
    >>>
    >>> for the preprocessor? If so why didn't they use the same style of syntax
    >>> for
    >>> the language itself? Then they could have got rid of all those annoying
    >>> braces as obviously others have attempted to do!
    >>>

    >>
    >> I'm sure you're already aware that the braces used with 'if' contribute to
    >> what's called a "compound statement". I guess that you would consider
    >> 'endif', 'endwhile' (remember BASIC's "wend"?), 'endswitch', 'endfor' to
    >> be less annoying than the more general compound statement?

    >
    > Those forms are a little annoying, but less so than braces!


    There is no objective measure of annoyance. Braces are annoying *to you*.

    > Together with 'then', if-statements become:
    >
    > if (...) then
    > stmt1;
    > stmt2;
    > ...
    > else
    > stmt6;
    > ...
    > endif
    >
    > The need for a specific compound statement disappears. You don't need to
    > keep adding and removing braces when the number of statements in each block
    > changes between 1 and more than 1. The 'else' and 'endif' keywords are more
    > likely to be where you might expect it (ie. lined up with 'if'). The 'endif'
    > terminator will *always* be there (unlike a closing }). Writing 'endwhile'
    > instead of 'endif' would be a more obvious error, and instantly picked up,
    > than writing '}' instead of '}' (where the first '}' is supposed to close
    > 'while', and the second is for closing 'if').


    Yes, and there are languages that take that approach. The above looks a
    lot like Ada, for example, except that Ada doesn't require parentheses
    on the if condition and uses "end if;" at the end.

    >> What makes the braces annoying, exactly?

    >
    > Where do I start?! Let's take the 'else' statement, which appears in these
    > different contexts:
    >
    > else
    > } else
    > else {
    > } else {


    With a consistent coding style, I haven't found that to be a problem.

    > shown. It can be difficult to tell at a glance which of these 4 else's
    > you're dealing with. That's significant when you have the modify the 1 or N
    > statements before or after the else. The fact that you have to be constantly
    > aware that you have 1 or N statements is itself annoying!
    >
    > There are too many possibilities and styles for placement of a '{' and '}':
    >
    > if (... ) {
    > stmt;
    >
    > if (...)
    > { stmt;
    >
    > if (...)
    > {
    > stmt;
    >
    > with the additional options of whether they '{' an '}' line up with each
    > other, and with 'if' and 'else.


    Yes, there are a lot of different brace placement styles in C. I'll
    even concede that that's a slight drawback of the language. Then again,
    I've seen varying layouts for languages that use begin and end keywords;
    unless you impose a specific layout, there are going to be variations.

    > Then there is no distinction the various '}': the same symbol closes an if,
    > for, while, do, switch, and even a function! (Initialisation data too.)
    > You just can't tell them apart (see point I made above). With {,} often
    > being optional, a missing or superfluous { or } can cause chaos (if you
    > can't enlist help from a smart editor).


    { and } delimit compound statements, nothing else. In:

    if (condition) {
    do_this();
    }
    else {
    do_that();
    }

    *none* of the braces are part of the syntax of the if statement.

    > Finally, they are just too flimsy a symbol to close something substantial
    > such as a large switch or function body.


    Again, with a consistent layout, I haven't found it to be a problem.

    When I learn a new language, I try to learn it in the style of that
    language. I might dislike the layout commonly used for language
    X, but I'd still rather stick to the language-specific conventions
    than try to impose those of my own preferred language. Similarly,
    when I speak French (poorly), I don't insist on pronouncing all
    the consonants at the ends of words or using English word order;
    I have my opinions about the way French is pronounced, but imposing
    those opinions isn't going to do anyone any good.

    How you write your own code is entirely up to you -- but if you'd try
    approaching C on its own terms, rather than trying to impose, say,
    Pascal-like concepts onto C syntax, you just might enjoy the language a
    bit more. And you'd certainly find it easier to share code, and to mix
    it with code written by others.

    --
    Keith Thompson (The_Other_Keith) <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"
     
    Keith Thompson, Feb 4, 2013
    #19
  20. Jens Schweikhardt

    BartC Guest

    "Keith Thompson" <> wrote in message
    news:...
    > "BartC" <> writes:


    >> Then there is no distinction the various '}': the same symbol closes an
    >> if,
    >> for, while, do, switch, and even a function! (Initialisation data too.)
    >> You just can't tell them apart


    > { and } delimit compound statements, nothing else. In:
    >
    > if (condition) {
    > do_this();
    > }
    > else {
    > do_that();
    > }
    >
    > *none* of the braces are part of the syntax of the if statement.


    I think it's possible to look at it either way. And in your example, you're
    acknowledging that the final '}' is part of the if-else statement, by lining
    it up with the else, rather than its matching '{'.

    Some problems with { and } are solved if they are always used, even to
    enclose a single statement (I believe 'Go' has that requirement). But they
    are fiddly to write and I always had problems finding a good home for a
    closing } before an else, where it doesn't look like it's in the way.

    > How you write your own code is entirely up to you -- but if you'd try
    > approaching C on its own terms, rather than trying to impose, say,
    > Pascal-like concepts onto C syntax, you just might enjoy the language a
    > bit more. And you'd certainly find it easier to share code, and to mix
    > it with code written by others.


    I've tried using normal C syntax, and had endless problems and loads of bugs
    because of braces. So here:

    else /* comment */
    stmt1;
    }

    the last } is misaligned making it look like it's closing this else branch.
    However it still compiles without errors. Then I add an extra statement to
    the else branch:

    else /* comment */
    stmt1;
    stmt2;
    }

    Now have to spend time figuring out why it doesn't work as I expected!
    (Although I've spent even more time solving mysterious bugs due to missing a
    '*/' at the end of a comment (it gets matched with the next comment in the
    code, but a bunch of intermediate lines get commented out); that's another
    story however.)

    --
    Bartc
     
    BartC, Feb 4, 2013
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Johann Klammer
    Replies:
    0
    Views:
    209
    Johann Klammer
    Feb 1, 2013
  2. Malcolm McLean
    Replies:
    5
    Views:
    229
    Bart van Ingen Schenau
    Feb 2, 2013
  3. Mark Bluemel
    Replies:
    2
    Views:
    208
    James Kuyper
    Feb 1, 2013
  4. Keith Thompson
    Replies:
    0
    Views:
    202
    Keith Thompson
    Feb 1, 2013
  5. Jorgen Grahn
    Replies:
    0
    Views:
    219
    Jorgen Grahn
    Feb 2, 2013
Loading...

Share This Page