K&r chapter-1; exc-17

S

sathya

Q. Write a program to print all input lines that are longer than 80
characters.

Code taken from
http://users.powernet.co.uk/eton/kandr2/krx117.html

========================code===========================
#include <stdio.h>
#define MINLENGTH 81

int readbuff(char *buffer) {
size_t i=0;
int c;
while (i < MINLENGTH) {
c = getchar();
if (c == EOF) return -1;
if (c == '\n') return 0;
buffer[i++] = c;
}
return 1;
}

int copyline(char *buffer) {
size_t i;
int c;
int status = 1;
for(i=0; i<MINLENGTH; i++)
putchar(buffer);
while(status == 1) {
c = getchar();
if (c == EOF)
status = -1;
else if (c == '\n')
status = 0;
else
putchar(c);
}
putchar('\n');
return status;
}

int main(void) {
char buffer[MINLENGTH];
int status = 0;
while (status != -1) {
status = readbuff(buffer);
if (status == 1)
status = copyline(buffer);
}
return 0;
}
================================code====================
My doubts are:

1)Why there are two getchar functions in copyline and readbuff. Can it
be done with one
global buffer pointer?

2) status variable in the main function is either 1 ,0,-1. I have seen
codes uses this kind of checking a function’s return type. That is
initializing the variable at first either with 0 or 1 and then checking
the modified value of that variable with function return type. Does this
practice carry any name?


--
"Combination is the heart of chess"
A.Alekhine
Mail to:
sathyashrayan AT gmail DOT com
(AT = @ and DOT = .)
 
M

Merrill & Michele

sathya said:
Q. Write a program to print all input lines that are longer than 80
characters.

Code taken from
http://users.powernet.co.uk/eton/kandr2/krx117.html

========================code===========================
#include <stdio.h>
#define MINLENGTH 81

int readbuff(char *buffer) {
size_t i=0;
int c;
while (i < MINLENGTH) {
c = getchar();
if (c == EOF) return -1;
if (c == '\n') return 0;
buffer[i++] = c;
}
return 1;
}

int copyline(char *buffer) {
size_t i;
int c;
int status = 1;
for(i=0; i<MINLENGTH; i++)
putchar(buffer);
while(status == 1) {
c = getchar();
if (c == EOF)
status = -1;
else if (c == '\n')
status = 0;
else
putchar(c);
}
putchar('\n');
return status;
}

int main(void) {
char buffer[MINLENGTH];
int status = 0;
while (status != -1) {
status = readbuff(buffer);
if (status == 1)
status = copyline(buffer);
}
return 0;
}
================================code====================
My doubts are:

1)Why there are two getchar functions in copyline and readbuff. Can it
be done with one
global buffer pointer?

2) status variable in the main function is either 1 ,0,-1. I have seen
codes uses this kind of checking a function's return type. That is
initializing the variable at first either with 0 or 1 and then checking
the modified value of that variable with function return type. Does this
practice carry any name?


Although K&R has somehow gotten away from me in the holiday shuffle, I think
this code ignores the development of the text. In particular, the
instructions are to WRITE the program in question, as opposed to poaching
it. That aside, your questions are topical but beyond my ability to answer
with any degree of veracity. MPJ
 
M

Michael Mair

sathya said:
Q. Write a program to print all input lines that are longer than 80
characters.

Code taken from
http://users.powernet.co.uk/eton/kandr2/krx117.html

========================code===========================
#include <stdio.h>
#define MINLENGTH 81

int readbuff(char *buffer) {
size_t i=0;
int c;
while (i < MINLENGTH) {
c = getchar();
if (c == EOF) return -1;
if (c == '\n') return 0;
buffer[i++] = c;
}
return 1;
}

int copyline(char *buffer) {
size_t i;
int c;
int status = 1;
for(i=0; i<MINLENGTH; i++)
putchar(buffer);
while(status == 1) {
c = getchar();
if (c == EOF)
status = -1;
else if (c == '\n')
status = 0;
else
putchar(c);
}
putchar('\n');
return status;
}

int main(void) {
char buffer[MINLENGTH];
int status = 0;
while (status != -1) {
status = readbuff(buffer);
if (status == 1)
status = copyline(buffer);
}
return 0;
}
================================code====================
My doubts are:

1)Why there are two getchar functions in copyline and readbuff.


If you take code from someone else and do not understand it:
Try it out!
If we have a line with >80 characters, the getchar() calls in readbuff()
were used to fill buf with the first 80 characters.
In copyline(), we write the contents of buf in one go and then print
out all the excess characters up to the end of the line or until
we encounter EOF.
We cannot read more than 80 characters into buf as buf is large enough.
On the other hand, if we wanted to output all characters in one go
with a getchar()/putchar() combination, we would have to "go back"
80 characters at realizing that we have more than 80 as we have just
"used up" these 80.
> Can it
> be done with one
> global buffer pointer?

I am not sure what you mean by that. If you want to declare buf
on file scope and not pass buf to either readbuf() or copyline(),
that is a Bad Idea. Read your C book or this group's FAQ to
find out why.
Once more: Try it out!
If you have an idea, try it. Then, you can come back and show us.

2) status variable in the main function is either 1 ,0,-1. I have seen
codes uses this kind of checking a function’s return type. That is
initializing the variable at first either with 0 or 1 and then checking
the modified value of that variable with function return type. Does this
practice carry any name?

status can be initialized with anything but -1 for the program
to work.
You could take any three values to do it. Moreover, you can
#define ENCOUNTERED_EOF -1
#define GEQ_MINLENGTH 1
use them instead of -1/1, redefine them to have any values and
so on. Instead of 0, you can return _anything_ but ENCOUNTERED_EOF
and GEQ_MINLENGTH.
<0, ==0, >0 are often used to signal whether something compared
less than, equal to, greater than something else.


Cheers
Michael
 
M

Michael Mair

Merrill & Michele wrote:

[snip: Topical question to a program not written by the OP]
Although K&R has somehow gotten away from me in the holiday shuffle, I think
this code ignores the development of the text. In particular, the
instructions are to WRITE the program in question, as opposed to poaching
it. That aside, your questions are topical but beyond my ability to answer
with any degree of veracity. MPJ

While you are right on the reminder that the OP would do better
to write the program himself, the last sentence exposes that you
are not going to either answer it (or part of it) or pose a topical
question related to his request -- and that you are aware of it.
This is bad practice. If your "bad practice" posts exceed a certain
threshold in relation to your topical posts, you will end up in many
more killfiles.
If you cannot contain your urge to spill out words, feel free to do
so where this is welcome. There are many newsgroups. Come here only
for C.


-Michael
 
D

Dan Pop

In said:
If you take code from someone else and do not understand it:
Try it out!

This is horrible advice. The code may be horribly broken, but still
working by pure accident. If the newbie sees that it works, he's likely
to assume that it is correct C code and try to learn from it.

Dan
 
M

Michael Mair

Dan said:
This is horrible advice. The code may be horribly broken, but still
working by pure accident. If the newbie sees that it works, he's likely
to assume that it is correct C code and try to learn from it.

You are right -- unqualified and without context this is horrible
advice. (Too many perl books lately...)

What I meant was: The code is advertised to be working and solving
the problem. The OP obviously believed that and from that assumption,
I went forward. Find out what happens by trying out modifications of
the parts you believe to understand and work your way down.
In this case, I would have tried modifying the output routine to
see what is going on...
IMO, writting it yourself and afterwards looking at "how it also
can be done" is much better -- you recognize the advantages and
disadvantages of both approaches and can fix bugs which escaped
the original author (or you yourself). If this is not an option, you
have to do the second best.
For badly commented complex source which I do not understand from
just reading around, I do about the same: Go to a safe box, run
with the debugger through it to get a feeling what happens
structurally, change the input data and the replacable parts.
Then, I have an image in my mind where what is going and can
figure out the relevant parts and the operations.
For long-term solutions, building the structure and the special
stuff from scratch (using libraries for the parts which really
need not be reinvented) is often better.

BTW: People who just get source from the web and want to learn
the language from that are at least naive. If I want to learn
something, I look for the community, their FAQ and the books they
recommend; even though it is not always given, there are often
good books in electronic form for free.
If there is nothing for free, I still can try a library. If then
still nothing can be turned up, then one can sigh and go by the
good old "information is power -- and power is expensive"... :-/


-Michael
 
M

Merrill & Michele

"Michael Mair"
Merrill & Michele wrote:

