stevepedwards.com/DebianAdmin linux mint IT admin tips info

Chapter 7 Notes – Practical C Programming, 3rd Edition By Steve Oualline

Chapter 7 takes you through all the necessary steps to create a simple program from specification through release. Structured programming, fast prototyping, and debugging are also discussed.

It's just a simple matter of programming.

Any boss who has never written a program

The major steps in making a program are:

Requirements. Programs start when someone gets an idea and starts to implement it. The requirement document describes, in very general terms, what is wanted.

Program specification. The specification is a description of what the program does. In the beginning, a preliminary specification is used to describe what the program is going to do. Later, as the program becomes more refined, so does the specification. Finally, when the program is finished, the specification serves as a complete description of what the program does.

Code design. The programmer does an overall design of the program. The design should include major algorithms, module definitions, file formats, and data structures.

Coding. The next step is writing the program. This step involves first writing a prototype and then filling it in to create the full program.

Testing. The programmer should design a test plan and then use it to test his program. When possible, the programmer should have someone else test the program.

Debugging. Unfortunately, very few programs work the first time. They must be corrected and tested again.

Release. The program is packaged, documented, and sent out into the world to be used.

Maintenance. Programs are never perfect. Bugs will be found and will need correction. This step is the maintenance phase of programming.

Revision and updating. After a program has been working for a while, the users will want changes, such as more features or more intelligent algorithms. At this point, a new specification is created and the process starts again.

For this chapter, we assume that we have the requirement to "write a program that acts like a four-function calculator."

We implement the smallest portion of the specification that will still do something. In our case, we will cut our four functions down to a one-function calculator. After we get this small part working, we can build the rest of the functions onto this stable foundation.

calc1.c

#include <stdio.h>

char line[100];/* line of data from the input */

int result;

char operator; /* operator the user specified */

int value;

/* the result of the calculations */

/* value specified after the operator */

int main()

{

result = 0; /* initialize the result */

/* Loop forever (or till we hit the break statement) */

while (1)

{

printf("Result: %d\n", result);

printf("Enter operator and number: ");

fgets(line, sizeof(line), stdin);

sscanf(line, "%c %d", &operator, &value);

if (operator = '+') /*mistake here! Should be == remember? If not, then next else does not happen */

{

result += value;

}

else

{

printf("Unknown operator %c\n", operator);

}

}

}

So far, we only recognize the plus ( +) operator. As soon as this operator works correctly, we will add more operators by adding more if statements.

Finally, if an illegal operator is entered, the line:

} else {

printf("Unknown operator %c\n", operator);

}

writes an error message telling the user that he made a mistake.

So far this prog treats any other operator as a + only, and does not printf("Unknown operator %c\n", operator);

$ ./calc

Result: 0

Enter operator and number: +1

Result: 1

Enter operator and number: +2

Result: 3

Enter operator and number: x

Result: 5

Enter operator and number: x5

Result: 10

Enter operator and number: /5

Result: 15

Enter operator and number: q

Result: 20

Enter operator and number: ^C

This is fixed with the == added, but should not be done yet so the insight to the Makefile section debugs it for you...but so you know what the prob is here...:

$ ./calc

Result: 0

Enter operator and number: +1

Result: 1

Enter operator and number: +1

Result: 2

Enter operator and number: x3

Unknown operator x

Interesting insight into a Makefile's structure:

The make utility is responsible for one of the nastiest surprises for unsuspecting users. The line:

$(CC) $(CFLAGS) -o calc1 calc1.c

must begin with a tab. Eight spaces won't work. A space and a tab won't work. The line must start with a tab. Check your editor and make sure that you can tell the difference between a tab and bunch of spaces.

http://www.gnu.org/software/make/manual/make.html

Note this copies incorrectly from the PDF due to formatting:

File: calc1/makefile.gcc

#-----------------------------------------------#

#

#

Makefile for UNIX systems

#

using a GNU C compiler

#

#-----------------------------------------------#

CC=gcc

CFLAGS=-g -D__USE_FIXED_PROTOTYPES__ -ansi

#

# Compiler flags:

# -g

-- Enable debugging

# -Wall

-- Turn on all warnings (not used since it gives away

#

#

the bug in this program)

-D__USE_FIXED_PROTOTYPES__

#

#

-- Force the compiler to use the correct headers

-ansi

-- Don't use GNU extensions.

Stick to ANSI C.

calc1: calc1.c

$(CC) $(CFLAGS) -o calc1 calc1.c

clean:

rm -f calc1

Should look like this in vi??:

To run the makefile understand make a bit first:

man make

To prepare to use make, you must write a file called the makefile that describes the rela‐

tionships among files in your program, and the states the commands for updating each file.

In a program, typically the executable file is updated from object files, which are in turn

made by compiling source files.

Once a suitable makefile exists, each time you change some source files, this simple shell

command:

make

-f file, --file=file, --makefile=FILE

Use file as a makefile.

