I'm pretty sure I have some out of control Undefined Behavior

Discussion in 'C Programming' started by Chad, Apr 5, 2006.

  1. Chad

    Chad Guest

    The input file is:
    Params
    1
    2
    3
    4
    5
    6,7
    Data
    1,1
    2,2
    3,2
    4,4
    5,6

    The output should be
    1
    2
    3
    4
    5
    6,7
    1,1
    2,2
    3,2
    4,4
    5,6

    Okay, with that, here is what I attempted, and what my computer
    produced.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    #define MAXLINE 10

    int main(void)
    {

    char buff[MAXLINE];

    char temp1[] = "Params\n";
    char temp2[] = "Data\n";

    FILE *inFile;

    inFile = fopen("LAND2.txt", "r");
    if (inFile != NULL)
    {
    while (fgets(buff, sizeof(buff), inFile) != NULL) {
    if(strncmp(buff,temp1,sizeof(buff)) != 0)
    fputs(buff, stdout);

    if(strncmp(buff,temp2,sizeof(buff)) != 0)
    fputs(buff, stdout);
    }
    }

    if(feof) {
    return 0;
    }

    fclose (inFile);

    return 0;
    }

    Output

    $gcc -Wall lunar.c -o lunar
    $./lunar
    Params
    1
    1
    2
    2
    3
    3
    4
    4
    5
    5
    6,7
    6,7
    Data
    1,1
    1,1
    2,2
    2,2
    3,2
    3,2
    4,4
    4,4
    5,6
    5,6


    $

    Can someone enlighten me on where I'm screwing this up.

    Chad
     
    Chad, Apr 5, 2006
    #1
    1. Advertisements

  2. strcmp and strncmp return 0 if the strings being tested compare equal.
    This may seem a little backwards until you realize that strcmp stands
    for "string compare" not "string equal". The strcmp functions don't
    just compare strings for equality, they also let you know which string
    is "greater".
    In this instance you are printing the input string when it *doesn't*
    match "Params\n".
    The string will be printed again (or for the first time if it was
    "Params\n") if it doesn't match "Data\n".

    To do what you seem to be trying to accomplish, one if statement will
    suffice:
    if (strncmp(buff, temp1, sizeof(buff)) && strncmp(buff, temp2,
    sizeof(buff)))
    fputs(buff, stdout);
    This will print buff once when it doesn't match either strings, i.e.
    when both strncmp calls return non-zero.
    What are you trying to accomplish here? Since feof will evaluate to
    the address of the feof() function which is not a null pointer, you
    will always return here. I assume you meant to actually call the
    function but I don't know what the point of that would be in your
    example.
    Did you really? If you had, gcc would have complained about the "if
    (feof)" incident. Did you ignore the warning or did you not copy/paste
    your code correctly?
    Robert Gamble
     
    Robert Gamble, Apr 5, 2006
    #2
    1. Advertisements

  3. Chad

    Chad Guest

    gcc didn't complain. And I quote the ENTIRE output

    $gcc --version
    gcc (GCC) 3.3.3 (SuSE Linux)
    Copyright (C) 2003 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions. There is
    NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
    PURPOSE.

    $gcc -Wall lunar.c -o lunar

    Chad
     
    Chad, Apr 5, 2006
    #3
  4. Chad

    Chad Guest

    I probably shouldn't have put in feof(). The problem is that I still
    have no REAL understanding of the function. I would ask more about it,
    but I need to figure out EXACTLY the part of feof() I'm not fully
    grasping posting questions about it.

    Chad
     
    Chad, Apr 5, 2006
    #4
  5. Chad

    Chad Guest

    I probably shouldn't have put in feof(). The problem is that I still
    have no REAL understanding of the function. I would ask more about it,
    but I need to figure out EXACTLY the part of feof() I'm not fully
    grasping posting before questions about it.

    Chad
     
    Chad, Apr 5, 2006
    #5
  6. 2003? That's ancient ;)
    The newer versions (4.0.x) will complain.

    Robert Gamble
     
    Robert Gamble, Apr 5, 2006
    #6
  7. I'm not sure why you're using strncmp() here rather than strcmp().
    Both arguments are strings (i.e., character arrays properly terminated
    by '\0').

    Your logic here is:

    For each line
    Print the line if it's not equal to "Params\n".
    Print the line if it's not equal to "Data\n".

    That's your problem.
    What is the purpose of the above test?

    The feof function expects a single argument of type FILE*. The only
    thing in your program it would make sense to pass to it is inFile,
    i.e., "feof(inFile)". With no parentheses, you don't even have a
    function call; the name of a function is converted to a pointer to the
    function, which you then evaluate as a condition; any non-null pointer
    evaluates as true.

    But even if you corrected it to "if (feof(inFile)", I'm not sure what
    the purpose is -- unless you're using it to check whether the fopen()
    call succeeded. (I'm actually not sure what feof() does on a closed
    file.)

    It would be better to associate any error handling directly with the
    result of fopen(), such as:

    inFile = fopen("LAND2.txt", "r");
    if (inFile == NULL) {
    fprintf(stderr, "fopen failed for LAND2.txt\n");
    exit(EXIT_FAILURE);
    }

    [snip]
     
    Keith Thompson, Apr 5, 2006
    #7
  8. Chad

    Chad Guest

    Why wouldn't something like

    if feof(inFile)

    not make sense to check if fopen() call succeeded in this case?

    Chad
     
    Chad, Apr 5, 2006
    #8
  9. The first thing to understand about feof() is that it's rarely
    necessary to use it. Each input function returns a result that tells
    you whether it succeeded or not. An input function can fail either
    because of an error or because you've reached the end of the input
    file (or, in some cases, because the input doesn't match the expected
    format). (Once you've detected the failure, you can *then* use feof()
    and/or ferror() to distinguish between an error condition and an
    end-of-file condition.)

    Read section 12 of the comp.lang.c FAQ, <http://www.c-faq.com/>.
     
    Keith Thompson, Apr 5, 2006
    #9
  10. When you post a followup, please trim the parts of the previous
    article that aren't relevant (as I've done here).

    Why *would* feof(inFile) make sense as a way to check whether fopen()
    succeeded? Was that really what you had in mind?

    The feof() function tells you whether the end-of-file indicator is set
    for the specified stream. If fopen() fails, it returns NULL;
    feof(NULL) invokes undefined behavior (i.e., it's likely to blow up in
    your face).

    fopen() tells you whether it succeeded or failed. All you have to do
    is remember what it told you.
     
    Keith Thompson, Apr 5, 2006
    #10
    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.