[snip: Topical question to a program not written by the OP]
Although K&R has somehow gotten away from me in the holiday shuffle, I think
this code ignores the development of the text. In particular, the
instructions are to WRITE the program in question, as opposed to poaching
it. That aside, your questions are topical but beyond my ability to answer
with any degree of veracity. MPJ

While you are right on the reminder that the OP would do better
to write the program himself, the last sentence exposes that you
are not going to either answer it (or part of it) or pose a topical
question related to his request -- and that you are aware of it.
This is bad practice. If your "bad practice" posts exceed a certain
threshold in relation to your topical posts, you will end up in many
more killfiles.
If you cannot contain your urge to spill out words, feel free to do
so where this is welcome. There are many newsgroups. Come here only
for C.

Michael, I would love to have posted MY version of 1-17, but I can't find
anything around this dump. If, after one more hour of tearing this place
apart to find K&R, I get a negative return value, I'll go get a new one. As
for killfiles, I know more than most about killing, less than most about
files and have no idea what the marriage of the two notions means. MPJ
 
M

Merrill & Michele

"Michael Mair
This is horrible advice. The code may be horribly broken, but still
working by pure accident. If the newbie sees that it works, he's likely
to assume that it is correct C code and try to learn from it.

You are right -- unqualified and without context this is horrible
advice. (Too many perl books lately...) [snipped]

BTW: People who just get source from the web and want to learn
the language from that are at least naive. If I want to learn
something, I look for the community, their FAQ and the books they
recommend; even though it is not always given, there are often
good books in electronic form for free.
If there is nothing for free, I still can try a library. If then
still nothing can be turned up, then one can sigh and go by the
good old "information is power -- and power is expensive"... :-/

Changing the topic slightly, but I think to do so in the direction of the
OP.
The following is lifted heavily from K&R §1.9, but with the bracing and
spacing style that I think is best. The substantive change is that I've
used char *foo instead of char foo[]. I thought Sosman called the
difference akin to coconuts vs mangoes. Anyways, the darn thing doesn't
compile, the first complaint coming from the int getline... that comes right
after main(). ++thanks MPJ

#include <stdio.h>
#define MAXLINE 5000

int getline(char *line, int maxline);
void copy(char *to, char *from);