-d Print debugging information in addition to normal processing.

stevee@AMDA8 ~/Cprogs/calc1 $ ls

calc.c makefile

Seems to have a problem..:

$ make

make: *** No rule to make target `calc1/makefile', needed by `calc1'. Stop.

Have to come back to that...

Most systems have C debugging programs; however, each system is different.

Some systems have no debugger. In such a case, we must resort to a diagnostic print statement. The technique is simple: put a printf at the points at which you know the data is good (just to make sure the data is really good). Then put a printf at points at which the data is bad. Run the program and keep putting in printf statements until you isolate the area in the program that contains the mistake.

It's good to re-arrange the brackets to suit your clarity preference then comment each function so you write it in your own way you understand what each is doing, as I tried below:

/**calc2.c*/

#include <stdio.h>

char line[100]; /* line of text from input */

int result; /* the result of the calculations */

char operator; /* operator the user specified */

int value; /* value specified after the operator */

int main()

{

result = 0; /* initialize the result */

/* loop forever (or until break reached) */

while (1)

{

printf("Result: %d\n", result); /*result matches int decl.*/

printf("Enter operator and number: ");

fgets(line, sizeof(line), stdin); /*puts chars in line array; counts chars; from keys*/

sscanf(line, "%c %d", &operator, &value); /*op and value matches char and int decl.*/

if ((operator == 'q') || (operator == 'Q')) /*for caps lock on: either Qq input*/

break;

if (operator == '+')

{

result += value;

}

else if (operator == '-')

{

result -= value;

}

else if (operator == '*')

{

result *= value;

}

else if (operator == '/')

{

if (value == 0) /*final nested if else for div by 0 BEFORE op /: Why not have another elsif for a 0 input at end of all these ???*/

{

printf("Error:Divide by zero\n");

printf("operation ignored\n");

}

else

result /= value;

}

else

{

printf("Unknown operator %c\n", operator);

}

}

return (0);

}

It looks much nicer zoomed out in VIM to fit all, with a yellow BG:

We expand our test plan to include the new operators and try it again:

+ 123 Result should be 123

+ 52

x 37 Result should be 175

Error message should be output

- 175 Result should be zero

+ 10 Result should be 10

/ 5 Result should be 2

/ 0 Divide by zero error

* 8 Result should be 16

q Program should exit

While testing the prog ram, we find that, much to our surprise, the program works.

The word "Preliminary" is removed from the specification, and the program, test

plan, and specification are released.

This programme works to the test plan for all the functions designed for: (0+-*/qQ and ignoring non integers). Now there is the stable base for adding functionality.

$ ./calc2

Result: 0

Enter operator and number: +2

Result: 2

Enter operator and number: -1

Result: 1

Enter operator and number: *3

Result: 3

Enter operator and number: /1.5 /*missed out from PDF test plan… */

Result: 3

Enter operator and number: /3

Result: 1

Enter operator and number: /0

Error:Divide by zero

operation ignored

Result: 1

Enter operator and number: *10

Result: 10

Enter operator and number: /2

Result: 5

Enter operator and number: -3

Result: 2

Enter operator and number: Q

Electronic archaeology is the art of digging through old code to discover amazing things (like how and why the code works).

Unfortunately, most programmers don't start a project at the design step. Instead, they are immediately thrust into the maintenance or revision stage and must face the worst possible job: understanding and modifying someone else's code.

Your computer can aid greatly in your search to discover the true meaning of someone else's code. Many tools are available for examining and formatting code.

Some of these tools include: ...are pretty obsolete for this PDF!

Text Editor: One of the best tools for going through someone else's code is your text editor.

Suppose you want to find out what the variable sc is used for. Use the search command to find the first place sc is used...you can easily do a global search and replace to change sc to sequence_counter. (Disaster warning: Before you make the change, make sure that sequence_counter is not already defined as a variable or part of another declaration!!

Take a printout of the program and make notes all over it. Use red or blue ink so that you can tell the difference between the printout and the notes. Use a highlighter to emphasize important sections. These notes are useful; put them in the program as comments, then make a new printout and start the process again.

Exercise 7-1 : Write a program to convert English units to metric (i.e., miles to kilometers, gallons to liters, etc.). Include a specification and a code design.

Exercise 7-2: Write a program to perform date arithmetic such as how many days there are between 6/6/90 and 4/3/92. Include a specification and a code design.

Exercise 7-3 : A serial transmission line can transmit 960 characters each second.

Write a program that will calculate the time required to send a file, given the file's size. Try the program on a 400MB (419,430,400 -byte: 400 x 1024 x 1024b) file. Use appropriate units.

Exercise 7 -4 : Write a program to add an 8% sales tax to a given amount and round the result to the nearest penny.

Exercise 7-5 : Write a program to tell if a number is prime.

Exercise 7-6 : Write a program that takes a series of numbers and counts the number of positive and negative values.

Comments are closed.

Post Navigation