📄 cnews018.doc
字号:
Here is the code as it was published in the second column of
this series:
Issue C News 8
/* GET_DATA.C */
/* 2. Get any quantity of numbers from a file. To simplify the
problem, we will initially use four numbers hardcoded into
the program. As this column progresses, these
simplifications will be removed. */
float get_data()
{
float sum_x=0.0;
sum_x += 1.0; /* Start here*/
sum_x += 2.0;
sum_x += 3.0;
sum_x += 4.0; /* End here*/
/* Now is the time to return back to the main program. */
return(sum_x);
}
The first order of business is to get rid of the restriction
that we placed at the top of the column. We're going to read in
the four numbers from a file. If there are less than four
numbers present, the program should do what? If there are more
than four numbers, the extras will be ignored. We'll use some
of the techniques developed in the last column on reading a
file. (I've also modified the header at the top of the file,
initially we were going to read the keyboard, now we're using a
file. The same principles apply in both cases.)
I'm going to map out what is going to take place first in
pseudo-code in an attempt to get you to develop good programming
habits.
Basic function declaration - describe what the function is supposed to do
Any #include statements that will be needed
Declare the function - include the pointer variable
Declare memory needed for the file
Declare the variables that be used, the total & the
intermediate variable
(passed from the calling routine)
Open the file for reading, check for error on opening
Setup a loop that will execute until a 'stop value' is
encountered (in this case a negative number)
Read in a number into an intermediate variable
Add the intermediate variable to the total
Increment the counter that indicates the number of
samples read in
Terminate the loop
Decrement the counter (remember we incremented the counter
before we checked the validity of the entry)
Subtract the 'stop value' from the total
Close the file
Issue C News 9
Return the sample size as a passed variable & the total in the
function call
Now for the C code to implement this pseudocode:
/* GET_DATA.C */
/* Read in any quantity numbers from a file - stop on negative numbers */
/* Data passed to this function: address of the variable to hold the */
/* sample size */
/* Data returned from this function: The sum of the series of real */
/* numbers */
#include <stdio.h>
float get_data(int *samp_size_ptr)
{
FILE *in_file; /* declare an area for a file */
float sum_x = 0.0; /* THIS WAS IN THE ABOVE CODE */
float in_val; /* declare an intermediate */
/* variable to be read in */
if ((in_file = fopen ("mydata.dat", "r+t")) == NULL)
{
printf ("Oops, I don\'t see the data file\n");
exit(1);
}
do { /* set up a loop to read in the file */
fscanf (in_file, "%f", &in_val); /* read the file */
sum_x += in_val; /* add the value to the old sum */
(*samp_size_ptr)++; /* increment the counter */
} while (in_val >= 0);
(*samp_size_ptr)--; /* we have to decrement this because */
sum_x -= in_val; /* tried to read in the stop number */
/* and add in the stop number to the sum */
fclose (in_file); /* close the file */
return (sum_x); /* return the sum to the main */
/* program */
}
That's the new version of the GET_DATA routine. There are
a number of unusual things in this function. First is the
function declaration itself. Notice that in the parentheses is
what looks like a variable declaration with an asterisk in front
of it. That is how you declare a pointer. In this specific
case, I've declared that the variable, samp_size_ptr, is in
reality a 'pointer' to a location in memory, and that this
memory location is to contain an integer. The next odd thing
that the keen eyed reader will spot is the backslash 't' in the
printf expression that will be printed if the data file couldn't
Issue C News 10
be opened. There has to be way to put non-printing characters
into a string and it is done with escape sequences that begin
with the backslash. An abbreviated list of these is included
below for quick reference:
Sequence Action
\a Audible bell - this is an ANSI extension
\b Backspace
\f Formfeed
\n New line
\t Horizontal tab
\' Apostrophe or Single quote
\" Double quote - this is an ANSI extension
\? Question mark
The next thing you might ask yourself is why don't we just use
the GET_DATA routine to get the data from the file and return
the value to the calling routine and let it (the calling
routine) decide what to do next (get more data, proceed with the
computations, etc.)? That's logical (it modularizes the code,
etc.), but unfortunately it also defeats one of the main things
that I'm going to show you in the near future, so I'm going to
keep this slightly illogical organization.
You may also notice the '&' in the fscanf function call.
By the way, you may also have noticed that all of the function
oriented to files start with an 'f' (i.e. fopen, fscanf, fclose,
etc.), this is by design, not chance and is part of the ANSI
standard. This symbol tells the compiler to generate
instructions to the computer to pass the address of the variable
to the function instead of the variable itself. This
arrangement is termed "pass-by-reference".
The last thing that I hope you noticed actually consists of
two things, that of (*samp_size_ptr)++ and (*samp_size_ptr)--.
Let's dissect this example carefully to find out what is going
on. First the statement [ *samp_size_ptr ] inside of the
parentheses is executed, this retrieves the value stored at that
location in memory. Then that value is incremented (or
decremented as the case may be), and the value is stored back at
the same location in memory.
The main program file also changes (in three small ways):
Issue C News 11
#include <stdio.h>
float get_data (int *to_samp_size); /* <<--- this changed */
float compute (int samp_size, float x_sum);
void print_results (float average);
main ()
/* This program is to find the mean (average) and standard
deviation of a series of numbers. The numbers will be read in
from the keyboard and printed on the screen. Enter -1 when
finished. Temporarily simplified and reading from a file instead */
/* initialization of variables */
/* 1. Declare all variables needed and initialize them to zero.*/
{
int samp_size=0; /* samp_size: number of variables read in*/
float sum_of_x=0; /* this is the sum of the variables read in*/
float answer;
/* get the data needed by the program */
sum_of_x = get_data(&samp_size); /* <<--- this changed */
/* <<--- deleted a line here */
/* Now compute the answer */
answer = compute(samp_size, sum_of_x);
/* Print the results out */
print_results (answer);
/* Closing the brace on the main routine exits the
program. There are other ways out, but this way will do for
now.*/
}
As I said before, three things have changed in the main
program. The first thing is that the function prototype now
contains a reference to a variable that I've called
'to_samp_size'. Remember that name of the variable isn't
critical (as long as it makes sense to you and helps you
remember what the variable is for). In this case the variable
is to receive an address. The next thing is the '&' in my call
to the function called 'get_data'. This means that I want to
pass not the variable, but the ADDRESS of the variable to the
function. The next line, the line that used to set 'samp_size'
to a quantity is no longer needed.
The other three files (COMPUTE.C, PRINTRES.C & AVERAGE.PRJ) are
included here for completeness. In the file called COMPUTE.C:
Issue C News 12
/* This is the function that determines the average of a bunch
of numbers */
float compute (int n, float xsum)
{
return (xsum/(float)n);
}
In the file called PRINTRES.C:
/* This function prints out the average of the numbers that have
been entered or read in */
void print_results (float average)
{
printf ("\nThe average of the four numbers is:%f\n", average);
return;
}
In the file called AVERAGE.PRJ:
average
get_data
compute
printres
Issue C News 13
=================================================================
TOGGLES AND COMMAND-LINE PARSING by Paul E. Castle II
=================================================================
Every beginners book on C starts out the same way. It
teaches you how to print "Hello, world" on the screen. From
that point on they all follow essentially the same path, the
only real difference being the author's ability to entertain and
teach at the same time. These books teach the basics of the C
language and programming. They give you something upon which to
build. This education is extended and enhanced in the pages of
intermediate and advanced texts. These texts cover topics that
range from random number generators, sort/search algorithms, and
linked lists to complete menuing systems and serial port I/O.
However, there seems to be a gap between the beginner and
intermediate texts, an area of routines and techniques slightly
beyond the beginner's needs and slightly beneath the needs of
the intermediate programmer.
One such case came to my attention while coding a video
tape library program (VTL from this point forward). VTL is a
windowed application. I thought that exploding windows (windows
that seem to explode from the center of the screen out) would be
a nice touch. After a while, however, exploding windows can
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -