You are not logged in.

#1 2012-07-08 22:22:40

exapplegeek
Member
From: Macedonia
Registered: 2012-06-24
Posts: 36

A beginner's problems in C (exercises from K&R book)

Ignore the first part of this message as it was cross-posted:
[IGNORE]
I have recently started to learn C programming language from "The C Programming Language" book, but there is something that really bothers me.

This is exercise 1-9:

Write a program to copy its input to its output, replacing each string of one or more blanks by a single blank.

So I tried to write it by myself, but didn't get it right, so I searched online for a solution, and found a few, but I choose to 'explore' the easier one, but I couldn't really understand it.

Here it is:

#include <stdio.h>

/* count lines in input */
int
main()
{
        int c, pc; /* c = character, pc = previous character */

        /* set pc to a value that wouldn't match any character, in case
        this program is ever modified to get rid of multiples of other
        characters */

        pc = EOF;

        while ((c = getchar()) != EOF) {
                if (c == ' ')
                        if (pc != ' ')   /* or if (pc != c) */ 
                                putchar(c);

                /* We haven't met 'else' yet, so we have to be a little clumsy */
                if (c != ' ')
                        putchar(c);
                pc = c;
        }

        return 0;
}

It is from this page: http://users.powernet.co.uk/eton/kandr2/krx109.html

Can you please explain it for me?

Thanks, and God bless!

[/IGNORE]

I will post my problems with the C exercises from K&R book here in this thread, so that I will not open a new thread for every new problem that I run into.

Last edited by exapplegeek (2012-07-10 13:10:21)


Soli Deo Gloria!
I Stand Up For Christ! Do you?
________________________
Always have your stuff when you need it with Dropbox. Sign up for free (under my referral link)! http://db.tt/3rOCPK4r

Offline

#2 2012-07-08 22:46:41

falconindy
Developer
From: New York, USA
Registered: 2009-10-22
Posts: 4,111
Website

Re: A beginner's problems in C (exercises from K&R book)

If your goal is to learn the language, having someone explain this piece of code in full isn't going to help you very much. Making an initial effort and then asking pointed questions about the remaining bits is far more productive.

What specifically is unclear about this?

Offline

#3 2012-07-08 22:48:06

Procyon
Member
Registered: 2008-05-07
Posts: 1,819

Re: A beginner's problems in C (exercises from K&R book)

And post your failed attempt.

Offline

#4 2012-07-08 22:57:51

exapplegeek
Member
From: Macedonia
Registered: 2012-06-24
Posts: 36

Re: A beginner's problems in C (exercises from K&R book)

falconindy wrote:

If your goal is to learn the language, having someone explain this piece of code in full isn't going to help you very much. Making an initial effort and then asking pointed questions about the remaining bits is far more productive.

What specifically is unclear about this?

The thing that is unclear is simply that I don't understand how it replaces '        ' with simply a ' ' for example. I need to understand how it works.

It reads the data from "c" and then it prints it again (if the condition is met), but I don't see how it changes the data inside "c".

And I don't undestand how the "pc" works.

I didn't save my (failed attempt) code, but I think I can rewrite it, but it's simply too stupid to base my solution on it.
If you want, I will rewrite it and post it here.

Last edited by exapplegeek (2012-07-08 22:58:36)


Soli Deo Gloria!
I Stand Up For Christ! Do you?
________________________
Always have your stuff when you need it with Dropbox. Sign up for free (under my referral link)! http://db.tt/3rOCPK4r

Offline

#5 2012-07-08 23:05:45

Terminator
Member
From: Belgium
Registered: 2012-05-07
Posts: 265

Re: A beginner's problems in C (exercises from K&R book)

Disclaimer: I have never used C, but I can program in java, haskell and prolog.

Although this is a particularly bad program for such an easy task and the code speaks for itself, I will try to explain it anyway. Note, EOF=end of file.
The code reads every character from the input. The character is kept in c. The previous character is kept in pc. Unless both c and pc are a space, it will print it.
Note that the condition in the while loop both reads a new character and checks if the character is different from EOF.

