Reading a data file

Discussion in 'C Programming' started by W. eWatson, Jul 19, 2013.

  1. W. eWatson

    blmblm Guest

    Ah, that explains ....

    I was going to strongly recommend that the OP make a habit of
    compiling with flags to enable optional warnings ("-Wall -pedantic"
    is what I usually use, that being a reasonable compromise for
    me between "all possible warnings" and "too much to type" [*]),
    in which case gcc would have produced the warning message

    qq.c:32: warning: implicit declaration of function 'strtok'

    which is at least a clue about the real problem.

    In the course of confirming that my advice wasn't going to be total
    nonsense, I observed that just "-std=c99" produces the warning about
    implicit declaration. Which now makes sense!

    Be that as it may, I still vote for compiling with at least a minimal
    set of "show me more warnings" flags -- not infrequently (as in this
    case) the extra warnings are clues about behavior that otherwise could
    be puzzling.

    [*] Yes, yes, makefiles, scripts, aliases .... Sometimes it's simpler
    to just go with what one is willing to type. IMO.
     
    blmblm, Jul 21, 2013
    #41
    1. Advertisements

  2. (snip)
    Seems to me that some went too far with Y2K. There are many cases where
    the year modulo 100 is close enough. (There was a story about someone
    at 104 years old being sent a kindergarten application, but that should
    be rare.)

    With the first standard in 1990, C has a ways to go before the
    year modulo 100 isn't good enough.

    Fortran started out (first IBM document published) in 1956, and the
    first standard in 1966. It will be interesting to see if it survives
    for 100 years.

    -- glen
     
    glen herrmannsfeldt, Jul 21, 2013
    #42
    1. Advertisements

  3. You not infrequently need the counter outside of the loop.

    for(i=0;i<N;i++)
    if(!array.field)
    break;

    if(i < N)
    processnullvalue(&array);
    else
    nullvaluenotfound();
     
    Malcolm McLean, Jul 22, 2013
    #43
  4. W. eWatson

    James Kuyper Guest



    I've written code like that many times, but I have to disagree with your
    description of it as "not infrequent". For every loop like that which
    I've written, I've written dozens of other loops where the loop variable
    was used exclusively in the loop, where it would have been a logic error
    to make any reference to that variable outside the loop. I like having
    the compiler remind me when I've written illogical code - I can't count
    on catching all such errors myself.

    And please don't bring up the hoary old argument about some idiots
    assuming that, because the compiler can catch some errors, it must be
    capable of catching all errors, and therefore not bothering to do their
    own search for errors. Such idiots are quite capable of coming up with
    other reasons for not bothering to search. Giving the compiler less
    information so it won't be able to detect such problems will merely
    leave such problems undetected in their code - it won't force such
    idiots to actually search for their errors.

    Having the option of declaring a loop variable in the for() statement
    doesn't disable the ability to declare it outside the statement, and
    therefore doesn't count as a valid argument against allowing such
    declarations.
     
    James Kuyper, Jul 22, 2013
    #44
  5. (snip, someone wrote)

    How much is "frequent" and how much "not infrequent"?
    Maybe not in C, but I believe it isn't allowed in Java, and likely
    for the reason you mention above. It is too easy to have undetected
    logic errors when you allow both. You can, of course, use a
    different variable. If you want the compiler to help detect them,
    then you can't allow both.

    -- glen
     
    glen herrmannsfeldt, Jul 22, 2013
    #45
  6. W. eWatson

    James Kuyper Guest



    I've no hard statistics, but as implied below, I think that less than
    10% of my own loops look like that; possibly less than 5%. Of course,
    what counts as "frequent", "infrequent", or "not infrequent" depends
    upon the context. In this context, "not frequent" would have to be
    common enough to justify not allowing declaration of the variable in the
    first part of a for() statement. In my opinion, 10% is way too low to
    justify disallowing that; 95% might be high enough.
    My opinion would be quite different if allowing the loop variable to be
    declared there would have the consequence of disallowing it from being
    declared elsewhere - but that's not the case here.
    I'm not very familiar with Java, but
    <http://en.wikipedia.org/wiki/Java_syntax#for_loop> doesn't say anything
    to suggest a difference from C in that respect. What's missing from that
    description?
     
    James Kuyper, Jul 22, 2013
    #46
  7. W. eWatson

    Eric Sosman Guest

    <off-topic> Your beliefs about Java are at odds with
    the facts. </off-topic>
     
    Eric Sosman, Jul 22, 2013
    #47
  8. W. eWatson

    blmblm Guest

    Quite. (I was all set to reply to the preceding post, but you sort
    of beat me to it. But maybe saying a bit more, especially since
    you've helpfully marked it "OT" .... ) Example:

    public class QQ {
    public static void main(String[] args) {
    int i;
    for (i = 0; i < 10; ++i) System.out.println(i);
    System.out.println("ending i "+i);
    }
    }

    I was a little surprised that this compiled, since normally Java
    won't let you declare a local variable without assigning it a value.
    (That may be what Glen was thinking of?) But apparently the actual
    rule is that the compiler has to be able to figure out that every
    variable gets assigned a value before used, and in this case I
    guess it can figure that out.
     
    blmblm, Jul 22, 2013
    #48
  9. (snip, I wrote)
    public class forloop {
    public static void main(String[] args) {
    int i;
    for(int i=0;i<10;i++) System.exit(i);
    }
    }

    forloop.java:4: i is already defined in main(java.lang.String[])
    for(int i=0;i<10;i++) System.exit(i);
    ^
    1 error

    I don't know where it is in the language reference, but the
    compiler doesn't like it...

    -- glen
     
    glen herrmannsfeldt, Jul 22, 2013
    #49
  10. (snip, I wrote)
    While you have to be careful, I usually consider comparisons of
    features with other languages a reasonable point of discussion.
    Now, put int in the for statement, leaving int i outside, and
    it will fail to compile.

    -- glen
     
    glen herrmannsfeldt, Jul 22, 2013
    #50
  11. W. eWatson

    Eric Sosman Guest

    <off-topic> It will if you s/(int/(/. </off-topic>
     
    Eric Sosman, Jul 22, 2013
    #51
  12. W. eWatson

    James Kuyper Guest

    On 07/22/2013 05:27 PM, glen herrmannsfeldt wrote:
    ....

    That's not what I was referring to. I was saying that allowing

    // Example 1
    for(int i=0; i<N; i++) { /* Loop body */}

    does not mean that you have to prohibit

    // Example 2
    int i;
    for(i=0; i<N; i++) { /* Loop body with early exit */}
    if(i < N)
    {
    // Deal with early exit.
    }

    Therefore, the need to occasionally write code like Example 2 does not
    count as an argument against allowing Example 1.
     
    James Kuyper, Jul 22, 2013
    #52
  13. W. eWatson

    blmblm Guest

    True, while the equivalent(?) C (below) does. However, apparently
    gcc at least creates two distinct variables i, one valid inside
    the scope of the loop and one valid outside. Now *that* strikes
    me as asking for trouble. That the Java compiler just won't let
    you have the two declarations seems not-bad to me. ?

    #include <stdio.h>
    int main(void) {
    int i=0;
    for (int i = 0; i < 10; ++i) { printf("%d\n",i); }
    printf("%d\n",i);
    return 0;
    }
     
    blmblm, Jul 22, 2013
    #53
  14. (snip, I wrote)
    OK, I missed what you meant.
    There might be some langauges that allow a new scope nesting level,
    which doesn't help avoid the problem.

    -- glen
     
    glen herrmannsfeldt, Jul 22, 2013
    #54
  15. The two "i" variables are declared in different scopes. It's
    fundamentally no different than this:

    #include <stdio.h>
    int main(void) {
    int i = 0;
    printf("i = %d\n", i);
    {
    int i = 1;
    printf("i = %d\n", i);
    }
    printf("i = %d\n", i);
    }

    which prints:

    i = 0
    i = 1
    i = 0

    In general, an identifier declared in an inner scope hides the same
    identifier declared in an outer scope.

    I suppose you could have a rule forbidding that, but it would break
    existing code.
     
    Keith Thompson, Jul 23, 2013
    #55
  16. W. eWatson

    Tim Rentsch Guest

    The last statement is obviously false.
     
    Tim Rentsch, Jul 23, 2013
    #56
  17. "Not infrequent" means "often enough to be worth considering providing
    nice syntax / structures for", as opposed to simply making possible.

    If we allow for(int i=0;i<N;i++) it's only a good move if virtually
    every for loop follows this style. So now you could have an advantage,
    for(i=0;i<N;i++) tells us that i will be used outside of the loop body.
    However you'd need the compiler to enforce that by warning if it
    wasn't the case, which would break too much legacy code.

    But consider this:

    /* count the number of space characters before the quote */
    int count_pre_quote_spaces(char *str)
    {
    int i;
    int N;
    int answer = 0;

    for(i=0;str;i++)
    if(str == '\'')
    break;
    if(!str)
    return -1;
    N = i;
    for(int i=0; i<N;i++)
    if(str == ' ')
    answer++;
    return answer;
    }

    what do you reckon?
     
    Malcolm McLean, Jul 23, 2013
    #57
  18. W. eWatson

    Jorgen Grahn Guest

    Sure. You (and the OP, I hope) can see my posting as an addendum
    to your solution; something to consider when the fixed-filename
    version is already working.

    /Jorgen
     
    Jorgen Grahn, Jul 23, 2013
    #58
  19. W. eWatson

    James Kuyper Guest

    But there is already perfectly good syntax for that, and allowing
    declarations in the first part of a for() statement does nothing to
    interfere with that.
    That makes no sense to me. Do you normally argue that, just because
    something is allowed, it should be done whenever possible? If so, I'd
    like to point out that you're allowed to send me $1000.

    It should be used when it expresses what your code needs to do, and it
    should not be used when it doesn't. It's no different in that regard
    than ++i: if ++i means what you want to say, use ++i; if what you
    actually want to say is i+1, don't use ++i.

    The general rule I follow is to declare every identifier with the
    smallest scope that allows it to do what that identifier needs to do,
    (without using an extra set of curly brackets for the sole purpose of
    giving it a tighter scope). That minimizes the opportunities for
    different variables to conflict with each other.

    Taking advantage of the fact that we are allowed to declare a variable
    in the first part of a for() statement is something that should be done
    only when declaring it in that position gives it that the right scope.
    Such a warning should be optional, and turned off by default, and I
    wouldn't bother turning it on. But the standard allows compilers to warn
    about anything they want to, such as the fact that you failed to use
    obscene words as variable names - only mandatory diagnostics are worth
    talking about in the context of portable code.


    I reckon that the C language allows an inner scope declaration to hide
    an outer scope declaration, which is useful, because it makes it easier
    to move code from one context to another without accidentally breaking
    it - but that it is rarely, if ever, a good idea to deliberately write
    code that depends upon that fact.
     
    James Kuyper, Jul 23, 2013
    #59
  20. Not to put words in his mouth, but I think there's a reasonable point to
    be made that if you could be sure that (a) *not* declaring the loop variable
    in the for statement reliably implied that said variable *would* be used
    outside of the loop, that would be a more valuable piece of information
    to a reader of the code than that (b) declaring it in the loop means
    it's only used in the loop. In my opinion, (b) has value, so the two
    ideas are not in conflict.

    Yes, (a) can't be added to the language, but if a compiler provided a(n
    optional) warning to detect it, I can imagine it being a thing some
    reasonable people would want to turn on.
    This sounds to be fully in agreement with what Malcolm McLean actually
    said; the only difference is that he'd like to enforce it more strongly
    in this particular case.
    The code is portable (and standards-compliant) anyway, and nobody's
    suggesting adding the must-declare-inside-the-"for"-if-possible to the
    language. As far as I can see, the only issue left is whether including
    it as an optional feature would benefit a compiler's quality of
    implementation. Is there really anything else at question here?
     
    Lowell Gilbert, Jul 23, 2013
    #60
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.