int main(void){

int len;
int max;
char line[MAXLINE];
char longest[MAXLINE];

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

/*to console */
if (max > 0) printf("%s\nlength was%d \n", longest, max);

return 0;

int getline(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 copy(char *to, char *from) {

int i;

i = 0;
while ((to = from) != '\0') ++ i;
}
 
D

Dan Pop

In said:
The following is lifted heavily from K&R §1.9, but with the bracing and
spacing style that I think is best.

After years of experimenting, I've reached the conclusion that the K&R
bracing and spacing style is the best. I've been happily using it ever
since.
The substantive change is that I've
used char *foo instead of char foo[]. I thought Sosman called the
difference akin to coconuts vs mangoes. Anyways, the darn thing doesn't
compile, the first complaint coming from the int getline... that comes right
after main(). ++thanks MPJ

It is not the first time you're making this mistake. I didn't work in
the past, I doesn't work now and it is highly unlikely that it will work
in a future version of the language.
int main(void){

int len;
int max;
char line[MAXLINE];
char longest[MAXLINE];

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

/*to console */
if (max > 0) printf("%s\nlength was%d \n", longest, max);

return 0;

int getline(char *s, int lim) {

int c, i;

If you didn't try to improve on the K&R bracing and spacing style,
it would have been even more obvious that you're attempting to *define*
getline() *inside* main(). You CANNOT do that in C.

Dan
 
J

Jens.Toerring

Merrill & Michele said:
The following is lifted heavily from K&R §1.9, but with the bracing and
spacing style that I think is best. The substantive change is that I've
used char *foo instead of char foo[]. I thought Sosman called the
difference akin to coconuts vs mangoes.

They do differ, but in the context of calling a function (or to be
precise, treating an array in value context) coconut can look rather
similar to a mango.
Anyways, the darn thing doesn't
compile, the first complaint coming from the int getline... that comes right
after main(). ++thanks MPJ
#include <stdio.h>
#define MAXLINE 5000
int getline(char *line, int maxline);
void copy(char *to, char *from);
int main(void){
int len;
int max;
char line[MAXLINE];
char longest[MAXLINE];
max = 0;
while ((len = getline(line, MAXLINE)) > 0){
if (len > max) {
max = len;
copy(longest, line);
}
}
/*to console */
if (max > 0) printf("%s\nlength was%d \n", longest, max);
return 0;

You're missing a closing brace '}' here for main(). If you start using
some more reasonable indentation it will get easier to spot such
problems (probably you should try to find an editor that indents
int getline(char *s, int lim) {
int c, i;
for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++ i;) s
= c;


There's a semicolon at the end of the for loop condition that's not
supposed to be there. The compiler should tell you that.
if (c == '\n' {

You're missing a ')' for the if condition. Again the compiler will
tell you.
s = c;
++ i;


You can write that in a single line. i.e.

s[ i++ ] = c;
}
s = '\0';

return i;
}
void copy(char *to, char *from) {
i = 0;
while ((to = from) != '\0') ++ i;
}


If you get further in K&R you will find that the whole function can
be written as

void copy( char *to, const char *from )
{
while ( *to = *from )
;
}

or the whole thing simplified using the standard function strcpy( ) ;-)

Regards, Jens
 
M

Merrill & Michele

Merrill & Michele said:
The following is lifted heavily from K&R §1.9, but with the bracing and
spacing style that I think is best. The substantive change is that I've
used char *foo instead of char foo[]. I thought Sosman called the
difference akin to coconuts vs mangoes.

They do differ, but in the context of calling a function (or to be
precise, treating an array in value context) coconut can look rather
similar to a mango.
Anyways, the darn thing doesn't
compile, the first complaint coming from the int getline... that comes right
after main(). ++thanks MPJ
#include <stdio.h>
#define MAXLINE 5000
int getline(char *line, int maxline);
void copy(char *to, char *from);
int main(void){
int len;
int max;
char line[MAXLINE];
char longest[MAXLINE];
max = 0;
while ((len = getline(line, MAXLINE)) > 0){
if (len > max) {
max = len;
copy(longest, line);
}
}
/*to console */
if (max > 0) printf("%s\nlength was%d \n", longest, max);
return 0;

You're missing a closing brace '}' here for main(). If you start using
some more reasonable indentation it will get easier to spot such
problems (probably you should try to find an editor that indents
int getline(char *s, int lim) {
int c, i;
for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++ i;) s
= c;


There's a semicolon at the end of the for loop condition that's not
supposed to be there. The compiler should tell you that.
if (c == '\n' {

You're missing a ')' for the if condition. Again the compiler will
tell you.
s = c;
++ i;


You can write that in a single line. i.e.

s[ i++ ] = c;
}
s = '\0';

return i;
}
void copy(char *to, char *from) {
i = 0;
while ((to = from) != '\0') ++ i;
}


If you get further in K&R you will find that the whole function can
be written as

void copy( char *to, const char *from )
{
while ( *to = *from )
;
}

or the whole thing simplified using the standard function strcpy( ) ;-)


Thanks Jens. Can I ask what your compiler said about that first error? I
think it's an important modification from K&R days to #define MAXLINE a good
deal larger. MPJ
------
At the risk of incurring wrath of others, I'd like to say the following:
Heute errinert mich an dem an Tschernobyl ueber uns flog. Man kann, am Tage
nach Erntedankfest aus dem Hause heraus. Es graupelt und wir haben einen
Zustand von Minivan_shopping_hysterie.

source

#include <stdio.h>
#define MAXLINE 5000

int getline(char *line, int maxline);
void copy(char *to, char *from);

int main(void){

int len;
int max;
char line[MAXLINE];
char longest[MAXLINE];

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

/*to console */
if (max > 0) printf("%s\nlength was%d \n", longest, max);

return 0;
}

int getline(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 copy(char *to, char *from) {

int i;

i = 0;
while ((to = from) != '\0') ++ i;
}
 
J

Jens.Toerring

Merrill & Michele said:
Thanks Jens. Can I ask what your compiler said about that first error? I
think it's an important modification from K&R days to #define MAXLINE a good
deal larger. MPJ

The error message was

warning: ISO C forbids nested functions

and that (more or less clearly) tells that you're still within a
function when you assume that you're not - i.e. one or more
closing braces are missing.
Regards, Jens
 
M

Merrill & Michele

"Dan Pop"

After years of experimenting, I've reached the conclusion that the K&R
bracing and spacing style is the best. I've been happily using it ever
since.
It's on my short list to write a program that turns tabs into spaces, but
until then, I've got real trouble with the difference between what's on my
screen as opposed to what it looks like posted. Believe me, I don't like
Berkeley anything.
The substantive change is that I've
used char *foo instead of char foo[]. I thought Sosman called the
difference akin to coconuts vs mangoes. Anyways, the darn thing doesn't
compile, the first complaint coming from the int getline... that comes right
after main(). ++thanks MPJ

It is not the first time you're making this mistake. I didn't work in
the past, I doesn't work now and it is highly unlikely that it will work
in a future version of the language.

I posted something downthread that I thought worked. Did I stumble into
non-ANSI/ISO or undefined behavior?
If you didn't try to improve on the K&R bracing and spacing style,
it would have been even more obvious that you're attempting to *define*
getline() *inside* main(). You CANNOT do that in C.

No, I just blew the close-brace. It's also on my short list to write a prog
that counts open and close braces, but I've only got 32 hours in a day. MPJ
 
M

Michael Mair

[indented for readability:]
void copy(char *to, char *from) {
int i;
i = 0;
while ((to = from) != '\0')
>> ++ i;
}



If you get further in K&R you will find that the whole function can
be written as

void copy( char *to, const char *from )
{
while ( *to = *from )
;
}


I buy two postincrements for faster convergence... :)

void copy( char *to, const char *from )
{
while ( *to++ = *from++ )
;
}


Cheers
Michael
 
T

Trent Buck

Up spake Merrill & Michele:
It's also on my short list to write a prog that counts open and close braces

I have one of those. It's called emacs.

-t
PS: I expect vi(m) does it, too.
 
M

Merrill & Michele

"Trent Buck" ... braces

I have one of those. It's called emacs.

-t
PS: I expect vi(m) does it, too.

I use the platform that dare not speak its name in this environment. I
don't change whores in midstream until there's a darn good reason to do so.
MPJ
 
J

Jens.Toerring

[indented for readability:]
void copy(char *to, char *from) {
int i;
i = 0;
while ((to = from) != '\0')
++ i;
}



If you get further in K&R you will find that the whole function can
be written as

void copy( char *to, const char *from )
{
while ( *to = *from )
;
}

I buy two postincrements for faster convergence... :)
void copy( char *to, const char *from )
{
while ( *to++ = *from++ )
;
}

Grrrrrrr.... ;-)
Regards, Jens
 