example, input: "012  3"
1) pc=EOF c='0' --> print '0' (c!=' ' succeeds)
2) pc='0' c='1' --> print '1'
3) pc='1' c='2' --> print '2'
4) pc='2' c=' ' --> print ' ' (c==' ' succeeds and pc!=' ' succeeds)
5) pc=' ' c=' ' --> don't print anything (both c and pc are ' ')
6) pc=' ' c='3' --> print '3'
7) pc='3' c=EOF --> Stop

--> The while loop prints "012 3"

The code is really bad because of 3 things:
1) The code returns an integer (a number), 0, while in has nothing to do with numbers.
2) Characters are represented by integers (again, numbers), instead of chars (letters). While this is possible, it is ugly.
3) The code in the loop is too long for what it does.

The code should probably be written as:

#include <stdio.h>
void main()
{
        char pc = EOF;
        char c= getchar();

        while (c != EOF) {
                if (c != ' ' || pc != ' ')
                        putchar(c);
                pc = c;
                c = getchar();
        }
}

Offline

#6 2012-07-08 23:05:57

OU812
Member
Registered: 2009-11-19
Posts: 47

Re: A beginner's problems in C (exercises from K&R book)

Write a sentence with a just a few words in it. Put a 2 or 3 spaces between some of the words. Then go through the sentence using "pseudo-code" to understand the "flow" of the program. Then go through the sentence again using the actual code. For example, let's say I am typing the sentence

I saw   a red  truck.

So in psuedo-cdoe we have:

Read a character from input, until EOF is reached.
   If it's a space, check to see if previous character is a space.
      If previous character is not a space, echo character (otherwise do not echo additional spaces)
   If it's not a space, echo character

Always try and write your program in pseudo-code first.

john

Offline

#7 2012-07-09 19:17:19

drm00
Member
Registered: 2010-06-01
Posts: 38

Re: A beginner's problems in C (exercises from K&R book)

Here is my solution, with a different approach. Perhaps this makes more sense to you.

#include <stdio.h>

/* replace all sequences of blanks with a single blank. */
int main()
{
	int c;
	int series_of_blanks = 0;

	while ((c = getchar()) != EOF) {
		if (c == ' ') {
			if (!series_of_blanks) {
				series_of_blanks = 1;
				putchar(c);
			} 
		} else {
			series_of_blanks = 0;
			putchar(c);
		}
	}
	return(0);
}

Edit: Just read the linked thread, my solution is much like the first one. To get a better understanding of this problem, look at the positions in the code where and under which conditions a character is printed out.

Last edited by drm00 (2012-07-09 19:42:01)

Offline

#8 2012-07-09 20:31:45

Lux Perpetua
Member
From: The Local Group
Registered: 2009-02-22
Posts: 73

Re: A beginner's problems in C (exercises from K&R book)

Oy vey.

Terminator wrote:

Disclaimer: I have never used C, but I can program in java, haskell and prolog.

Then why are you trying to correct other people's code?

Terminator wrote:

The code is really bad because of 3 things:
1) The code returns an integer (a number), 0, while in has nothing to do with numbers.
2) Characters are represented by integers (again, numbers), instead of chars (letters). While this is possible, it is ugly.
3) The code in the loop is too long for what it does.

The code should probably be written as:

#include <stdio.h>
void main()
{
        char pc = EOF;
        char c= getchar();

        while (c != EOF) {
                if (c != ' ' || pc != ' ')
                        putchar(c);
                pc = c;
                c = getchar();
        }
}

1) main() always returns an int, which is the exit status of the program. People who write void main() in C don't know what they're doing. return 0; from main signifies a normal status and is completely standard and correct.
2) getchar() returns an int, and storing the result as a char eliminates your ability to test for end-of-file. EOF is defined to be -1, which as an int can be distinguished from a valid character. On the other hand, the char value -1, namely 0xff, is a perfectly valid constituent of a file.
3) This is completely subjective, and "length of source code" is a poor metric of quality, in any case.

