Google
 
Webnews.only-4-geeks.com
Interesting places
news.only-4-geeks.com Forum Index » CGoto page 1, 2, 3  Next

K&R Ex 1-22

 
Jump to:  
 
Andrew C.
PostPosted: Tue Aug 19, 2008 5:36 am    Post subject: K&R Ex 1-22
       
I'm trying to complete excercise 1-23 in the K&R book, which calls for
a program to wrap input lines at a given column, making sure to handle
lines that wrap twice or don't contain whitespace. This is what I have
so far*:
LINK
*Insert is a function which shifts the contents of the string right by
one character and inserts another character in its place.

I'm sure there's probably a completely better way to do this, but I'm
too far into it to rewrite it a different way.

Anyway, what I really want to know is
why the variable "search_state" always equals zero (at least according
to the printf statement I put in there and the fact that it never
wraps) even though the if statement before "search_state = 1" resolves
to be true. It's almost as though search_state was losing its value at
the end of the for loop. If it doesn't get set to 1, no wrapping will
happen.

I feel really stupid for having this much
trouble with an excercise so early in the book, but this has me
baffled.


-
You can get everything in life you want, if you will help enough other
people get what they want.
 

 
Richard Heathfield
PostPosted: Tue Aug 19, 2008 5:57 am    Post subject: Re: K&R Ex 1-22
       
Andrew C. said:

Quote:
I'm trying to complete excercise 1-23 in the K&R book, which calls for
a program to wrap input lines at a given column, making sure to handle
lines that wrap twice or don't contain whitespace. This is what I have
so far*:
LINK

I haven't much time right now, but I will have, later on. For me (or indeed
for anyone else) to look at your problem in sufficient detail to help you,
it would be handy if you could post the complete, compilable source code
that you are using, preferably right here on Usenet rather than on a Web
site. Also, it would be very useful to know what test data you're using.

My first glance (and it *is* only a quick glance) suggests that, when you
pass a string of fewer than 80 characters, your value for 'next' will be
0, which looks like it could be problematic. (That might not be the
problem - it's just a first impression.)

No doubt someone else will be able to help you more, but I really do
recommend that you post the full source here, together with your test
data.

HTH. HAND.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
 

 
Andrew C.
PostPosted: Tue Aug 19, 2008 7:34 am    Post subject: Re: K&R Ex 1-22
       
On 2008-08-19, Richard Heathfield <rjh@see.sig.invalid> wrote:
Quote:
Andrew C. said:

I'm trying to complete excercise 1-23 in the K&R book, which calls for
a program to wrap input lines at a given column, making sure to handle
lines that wrap twice or don't contain whitespace. This is what I have
so far*:
LINK

I haven't much time right now, but I will have, later on. For me (or indeed
for anyone else) to look at your problem in sufficient detail to help you,
it would be handy if you could post the complete, compilable source code
that you are using, preferably right here on Usenet rather than on a Web
site. Also, it would be very useful to know what test data you're using.

My first glance (and it *is* only a quick glance) suggests that, when you
pass a string of fewer than 80 characters, your value for 'next' will be
0, which looks like it could be problematic. (That might not be the
problem - it's just a first impression.)

No doubt someone else will be able to help you more, but I really do
recommend that you post the full source here, together with your test
data.

HTH. HAND.

You're right, I should have posted the full source code. I used

pastebin because I figured it would have been a bigger breach of
ettiquette to post a sizeable source file directly to usenet, long
lines and all, but here goes:

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

#define MAXCOLS 80 /*Column to wrap at*/
#define MAXLINE 1000 /*Maximum string length*/
#define NEXT(current) ((current/MAXCOLS+1)*MAXCOLS) /*macro
to calculate next*/

void wrap(char s[], int len);
void insert(char s[], int at, char c);
int getline(char s[], int lim);

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

int i;
for(i = 0; i<=80; ++i)
putchar(' ');
printf("|\n");

while((len = getline(line, MAXLINE)) > 0) {
wrap(line,len);
printf("%s",line);
}

return 0;
}

