Input Program Problem

M

Marcelo De Brito

Hi!

I've implemented a K&R's book (2nd edition) example from chapter 1
(the program that takes some text lines and gives you back the longest
line's length), but it seems it is not working.

When I press CTRL+D (EOF), the program should quit and give me back
the length of the longest line typed. However, it does not happen
anyway.

If possible, please, read the code below and if you find some bug, let
me know.

Here you are the code:

#include<stdio.h>

#define MAXLINE 1000 //maximum input line lenght

int mygetline(char line[], int maxline);
void mycopy(char to[], char from[]);

int main()
{
int len;
int max;
char line[MAXLINE];
char longest[MAXLINE];

max = 0;
while((len = mygetline(line, MAXLINE)) > 0)
if(len > max)
{
max = len;
mycopy(longest, line);
}

if(max > 0)
printf("%s", longest);
return(0);
}

int mygetline(char s[], int lim)
{
int c, i;

for(i = 0; ((i < lim - 1) && ((c = getchar()) != EOF) && (c !=
'\n')); ++i)
s = c;
if(c == '\n')
{
s = c;
++i;
}
s = '\0';
return(i);
}

void mycopy(char to[], char from[])
{
int i;
while((to = from) != '\0')
++i;
}


Best Regards!

Marcelo
 
B

Beej Jorgensen

void mycopy(char to[], char from[])
{
int i;
while((to = from) != '\0')
++i;
}


i isn't initialized in this function. Initialize it to 0 and see if
that makes it work for you.

(For some reason, my compiler isn't issuing a warning here, and I'd
expect it to.)

-Beej
 
E

Eric Sosman

Hi!

I've implemented a K&R's book (2nd edition) example from chapter 1
(the program that takes some text lines and gives you back the longest
line's length), but it seems it is not working.

When I press CTRL+D (EOF), the program should quit and give me back
the length of the longest line typed. However, it does not happen
anyway.

Different systems use different key combinations to
indicate end-of-input from keyboards. CTRL-D is the usual
keystroke for most Unix variants, CTRL-Z is used on Windows
and some other systems. Perhaps you're using the wrong key
combination? Also, on some systems the special keystroke
means end-of-input only if it's entered at the beginning of
a line.
If possible, please, read the code below and if you find some bug, let
me know. [... code snipped; see up-thread ...]

Your code prints the content of the longest line, but
doesn't even try to print its length. Other than that I see
nothing seriously "wrong," although there are opportunities
to clean things up a bit. (Of course, I may have overlooked
something ...)

Look into the CTRL-D/CTRL-Z/whatever issue; that's my
candidate for the most probable cause of your symptom.
 
A

Alan Curry

void mycopy(char to[], char from[])
{
int i;
while((to = from) != '\0')
++i;
}


i isn't initialized in this function. Initialize it to 0 and see if
that makes it work for you.

(For some reason, my compiler isn't issuing a warning here, and I'd
expect it to.)


Is it a case of "uninitialized variable warnings require data flow analysis
that is only performed when optimization is turned on"?
 
M

Marcelo De Brito

Hi, Guys!

I made some mistakes while copying the code from the book to my code
editor.

Beej Jorgensen is right! The uninitialized int variable "i" was the
problem. Now, the problem has been fixed and the program runs smooth
and well.

Eric Sosman is right too. The program I mentioned above does not
return the line's length but the longest line itself!

Thank you so much, guys!

Best regards!

Marcelo
 
M

Marcelo De Brito

Hi!

Alan, I think that has to do with the fact that uninitialized
variables hold some value in some sense. For example, this is the
output I got after compiling (using gcc 4.2.4) the code above without
explicitly setting any value to the int variable "i":

a

i = 10
aa

i = 10
aaa

i = 10
aaaa

i = 10
aaaaa

i = 10

So, without explicitly stating "int i = 0", the variable holds a valid
value anyway and I think that is the reason the compiler does not
issue any warnings.

Best Regards!

Marcelo
 
B

Beej Jorgensen

Is it a case of "uninitialized variable warnings require data flow analysis
that is only performed when optimization is turned on"?

Well, well--once again is it true that one learns something new every
day! Check it out--"c" is also used uninitialized:

$ c99 -O2 -o foo foo.c
foo.c: In function ‘mycopy’:
foo.c:49: warning: ‘i’ is used uninitialized in this function
foo.c: In function ‘mygetline’:
foo.c:37: warning: ‘c’ may be used uninitialized in this function

-Beej
 
B

Beej Jorgensen


For me, it prints "i = 5".
Alan, I think that has to do with the fact that uninitialized
variables hold some value in some sense.

They hold an indeterminate value, which can't be used in a defined
sense:

C99 6.7.8p10:
# If an object that has automatic storage duration is not initialized
# explicitly, its value is indeterminate.

C99 Annex J2p1:
# The behavior is undefined in the following circumstances:
#
# — The value of an object with automatic storage duration is used while
# it is indeterminate

And, as we saw above, it actually is behaving differently on different
systems.

More info:

C99 3.17.2p1:
# indeterminate value
# either an unspecified value or a trap representation

C99 6.2.6.1p5:
# Certain object representations need not represent a value of the
# object type. If the stored value of an object has such a
# representation and is read by an lvalue expression that does not have
# character type, the behavior is undefined. If such a representation is
# produced by a side effect that modifies all or any part of the object
# by an lvalue expression that does not have character type, the
# behavior is undefined.[41] Such a representation is called a trap
# representation.
#
# [41] Thus, an automatic variable can be initialized to a trap
# representation without causing undefined behavior, but the value
# of the variable cannot be used until a proper value is stored in
# it.
So, without explicitly stating "int i = 0", the variable holds a valid
value anyway and I think that is the reason the compiler does not
issue any warnings.

When I put a printf() right after "int i;" to print its value, I did get
a warning about i being uninitialized. I think Alan is right that with
the while loop, the code just isn't being analyzed for unused variables
unless optimizations are on.

-Beej
 
K

Keith Thompson

Marcelo De Brito said:
Alan, I think that has to do with the fact that uninitialized
variables hold some value in some sense. For example, this is the
output I got after compiling (using gcc 4.2.4) the code above without
explicitly setting any value to the int variable "i": [snip]
So, without explicitly stating "int i = 0", the variable holds a valid
value anyway and I think that is the reason the compiler does not
issue any warnings.

No, that's not it at all.

Without an explicit initialization, i hold some garbage value, and any
attempt to use that value invokes undefined behavior. Usually the
program will behave as if you had assigned some specific value to i
(most commonly 0 but it could be anything), but the code is still
wrong.

gcc didn't warn about it because it didn't notice the problem.
As Alan Curry pointed out, "uninitialized variable warnings require
data flow analysis that is only performed when optimization is
turned on". For gcc in particular, compiling with "-Wall -O"
produces the expected warnings. ("-O" requests optimization.
The analysis that the compiler performs in order to generate better
code has the side effect of causing it to notice that i is used
before being initialized.) Other compilers may behave differently.
 
N

Nobody

Different systems use different key combinations to
indicate end-of-input from keyboards. CTRL-D is the usual
keystroke for most Unix variants, CTRL-Z is used on Windows
and some other systems. Perhaps you're using the wrong key
combination? Also, on some systems the special keystroke
means end-of-input only if it's entered at the beginning of
a line.

On Unix, typing the VEOF character (typically Ctrl-D) at a terminal which
is in canonical mode will cause a read() from the terminal to return the
buffered data for the current line, and the buffer will be cleared. If the
buffer is empty (i.e. VEOF is received while at the beginning of a line
or immediately following a previous VEOF), the byte count returned from
read() will be zero, which normally indicates an EOF condition. The
condition isn't persistent; a subsequent read() will read more data.

Most programs treat a zero byte count from read() as indicating EOF. When
input is from a terminal, these will only treat the VEOF character as an
EOF condition when it occurs at the beginning of a line. In particular,
the stdio functions behave this way, so fgetc() will only return EOF when
the VEOF character follows CR/LF/VEOL.
 

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,995
Messages
2,570,230
Members
46,818
Latest member
Brigette36

Latest Threads

Top