P. S. The OP is a cross post.

Offline

#9 2012-07-09 20:31:51

Xyne
Administrator/PM
Registered: 2008-08-03
Posts: 6,965
Website

Re: A beginner's problems in C (exercises from K&R book)

exapplegeek wrote:

The thing that is unclear is simply that I don't understand how it replaces '        ' with simply a ' ' for example. I need to understand how it works.

It reads the data from "c" and then it prints it again (if the condition is met), but I don't see how it changes the data inside "c".

And I don't undestand how the "pc" works.

First, remember what it is supposed to do:

Write a program to copy its input to its output, replacing each string of one or more blanks by a single blank.

So if you have the input string "foo   bar baz          whatever", then you want to copy it to "foo bar baz whatever".

What you are really doing is removing extra blanks (" "). If there is only one blank in a row, then you can just pass it through. If there are two or more blanks in a row, you only want to pass one through. Everything that is not a blank gets passed through.

Another way to think of it is that a blank can only go through if the last character was not a blank.

So for each character of the input, if it is not a blank,  you let it through.
If it is a blank and the last character was not a blank, you let it through.
If it is a blank and the last character was also a blank, then you throw it away. You do this until you get to a non-blank character.

"pc" is the previous character. It keeps track of the last character so you know what to do with the blanks.

Does that help at all?


My Arch Linux StuffForum EtiquetteCommunity Ethos - Arch is not for everyone

Offline

#10 2012-07-09 23:48:52

Trent
Member
From: Baltimore, MD (US)
Registered: 2009-04-16
Posts: 990

Re: A beginner's problems in C (exercises from K&R book)

Lux Perpetua wrote:

Oy vey.

Terminator wrote:

Disclaimer: I have never used C, but I can program in java, haskell and prolog.

Then why are you trying to correct other people's code?

Maybe he intends to become the next Herbert Schildt.

Offline

#11 2012-07-10 02:08:49

ewaller
Administrator
From: Pasadena, CA
Registered: 2009-07-13
Posts: 20,334

Re: A beginner's problems in C (exercises from K&R book)

Lux Perpetua wrote:

...
1) main() always returns an int, which is the exit status of the program. People who write void main() in C don't know what they're doing. return 0; from main signifies a normal status and is completely standard and correct.
...

Well, always is a pretty broad brush.  Granted, on a program designed to run on a system with an operating system, it is probably true.  There are, however, those of us who write firmware for embedded systems.  If main ever returns, you have done something very, very wrong.  Sometimes, the stack does not even get set up until you are in the main code. Hopefully there is a good watchdog timer to provide a non-graceful recovery should main return.  As such, we use void main(void) to explicitly say we don't return anything, and we don't expect any parameters on the stack.

I'm just saying ...  tongue


Nothing is too wonderful to be true, if it be consistent with the laws of nature -- Michael Faraday
Sometimes it is the people no one can imagine anything of who do the things no one can imagine. -- Alan Turing
---
How to Ask Questions the Smart Way

Offline

#12 2012-07-10 09:09:36

Lux Perpetua
Member
From: The Local Group
Registered: 2009-02-22
Posts: 73

Re: A beginner's problems in C (exercises from K&R book)

ewaller wrote:
Lux Perpetua wrote:

...
1) main() always returns an int, which is the exit status of the program. People who write void main() in C don't know what they're doing. return 0; from main signifies a normal status and is completely standard and correct.
...

Well, always is a pretty broad brush.  Granted, on a program designed to run on a system with an operating system, it is probably true.  There are, however, those of us who write firmware for embedded systems.  If main ever returns, you have done something very, very wrong.  Sometimes, the stack does not even get set up until you are in the main code. Hopefully there is a good watchdog timer to provide a non-graceful recovery should main return.  As such, we use void main(void) to explicitly say we don't return anything, and we don't expect any parameters on the stack.

I'm just saying ...  tongue