M

Michael Mair

Merrill said:
It's on my short list to write a program that turns tabs into spaces, but
until then, I've got real trouble with the difference between what's on my
screen as opposed to what it looks like posted. Believe me, I don't like
Berkeley anything.

Until you have managed to write your own, use
http://www.contrib.andrew.cmu.edu/~ajo/free-software/usenetify2.c
by Arthur J. O'Dwyer.
The substantive change is that I've
used char *foo instead of char foo[]. I thought Sosman called the
difference akin to coconuts vs mangoes. Anyways, the darn thing doesn't
compile, the first complaint coming from the int getline... that comes
right
after main(). ++thanks MPJ

It is not the first time you're making this mistake. I didn't work in
the past, I doesn't work now and it is highly unlikely that it will work
in a future version of the language.

I posted something downthread that I thought worked. Did I stumble into
non-ANSI/ISO or undefined behavior?

Dan refers to the fact that you effectively have tried to define
getline() inside main() which you have tried in your derangement code,
too.

No, I just blew the close-brace. It's also on my short list to write a prog
that counts open and close braces, but I've only got 32 hours in a day. MPJ

I do not really want to bring it up again but: Get a better working
environment. Every halfway decent editor can do parentheses, brackets,
and braces matching.
Apart from that: Indentation helps.

-Michael
 
J

Jens.Toerring

I use the platform that dare not speak its name in this environment. I
don't change whores in midstream until there's a darn good reason to do so.
MPJ

We can see what system you use (just have a look at the mesage
headers yourself) and there are perfectly well working imple-
mentations for both these editors for that OS - just in case
you decide to give it a try ...
Regards, Jens
 

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

Similar Threads

K$R xrcise 1-13 (histogram) 4
K&R 1-24 15
1-17 in K&R book 9
K&R 5-1 9
Beginner at c 0
K&R xrcise 1-13 6
K&R Exercise 1-21: entab 10
C pipe 1

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,049
Latest member
Allen00Reed

Latest Threads

Top