## Thursday, 13 January 2011

### The C Programming Language (K&R) 01x0A—Multiple Spaces—Exercise 1-09

I am making my way through the book “The C Programming Language” by Brian Kernighan and Dennis Ritchie aka K&R. You may wonder why I’m using 01x0A and the like for the title of the blogs. The book has eight chapters so the first part, 01, means chapter one. The x comes from C and it’s notation for hex numbers. 0A is hexadecimal for 10. The previous entry was 01x09, add one to get 01x0A.

We’re used to Arabic numerals 0 to 9 and the base-10 number system. That’s the default in C. If I write: x = 10; the compiler knows I’m referring to ten and not 2 from the binary system or 16 in hex. So any literal with a series of 0 to 9 is decimal, base 10. To tell the compiler it’s a hex number you start with ‘0x’ then your numbers.

// Decimal.
x = 10;

is the same as

// Hex.
x = 0x0A;

In both instances, x has the same value just a different numbering system.

You can follow the same approach with the octal system (base 8) but there’s no equivalent for entering a series of binary numbers. You’d have to write code to handle it.

An octal starts with zero (‘0’) then the number you want. So, x = 012 in octal is 10 decimal. I can’t say I agree with this setup, but that’s how it works. And other languages (Java, Ruby) have followed it.

More on negative numbers another time. It gets a bit ugly. Two-compliments and all. Negative ten in hex will show up as FFFFFFF6. Huh? It’s right, but this blog isn’t about that topic.

Exercise 1-09 from K&R

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

The concept is straight forward. Take some characters from the keyboard as entered by a user. Allow one space but not more than one. It’s easy to search for a space, that’s ASCII 32 or the character constant ‘ ’. Allow anything that is not a space and ignore a space if the previous character was a space.

The pseudocode might be:

while not EOF
if not a space, allow
if a space allow if previous character was not a space

That means we need to know what the previous character was and that means creating a variable to store the data.

Further, there’s the special case of the first character. It doesn’t have a previous character. So we initiate our variable with a value that is not a space and pretend it’s the previous character.

Looking at it this way, it won’t be hard to code.

The trick in using if statements within if statements is to make sure the else portion relates to the right if condition. Use brackets or null statements to create the right associations. Indenting is irrelevant to the compiler.

Sample Code #1.

I am using Visual C++ 2010 and creating the code as a console application.

// The standard library includes the system function.
#include <cstdlib>

// C++ standard I/O library
#include <cstdio>

// Replace multiple spaces with only one.
int main()
{
// Current keyboard input.
int c = 0;
// Previous keyboard input.
int prevCh = 0;

// Get input from keyboard.
while ((c = getchar()) != EOF) {

// Test if space.
if (c == 32) {
if (prevCh != 32)
// Allow space if previous char wasn't a space.
putchar(c);
}
// Without the brackets the else section
// will tie with 2nd if and the code won't work.
else
// Not a space, allow.
putchar(c);

// Store current character as previous.
prevCh = c;
}
// keep console window open
system("pause");

// return some value
return 0;
} // end main

Sample Code #2.

This sample varies the nested if statements by using a null else section to make sure the proper logic is executed.

// The standard library includes the system function.
#include <cstdlib>

// C++ standard I/O library
#include <cstdio>

// Replace multiple spaces with only one.
int main()
{
// Current keyboard input.
int c = 0;
// Previous keyboard input.
int prevCh = 0;

// Get input from keyboard.
while ((c = getchar()) != EOF) {

// Test if space (ASCII 32)
if (c == 32)
if (prevCh != 32)
// Allow space if previous char wasn't a space.
putchar(c);
else
; // Null statement
// Blank else stmt to keep lined up with ifs
else
// Not a space, allow.
putchar(c);

// Store current character as previous.
prevCh = c;
}
// keep console window open
system("pause");

// return some value
return 0;
} // end main

The output is the same.