Okay, fair enough. I do recall that the standard distinguishes between "hosted" and "freestanding" environments, the requirements on main() applying to the former and basically going out the window for the latter. (I think that in the freestanding case, the entry point doesn't even have to be called "main()".) But it's safe to assume by default that the OP's program is intended for a hosted environment (indeed, it's probably intended to be portable ANSI-compliant code).

Offline

#13 2012-07-10 12:51:21

exapplegeek
Member
From: Macedonia
Registered: 2012-06-24
Posts: 36

Re: A beginner's problems in C (exercises from K&R book)

I have closed the thread on devshed, but will keep this open for further questions.


Soli Deo Gloria!
I Stand Up For Christ! Do you?
________________________
Always have your stuff when you need it with Dropbox. Sign up for free (under my referral link)! http://db.tt/3rOCPK4r

Offline

#14 2012-07-10 13:07:41

exapplegeek
Member
From: Macedonia
Registered: 2012-06-24
Posts: 36

Re: A beginner's problems in C (exercises from K&R book)

OU812 wrote:

Write a sentence with a just a few words in it. Put a 2 or 3 spaces between some of the words. Then go through the sentence using "pseudo-code" to understand the "flow" of the program. Then go through the sentence again using the actual code. For example, let's say I am typing the sentence

I saw   a red  truck.

So in psuedo-cdoe we have:

Read a character from input, until EOF is reached.
   If it's a space, check to see if previous character is a space.
      If previous character is not a space, echo character (otherwise do not echo additional spaces)
   If it's not a space, echo character

Always try and write your program in pseudo-code first.

john

Thanks about this, this helped me when solving the next exercise, and I see it as an advice from an experienced programmer, and I think it will be of a great use.

On the other side, speaking about "void main()" it caused me some confusion, but in the past, when I was coding in Xcode (back when I had OS X) it gave me some warning, and from that time till now, I thought that "void main()" was obsolete and replaced by "int main()". But now I see in the book that it is even possible to write it as "main()".

Thanks God, I successfully wrote the next program (exercise 1-12), though it was not very successful on the first attempt, I did a lot of tweaking, and I was going to ask here what I was doing wrong why it printed new lines for every blank, but I looked at the solution from that site, and I didn't copy it, but tweaked my code, and finally got it working.

I will also change the name of the thread, so I will not post new threads for every 'difficult' exercise in K&R.


Soli Deo Gloria!
I Stand Up For Christ! Do you?
________________________
Always have your stuff when you need it with Dropbox. Sign up for free (under my referral link)! http://db.tt/3rOCPK4r

Offline

#15 2012-07-10 13:17:12

Trent
Member
From: Baltimore, MD (US)
Registered: 2009-04-16
Posts: 990

Re: A beginner's problems in C (exercises from K&R book)

ewaller wrote:

Well, always is a pretty broad brush.  Granted, on a program designed to run on a system with an operating system, it is probably true.  There are, however, those of us who write firmware for embedded systems.  If main ever returns, you have done something very, very wrong.  Sometimes, the stack does not even get set up until you are in the main code. Hopefully there is a good watchdog timer to provide a non-graceful recovery should main return.  As such, we use void main(void) to explicitly say we don't return anything, and we don't expect any parameters on the stack.

Somebody always brings this up when void main() comes up, and, while true, it isn't useful. People who use freestanding implementations generally know it. Given that this is a general programming forum not dedicated to any freestanding implementation, the OP didn't name any particular implementation, and the code in question uses <stdio.h> and no strictly conforming freestanding implementation is required to do anything sensible or even output-related with those functions, supposing a freestanding environment merely confuses the issue.

Offline

#16 2012-07-10 13:27:00

Trent
Member
From: Baltimore, MD (US)
Registered: 2009-04-16
Posts: 990

Re: A beginner's problems in C (exercises from K&R book)

exapplegeek wrote:

On the other side, speaking about "void main()" it caused me some confusion, but in the past, when I was coding in Xcode (back when I had OS X) it gave me some warning, and from that time till now, I thought that "void main()" was obsolete and replaced by "int main()". But now I see in the book that it is even possible to write it as "main()".

In C89, a function without an explicitly declared return type is implicitly int, so main() is the same as int main(). C99 got rid of the implicit-int rule, so under C99 you have to use int explicitly. It's good practice anyway.

void main() is a non-standard extension supplied by some compilers that gained popularity by being used by a number of popular reference books on C. It's not "obsolete" because it was never part of C in the first place.

Offline

#17 2012-07-10 16:00:18

holland01
Member
Registered: 2011-12-22
Posts: 50

Re: A beginner's problems in C (exercises from K&R book)

Trent wrote:

.
void main() is a non-standard extension supplied by some compilers that gained popularity by being used by a number of popular reference books on C. It's not "obsolete" because it was never part of C in the first place.

Interesting, I thought that was just some trash that was only MSVC compatible. For firmware/embedded systems it makes sense, but for a program being loaded into memory on an O.S.?

I honestly am GCC strictly guy; I'll MSVC occasionally, but that's usually if it's my only option.

Offline

#18 2012-07-12 00:21:50

Lux Perpetua
Member
From: The Local Group
Registered: 2009-02-22
Posts: 73

Re: A beginner's problems in C (exercises from K&R book)

exapplegeek wrote:

I have closed the thread on devshed, but will keep this open for further questions.

No need to go that far! You were getting some really good replies on Dev Shed. I'd say there's nothing wrong with cross-posting to multiple forums on different websites as long as you link to the cross posts. It saves people from wasting effort posting the same answer someone else posted on a different forum. smile

(Unfortunately, this level of etiquette is very rare. Typically, people not only cross-post their question all over the web, but they don't even bother to follow up when answers are posted.)

http://www.youtube.com/watch?v=v3rhQc666Sg

Last edited by Lux Perpetua (2012-07-12 00:22:29)

Offline

#19 2012-07-12 16:56:35

exapplegeek
Member
From: Macedonia
Registered: 2012-06-24
Posts: 36

Re: A beginner's problems in C (exercises from K&R book)

The exercise 1-13 is a bit complicated, and I don't know how to acheive one thing.
Exercise 1-13:

Write a program to print a histogram of the lengths of words in its input. It is easy to draw the
histogram with the bars horizontal; a vertical orientation is more challenging.

Here is my current code:

#include<stdio.h>

#define OUT 0
#define IN 1

main() {
   int c, i1, i2, nchar, ndigit, nword, state;

   nchar = ndigit = nword = 0;

   printf("Please enter word(s):\n");

   while ((c = getchar()) != EOF) {
	if (c == ' ' || c == '\n' || c == '\t')
		state = OUT;
	else if (state == OUT) {
		state = IN;
		++nword;
	}
	if (c >= '0' && c <= '9')
	   ++ndigit;
	if (c != ' ' && c != '\n' && c != '\t') {
	   ++nchar;
	}
   }
   putchar('\n');
   for (i1 = 0; i1 <= nword; ++i1) {
	putchar('|');
   	putchar('\n');
   }
   for (i2 = ndigit; i2 < nchar; ++i2)
	putchar('-');
   putchar('\n');
}

If my input is like this:

word1 word2 word3

It's output would be like this:

|
|
|
------------

What I am trying to acheive is at least this:

|----
|----
|----

Note: '|' - denotes a word; while '-' denotes its length.


Soli Deo Gloria!
I Stand Up For Christ! Do you?
________________________
Always have your stuff when you need it with Dropbox. Sign up for free (under my referral link)! http://db.tt/3rOCPK4r

Offline

#20 2012-07-12 18:32:53

null
Member
Registered: 2009-05-06
Posts: 398

Re: A beginner's problems in C (exercises from K&R book)

have a look on both for loops. For the moment the first one just prints every '|\n' and the second one produces '----' four times in a row. Just put them together and it should work (and save you some code wink ). *
And you really can make it work with just one variable. Try smile


* sorry, didn't look properly, there is a bit more to do which you'll see after you made the diagram work...

Last edited by null (2012-07-12 18:55:01)

Offline

#21 2012-07-12 18:41:29

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,330
Website

Re: A beginner's problems in C (exercises from K&R book)

The statistician in me just died a little: that's not a histogram.

Do you just want to graphically represent the length of words, or do you want an actual histogram?  For the latter you could do something following the logic:

1) create array of integers with length up to the max word-size you'd care about, for this example I'll call it counts[]
2) loop through the input counting (non-whitespace) characters until the first whitespace character, add one to the appropriate member of the above array (eg counts[count]++).
3) repeat (2) until end of input is reached
4) loop through counts displaying each value as a column with a height equal to it's value.

