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

C

Chad

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
 
R

Robert Gamble

Chad said:
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);

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".
if(strncmp(buff,temp2,sizeof(buff)) != 0)
fputs(buff, stdout);

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.
}
}

if(feof) {
return 0;
}

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.
fclose (inFile);

return 0;
}

Output

$gcc -Wall lunar.c -o lunar

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?
$./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

Robert Gamble
 
C

Chad

Robert said:
Chad said:
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);

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".
if(strncmp(buff,temp2,sizeof(buff)) != 0)
fputs(buff, stdout);

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.
}
}

if(feof) {
return 0;
}

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.
fclose (inFile);

return 0;
}

Output

$gcc -Wall lunar.c -o lunar

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?
$./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

Robert Gamble

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
 
C

Chad

Chad said:
Robert said:
Chad said:
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);

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".
if(strncmp(buff,temp2,sizeof(buff)) != 0)
fputs(buff, stdout);

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.
}
}

if(feof) {
return 0;
}

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.
fclose (inFile);

return 0;
}

Output

$gcc -Wall lunar.c -o lunar

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?
$./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

Robert Gamble

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

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
 
C

Chad

Chad said:
Robert said:
Chad said:
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);

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".
if(strncmp(buff,temp2,sizeof(buff)) != 0)
fputs(buff, stdout);

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.
}
}

if(feof) {
return 0;
}

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.
fclose (inFile);

return 0;
}

Output

$gcc -Wall lunar.c -o lunar

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?
$./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

Robert Gamble

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

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
 
R

Robert Gamble

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

2003? That's ancient ;)
The newer versions (4.0.x) will complain.

Robert Gamble
 
K

Keith Thompson

Chad said:
The input file is: [snip]

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);

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.
}
}

if(feof) {
return 0;
}

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]
 
C

Chad

Keith said:
Chad said:
The input file is: [snip]

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);

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.
}
}

if(feof) {
return 0;
}

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]

Why wouldn't something like

if feof(inFile)

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

Chad
 
K

Keith Thompson

Chad said:
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.

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/>.
 
K

Keith Thompson

Chad said:
Why wouldn't something like

if feof(inFile)

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

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.
 

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

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top