/*wrap: word wrap a string at the desired length */
void wrap(char s[], int len)
{
int search_state = 0; /*0 = looking for next, 1 = looking for
whitespace*/
int i = len-1;
int next = ((i/MAXCOLS))*MAXCOLS; /*next column to wrap at*/

for(i = len-1; i > MAXCOLS-1; --i) {
next = ((i/MAXCOLS))*MAXCOLS;
printf(" %d ",search_state); /*debug*/
if(search_state == 1) {
if(s[i] == ' ') { /*all is well*/
s[i] = '\n'; /*place a newline in the
whitespace*/
search_state = 0; /*reset the state*/
}
else if(i == next && s[i] != ' ') { /*there
wasn't any whitespace*/
insert(s,i,'\n'); /*insert a newline
at the wrap point*/
search_state = 0; /*reset the state*/
}
}
else
if(next >= MAXCOLS && i == next) /*if there is
a next, and i equals it, start wrapping*/
search_state = 1;
}
}

/*insert: insert a character into the middle of a character string*/
void insert(char s[], int at, char c)
{
int i;

for(i = strlen(s)-1; i>=at; --i)
s[i+1] = s[i];
s[i] = c;
}

/* getline: read a line into s, return length */
int getline(char s[], int lim)
{
int c, i;
for (i = 0; i<lim-1 && (c=getchar()) != EOF && c!='\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
++i;
}
if (i >= lim-1) {
while((c = getchar()) != EOF && c!='\n')
++i; /*increment length anyway in case of overflow*/
s[lim-1] = '\0';
}
else
s[i] = '\0';
return i;
}


By the way, with any input line less than 80 characters, absolutely
nothing should happen to it, which is indeed the correct behavior
because no word wrapping is needed.

As for test data, any input (I either mashed the keyboard or typed in
song lyrics) does the exact same thing: spit the input out unchanged.

Thanks for your help, and sorry for being a noob.
--
You can get everything in life you want, if you will help enough other
people get what they want.
 

 
Richard Heathfield
PostPosted: Tue Aug 19, 2008 12:30 pm    Post subject: Re: K&R Ex 1-22
       
Andrew C. said:

Quote:
On 2008-08-19, Richard Heathfield <rjh@see.sig.invalid> wrote:

No doubt someone else will be able to help you more, but I really do
recommend that you post the full source here, together with your test
data.

You're right, I should have posted the full source code. I used
pastebin because I figured it would have been a bigger breach of
ettiquette to post a sizeable source file directly to usenet, long
lines and all,

Your concern for etiquette makes a welcome change! Nevertheless, a hundred
lines or so is no big deal in Usenet nowadays, at least not for most
people, and we can hope that the first couple of articles in this thread
will warn modem-users off. :-)

Okay, my first step was to compile it:

gcc -W -Wall -ansi -pedantic -Wformat-nonliteral -Wcast-align
-Wpointer-arith -Wbad-function-cast -Wmissing-prototypes
-Wstrict-prototypes -Wmissing-declarations -Winline -Wundef
-Wnested-externs -Wcast-qual -Wshadow -Wconversion -Wwrite-strings
-ffloat-store -fno-builtin -O2 -g -pg -c -o kr123.o kr123.c
kr123.c:14: warning: return-type defaults to `int'
kr123.c:14: warning: function declaration isn't a prototype
kr123.c: In function `wrap':
kr123.c:50: warning: passing arg 3 of `insert' with different width due to
prototype
kr123.c: In function `getline':
kr123.c:75: warning: `c' might be used uninitialized in this function

So let's go fix those things.

On line 14, I changed:

main()

to:

int main(void)

On line 50, '\n' is actually of type int, would you believe? But we know
its value must fit in a char (for several reasons, one of which is that it
is a mandatory member of the source character set, so it must have a value
in the range 1 to CHAR_MAX), so it's okay to pass it to a function
expecting a char. No fix required (although changing insert() to take int
rather than char would at least silence the warning).

By far the most serious warning is the one about 'c' possibly being used
uninitialised. But as far as I can see, this is actually impossible, given
that there is only one call to getline, and it specifies a large-ish value
for lim, so i<lim-1 must be true first time round, so the getchar is
definitely called.

So much for the compiler. Let's look at the behaviour.

To make matters a little less long-winded, I changed MAXCOLS to 12 and
recompiled. I gave your program an input of abcdefghijklmnop, and it
printed a bunch of spaces and a vertical bar, as expected. (I don't know
why you do that, but hey, it's your program!) It then spat out what look
like some debugging numbers, followed by abcdefghijklmnop again, with no
wrap.

Then I gave it lots and lots of junk, and (remembering that we changed
MAXCOLS to 12) look what happened!

fkjslvnfdlskjvnfsdkjlvnfdskjvnfsdkjvnfksldjnvjksldfnvjdskfvnfdjsvnjkdfls
jfks vjksfdvjkfsdhvjksdfvhjksdfv
0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0
0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 fkjslvnfdls
jjvnfsdkjlvnfdskjvnfsdkj
nnfksldjnvjksldfnvjdskfv
ffdjsvnjkdfls jfks vjksf
vvjkfsdhvjksdfvhjksdfv
#1 Wed Mar 27 13:57:05 UTC 2002

WOW! I have no idea where that timestamp came from... :-)

So it looks like you *are* getting wrap, but not how and when you want it.
It also looks like you have an unterminated "string". (That's the usual
cause of utterly off-the-wall output.)

Time to read the code.

The first few lines in main just print out a bunch of spaces and a |, for
no apparent reason - although no doubt you know why. Nothing illegal
there, so let's move on.

You have a nice simple loop, consisting of getline, wrap, and printf. The
printf prints 'line', so we have a good idea of which "string" isn't
getting terminated. I checked to see whether it is constructed properly,
by looking at getline, and getline seems fine.

So the problem of failure to terminate is either in wrap() or in insert(),
and my money is on insert(), so let's take a look:

void insert(char s[], int at, char c)
{
int i;

for(i = strlen(s)-1; i>=at; --i)
s[i+1] = s[i];
s[i] = c;
}

Consider the following string: "ABCDEF\n\0" (I've made the \0 explicitly
visible, but it isn't part of the count given by strlen.)

i = strlen(s) - 1; Since strlen(s) is 7 (A-F is 6, + \n), i takes the value
6.

s[i+1] = s[i];

so we're doing s[7] = s[6]. Now, s[7] /was/ the null terminator, but we
just overwrote that. Not good. Let's fix it.

Whilst strlen yields the length of a string (not including the null), we
can think of it in another way, i.e. as returning the offset of the null
terminator.

void insert(char s[], int at, char c)
{
size_t nullpos = strlen(s);
size_t pos = nullpos;
while(pos > 0 && pos > at)
{
s[pos] = s[pos - 1];
--pos;
}
s[pos] = c;
s[nullpos + 1] = '\0';
}

That's fixed our null termination problem. Now for the logic bug, which is
clearly in the wrap() function. Experimentation quickly revealed that your
code *is* wrapping, albeit rather bizarrely - for example, the first wrap
seems to occur at 2*MAXCOLS, rather than at MAXCOLS.

It appears that what you're trying to do is replace a space with a newline
if possible, but if necessary you'll shift a long string's tail over by
one character to insert a newline. A perfectly reasonable approach,
although of course you have to be careful with lines close to your
buffer's size limit.

It strikes me that it would be much easier to do this as follows:

void wrap(char s[], size_t len)
{
char *t = s;
while(len >= MAXCOLS)
{
t += MAXCOLS;
while(t > s && *t != ' ')
{
--t;
}
if(*t == ' ')
{
*t = '\n';
}
else
{
t += MAXCOLS;
insert(t, 0, '\n');
}
len -= (t - s);
s = t;
}
}

Dropping that - and the insert() update - into your program (and making
appropriate type-changes from int to size_t, which is a more appropriate
type for describing buffer sizes), for input like this:

That's fixed our null termination problem. Now for the logic bug, which is
clearly in the wrap() function. Experimentation quickly revealed that your
code *is* wrapping, albeit rather bizarrely - for example, the first wrap
seems to occur at 2*MAXCOLS, rather than at MAXCOLS.

I get output like this:

That's fixed
our null
termination
problem.
Now for the
logic bug,
which is
clearly in
the wrap()
function.
Experimenta
tion
quickly
revealed
that your
code *is*
wrapping,
albeit
rather
bizarrely -
for
example,
the first
wrap seems
to occur at
2*MAXCOLS,
rather than
at
MAXCOLS.

and that seems to be working nicely.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
 

 
Andrew C.
PostPosted: Tue Aug 19, 2008 5:20 pm    Post subject: Re: K&R Ex 1-22
       
Thanks much for your help. First, let me go ahead and explain myself
on that one segment of code involving spaces and a pipe - that's just
a ruler I was printing to see if I had typed enough input to warrant
wrapping. I noticed it was hardcoded to use 80 columns so I fixed it
to use MAXCOLS instead. I guess I should have commented that.

Thank you for pointing out the problem with insert(), i probably
wouldn't have noticed it otherwise.

Your solution for wrap is amazingly more elegant than mine:

On 2008-08-19, Richard Heathfield <rjh@see.sig.invalid> wrote:

Quote:
It strikes me that it would be much easier to do this as follows:

void wrap(char s[], size_t len)
{
char *t = s;
while(len >= MAXCOLS)
{
t += MAXCOLS;
while(t > s && *t != ' ')
{
--t;
}
if(*t == ' ')
{
*t = '\n';
}
else
{
t += MAXCOLS;
insert(t, 0, '\n');
}
len -= (t - s);
s = t;
}
}

However, I'm having trouble understanding it because I can see it uses
pointers, and having not reached that chapter in the book I don't really
understand what pointers do. I'm sure this section can be written
without pointers though, so I'll just set out to rewrite the function
using the logic I think I'm seeing above.

--
You can get everything in life you want, if you will help enough other
people get what they want.
 

 
Andrew C.
PostPosted: Tue Aug 19, 2008 5:55 pm    Post subject: Re: K&R Ex 1-22
       
On 2008-08-19, mdh <mdeh@comcast.net> wrote:
Quote:
On Aug 19, 12:20 pm, "Andrew C." <sumguy231+n...@gmail.com> wrote:

However, I'm having trouble understanding it because I can see it uses
pointers, and having not reached that chapter in the book I don't really
understand what pointers do. I'm sure this section can be written
without pointers though, so I'll just set out to rewrite the function
using the logic I think I'm seeing above.


Andrew...like you, I have gone through K&R and done just about every
exercise. I would make one recommendation. There is a book called "The
C Answer book" by Tondo and Gimpel , that works through each
question, in order of learning ie it would not talk about pointers
before you have studied them. I have found this to be immensely
helpful, as their solutions are elegant ( which you apparently like)
and explained. The other thing is doing what you are doing ie asking
clc.
As long as you do not want your homework done.. Smile . the clc is
wonderfully... actually amazingly helpful, by the best minds on C.

Thanks for the recommendation, that book looks very helpful. I'm a
little short on cash at the moment, but I'll try to pick it up if I
can because it would help me immensely to be able to check my answers.

....And I promise not to ask you guys to do my homework for me, even
though I'm not taking any classes involving C (yet). :-)

--
You can get everything in life you want, if you will help enough other
people get what they want.
 

 
mdh
PostPosted: Tue Aug 19, 2008 7:34 pm    Post subject: Re: K&R Ex 1-22
       
On Aug 19, 12:20 pm, "Andrew C." <sumguy231+n...@gmail.com> wrote:

Quote:
However, I'm having trouble understanding it because I can see it uses
pointers, and having not reached that chapter in the book I don't really
understand what pointers do. I'm sure this section can be written
without pointers though, so I'll just set out to rewrite the function
using the logic I think I'm seeing above.


Andrew...like you, I have gone through K&R and done just about every
exercise. I would make one recommendation. There is a book called "The
C Answer book" by Tondo and Gimpel , that works through each
question, in order of learning ie it would not talk about pointers
before you have studied them. I have found this to be immensely
helpful, as their solutions are elegant ( which you apparently like)
and explained. The other thing is doing what you are doing ie asking
clc.
As long as you do not want your homework done.. Smile . the clc is
wonderfully... actually amazingly helpful, by the best minds on C.
 

 
Ron Ford
PostPosted: Tue Aug 19, 2008 11:26 pm    Post subject: Re: K&R Ex 1-22
       
On Tue, 19 Aug 2008 07:57:04 +0000, Richard Heathfield posted:

Quote:
http://pastebin.com/f61c6cfc

I haven't much time right now, but I will have, later on. For me (or indeed
for anyone else) to look at your problem in sufficient detail to help you,
it would be handy if you could post the complete, compilable source code
that you are using, preferably right here on Usenet rather than on a Web
site. Also, it would be very useful to know what test data you're using.

Richard errs that everyone else prefers source posting in clc as opposed to
a link. Are you solving 22 or 23?
--
When a new source of taxation is found it never means, in practice, that
the old source is abandoned. It merely means that the politicians have two
ways of milking the taxpayer where they had one before. 8
H. L. Mencken
 

 
Andrew C.
PostPosted: Tue Aug 19, 2008 11:41 pm    Post subject: Re: K&R Ex 1-22
       
On 2008-08-20, Ron Ford <ron@example.invalid> wrote:
Quote:
On Tue, 19 Aug 2008 07:57:04 +0000, Richard Heathfield posted:

LINK

I haven't much time right now, but I will have, later on. For me (or indeed
for anyone else) to look at your problem in sufficient detail to help you,
it would be handy if you could post the complete, compilable source code
that you are using, preferably right here on Usenet rather than on a Web
site. Also, it would be very useful to know what test data you're using.

Richard errs that everyone else prefers source posting in clc as opposed to
a link. Are you solving 22 or 23?
I'm solving 22. I already finished 23, it was actually quite easy.


--
Let us never negotiate out of fear, but let us never fear to negotiate.
-- John F. Kennedy
 

 
Richard Heathfield
PostPosted: Wed Aug 20, 2008 2:24 am    Post subject: Re: K&R Ex 1-22
       
Andrew C. said:

<snip>

Quote:
However, I'm having trouble understanding it because I can see it uses
pointers,

Oops! Sorry about that.

void wrap(char s[], size_t len)
{
size_t basepos = 0;
size_t curpos = 0;

while(len >= MAXCOLS)
{
curpos += MAXCOLS;
while(curpos > basepos && s[curpos] != ' ')
{
--curpos;
}
if(s[curpos] == ' ')
{
s[curpos] = '\n';
}
else
{
curpos += MAXCOLS;
insert(s, curpos, '\n');
}
len -= (curpos - basepos);
basepos = curpos;
}
}

I haven't actually tested this, but I'm reasonably sure I got the
translation right.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
 

Page 1 of 3 .:. Goto page 1, 2, 3  Next

Google
 
Webnews.only-4-geeks.com

Windows Update | C++ | C | PHP | JavaScript | Photoshop | Programming | Windows 2000 | Python | Windows XP | Object | Flash | Flash - ActionScript | Paint Shop Pro | Excel | PowerPoint | Access | Word | Windows 98 | Internet Explorer 6.0 | CorelDraw12 | Java | XML | asm x86 | Linux Mandrake | Linux RedHat | Outlook |  | news from newsgroups |_ | s

Web Templates

Awesome Website Templates ©

zabawki Tłumacz niemiecki apteka rowery Teksty piosenek