edit: some pseudo-code

decalare counts[MAX_WORDSIZE] as integer

while not end of input
    set count to 0
    get character
    while not whitespace
        increment count
        get character
    end while
    increment counts[count]
end while

for i in 1 to MAX_WORDSIZE
    print "|"
    for j in 1 to counts[i]
        print "-"
    end for
    print <newline>
end for

Last edited by Trilby (2012-07-12 18:46:49)


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#22 2012-07-13 05:07:15

OU812
Member
Registered: 2009-11-19
Posts: 47

Re: A beginner's problems in C (exercises from K&R book)

Trilby: Very nice solution. And written in pseudo-code. Since your solution employs nested loops, it makes me wonder if our student has been introduced to this structure yet. His solution, while not as elegant as yours, is really only missing this key idea.

john

P.S. I can't tell you how many times I've seen bar charts - clearly labeled with qualitative data - being described as histrograms. And in high school AP statistics books, they don't even show you how to create a histogram - everything is done on the TI-83. Just for fun, I show them how to do one by hand.

Offline

#23 2012-07-13 14:21:50

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,330
Website

Re: A beginner's problems in C (exercises from K&R book)

Mine also is hardly a histogram.  It is if there is a bin for each additional letter, which I suppose for human readable text is probably a good size.


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#24 2012-07-13 16:38:30

exapplegeek
Member
From: Macedonia
Registered: 2012-06-24
Posts: 36

Re: A beginner's problems in C (exercises from K&R book)

I have rewritten the code, following the advice of Trilby (but I didn't make it exactly like his solution), but it gives me some very long incorrect output.

Can you take a look and tell me what's wrong?

#include<stdio.h>

#define OUT 0
#define IN 1

main() {
   int c, i, j, nchar, ndigit, nword, state;
   int array[64];

   nchar = ndigit = nword = 0;

   printf("Please enter word(s) (max 64 chars):\n");

   while ((c = getchar()) != EOF) {
	if (c == ' ' || c == '\n' || c == '\t')
		state = OUT;
	else if (state == OUT) {
		state = IN;
		++nword;
	}
	if (c >= '0' && c <= '9')
	   ++ndigit;
	if (c != ' ' && c != '\n' && c != '\t') {
	   ++nchar;
	}
	++array[nchar];
   }
   putchar('\n');
   for (i = 1; i <= nword; ++i) {
	putchar('|');
	   for (j = ndigit; j < array[i]; ++j)
		putchar('-');
   	putchar('\n');
   }
}

Soli Deo Gloria!
I Stand Up For Christ! Do you?
________________________
Always have your stuff when you need it with Dropbox. Sign up for free (under my referral link)! http://db.tt/3rOCPK4r

Offline

#25 2012-07-13 17:04:11

ewaller
Administrator
From: Pasadena, CA
Registered: 2009-07-13
Posts: 20,334

Re: A beginner's problems in C (exercises from K&R book)

Initialize your array


Nothing is too wonderful to be true, if it be consistent with the laws of nature -- Michael Faraday
Sometimes it is the people no one can imagine anything of who do the things no one can imagine. -- Alan Turing
---
How to Ask Questions the Smart Way

Offline

Board footer

Powered by FluxBB