Character Sketches

I l @ ve RuBoard

Character Sketches

Now let's look at something a little more decorative . The plan is to create a program that enables you to draw rough, filled-in figures by using characters. Each line of output consists of an unbroken row of characters . You choose the character and the starting and stopping positions for printing the character in the row. The program, shown in Listing 8.8, keeps reading your choices until it finds EOF . This program illustrates several programming techniques, which, of course, we'll discuss soon.

Listing 8.8 The sketcher.c program.
 /* sketcher.c  -- this program makes solid figures */ #include <stdio.h> #include <ctype.h> #define TRUE 1 #define FALSE 0 #define MAXLENGTH 80 int badlimits(int begin, int end, int limit); void display(char c, int first, int last); int main(void) {    int ch;              /* character to be printed      */    int start, stop;     /* starting and stopping points */    int badlimits();     /* returns TRUE for bad limits  */    printf("Enter character and column positions in this ");    printf("style: D 3 21\n");    while ((ch = getchar()) != EOF) /* read in character  */    {       if (isspace(ch))          continue;       /* skip newlines, spaces */       if (scanf("%d %d", &start, &stop) != 2)  /* read limits */          break; if (badlimits(start, stop, MAXLENGTH) == TRUE)          printf("Inappropriate limits were entered.\n");       else          display(ch, start, stop);    }    return 0; } int badlimits(int begin, int end, int limit) {    if (begin > end  begin < 1  end > limit)       return TRUE;    else       return FALSE; } void display(char c, int first, int last) {    int column;    for (column = 1; column < first; column++)        putchar(' ');    /* print blanks to starting point */    for (column = first; column <= last; column++)        putchar(c);      /* print char to stopping point   */    putchar('\n');       /* end line and start a new one   */ } 

The general structure is similar to that of Listing 8.6. The three main differences are these:

  • A continue statement is used to skip to the end of the loop if ch is whitespace, instead of isolating the relevant code with an if statement.

  • The display() function has been rewritten to display the character in a different manner. Here, first represents the first column and last represents the last column for displaying the character.

  • A badlimits() function has been added to screen out bad input values.

Suppose you call the executable program sketcher . To run the program, type its name , and then enter a character and two numbers . The program responds, you enter another set of data, and the program responds again until you supply an EOF signal. On a UNIX system using the % prompt, an exchange could look like this:

 % sketcher Enter character and column positions in this style: D 3 21  B 10 20  BBBBBBBBBBB  Y 12 18  YYYYYYY [Ctrl+D] % 

The program printed the character B in columns 10 to 20, and it printed Y in columns 12 to 18. Unfortunately, when you use the program interactively, your commands are interspersed with the output. A more satisfactory way to use this program is to create a file containing suitable data and then use redirection to feed the file to the program. Suppose, for example, the file fig contains the following data:

 _ 30 50  30 50  30 50  30 50  30 50  30 50 = 20 60 : 31 49 : 30 49 : 29 49 : 27 49 : 25 49 : 30 49 : 30 49 / 30 49 : 35 48 : 35 48 

The command sketcher < fig produces the output shown in Figure 8.3. (If you use the program with data from a file, you may as well omit the two printf() statements providing the original instructions.)

Figure 8.3. The output of the character sketch program.
graphics/08fig03.gif

Note

Printers and screens have different values for the vertical-to-horizontal ratio for characters. This difference causes figures of this sort to look more compressed vertically when printed than when displayed on a screen.


Analyzing the Program

The sketcher.c program is short, but it is more involved than the examples we have given before. Let's look at some of its elements.

Line Length

We limited the program to print no farther than the 80th column because 80 characters is the standard width of many video monitors and of regular-width paper. However, you can redefine the value of MAXLENGTH if you want to use the program with a device having a different output width.

Program Structure

We've followed a modular approach, using separate functions (modules) to verify input and to manage the display. The larger a program is, the more vital it is to use modular programming.

The main() function acquires the data:

 while ((ch = getchar()) != EOF) {   if (isspace(ch))      continue;                           /* skip newlines, spaces */   if (scanf("%d %d", &start, &stop) != 2)  /* read limits */      break; 

With Listing 8.7, we discussed the rationale for skipping whitespace. Next, the program checks to see whether the input makes sense:

 if (badlimits(start, stop, MAXLENGTH) == TRUE)    printf("Inappropriate limits were entered.\n"); else    display(ch, start, stop); 

The purpose of the if else statement is to let the program skirt any values of start and stop that would lead to trouble. We will discuss the details of the badlimits() function later. The important point here is that it returns a value of TRUE if the data fails to pass the testing procedure. In that case, the computer prints a message and skips over the else part, which is the display output.

The display() function uses one for loop to print spaces up to where the character is first to appear. The second for loop then prints the character from the start column to the end column. Finally, it prints a newline to end the line.

 void display(char c, int first, int last) {    int column;    for (column = 1; column < first; column++)        putchar(' ');    /* print blanks to starting point */    for (column = first; column <= last; column++)        putchar(c);      /* print char to stopping point   */    putchar('\n');       /* end line and start a new one   */ } 
Error-Checking

Getting the user to supply data in a form the computer can use properly is a pervasive problem. One technique is to use error-checking. In this technique, the computer checks the data to see if it is okay before using it. We have included a beginning effort at error-checking in this program with the badlimits() function:

 int badlimits(int begin, int end, int limit) {    if (begin > end  begin < 1  end > limit)       return TRUE;    else       return FALSE; } 

What is the badlimits() function protecting against? First, there's no sense having the starting position come after the final position. Terminals normally print from left to right, not vice versa, so the expression begin > end checks for that possible error. Second, the first column on a screen is column 1 . You can't write to the left of the left margin, so the begin < 1 expression guards against making an error there. Finally, the expression end > limit checks to see that you don't try to print past the right margin.

Are there any other erroneous values you could give to begin and end ? Well, you could try to make begin greater than limit . Would that pass the test? No. It's true you don't check for this error directly. However, suppose begin is greater than limit . Then, either end is also greater than limit ”in which case that error is caught ”or else end isn't greater than limit . If end is less than limit , it must also be less than begin . Therefore, this case gets caught by the first test. Another possible error is that end is less than 1 . We leave it to you to make sure this error doesn't sneak through, either.

We kept the test pretty simple. If you design a program for serious use, you should put more effort than we did into this part of the program. For instance, you should put in error messages to identify which values are wrong and why, perhaps injecting your personality into the messages. Here are some possibilities:

 Your value of 897654 for stop exceeds the screen width. Oh my! Your START is bigger than your STOP. Please try again. THE START VALUE SHOULD BE BIGGER THAN 0, HONORED USER. RED USER. 

The personality you inject, of course, is up to you.

Another input problem occurs if letters show up when scanf() expects numbers. As the program is set up, letters cause the program to terminate, which is preferable to it getting stuck or misinterpreting input. It's also possible to have scanf() skip over data it can't read; we'll show the technique in Chapter 9, "Functions."

I l @ ve RuBoard


C++ Primer Plus
C Primer Plus (5th Edition)
ISBN: 0672326965
EAN: 2147483647
Year: 2000
Pages: 314
Authors: Stephen Prata

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net