When you have a variable x and you want a pointer to it, use &x.
When you are declaring a variable p, and you want that variable to be a pointer, use *p.
int *pInt; /* declares pointer pInt to variable of type int */
int *pChar; /* declares pointer pChar to variable of type char */
Generally, &x will occur in argument-lists in invocations and *p will appear in assignment statements and declarations of parameters in functions.
The second form would follow the examples in the stringExtras
module. But, in either case, don't try to invoke the function
on the right-hand-side of an assignment statement. Simply use
the function as a command, by itself, in the same way that you
have been using the strcpy and strcat functions.
Example invocations:
You only need to compile
the stringExtras module once (gcc -ansi -c stringExtras.c), no matter
how many times you recompile your program. But, you'll need to to the
link step (gcc -lm yourProg...) every time you recompile your
program.
The explanation under the "compile and run" link in the style guide
for this project went to the wrong place. That's been fixed now.
Also, I've updated the explanation in the Project 9 write-up on the
web of the string functions (from the intrinsic string module and from
the supplied module stringExtras) to make it more clear how to use the
functions from the stringExtras module.
Tom Wolfe, in his book on astronauts (The Right Stuff),
points out a similar conceit in fighter pilots.
Many of the early jet fighters had landing speeds that were
too high for safe operation. There were lots of crashes, and the
pilots who hadn't (yet) crashed
comforted themselves with the belief
that it wouldn't happen to them if they were just careful.
Turns out, the luck element was a little higher than they allowed
themselves to think.
The time of people using the software is even more important, of course,
since (one hopes) there will be more of them than were on the team
that developed the software. But, programmers almost never know in
advance which details of their codes need to be efficient.
After they've gotten the code working properly, they can use tools
such as time and memory profilers to find out which components
to optimize.
This course focuses on what programmers need to do first.
Subsequent courses will address efficiency issues.
If there is a role for debuggers, it is in verifying hypotheses,
formed during code inspection,
about the defects that trigger observed symptoms of errors.
Debuggers cannot
effectively take the place of code inspection, regardless of your
experience.
Arrays are an important aspect of C and will be covered in this
course, along with appropriate examples of their use. Project 9
provides no such examples.
I require that programs submitted in completion of Project 9
remain independent of the particular implementation of the string
abstraction that C has chosen. To do this, you must use string
functions to analyze strings, and you must avoid the use of
array operations, such as subscripting.
Arrays are usually defined as sequences whose lengths are fixed at the
time of declaration. This makes the array abstraction a poor choice
for implementing strings, or for any type of sequence demanding
operations such as concatenation, insertion, and deletion that lead to
flux in the length dimension over the course of the computation.
The designers of C chose to represent strings as arrays almost three
decades ago. Probably, they made this choice because the array
representation uses memory economically. They made their decision at a
time when fast-access memory, even on the most advanced computers, ran
at a few megahertz and when that memory, even on the cheapest systems,
cost tens of thousands of dollars per megabyte. (Actually, you
couldn't really get memory by the megabyte -- it came by the kilobyte
at that time.)
So, it was crucial in those days to use memory with great care.
Software people spent much of their time (well over half, I believe),
figuring out how to conserve it in their programs, or getting around
the problems caused by their attempts to conserve it.
Unfortunately,
these habits persist to the present day, when they are rarely
justified on an economic basis. When you take your first professional
position in computer science, they will be justified even less often.
For this reason, you will be better rewarded for learning well the
principles of abstraction on which good software is constructed than
for fiddling around with memory conservation excersises.
There are thousands of people in the programming business whose
level of understanding of the principles of computer science does
not encompass these principles.
They hack out defect-ridden, unmaintainable
software with alacrity.
The university is attempting to educate a new generation of computer
scientists who appreciate the difficulty and importance of producing
well-organized software grounded those few principles that have come
to light in the short history of the discipline. I hope that you
will be a literate and contributing member of that new generation.
But, there is no reason to compute e in this problem.
It doesn't matter what log base you use, as long as you use
the same base to compute constants that you use
in the model that estimates time (after you plug in the
constants).
To fix your PC file so it will work on Unix, get into Hugs and
load the removeBS.hs program (from Supplied Software on the web site).
The enter Hugs command
Now you should be able to run the C compiler against yourProgram.c
Software designers should transfer from people to computers as much as
possible of the work required to carry out the task at hand. Computers
should serve people, not the other way around. The job of the software
designer is to make computers into effective helpers, or even obsequious
servants if that pleases the people using the software. This is especially
important if the people using the software have the misfortune to be stupid,
which most people aren't, of course. Software designers certainly
must not allege stupidity in other people as a smokescreen to
hide laziness in the software development process.
You might ask why the picture was constructed this way in
the first place: turns out its easier to build it upside
down, less complicated counting.
Programming in its purest form (and you are learning it in
its purest form) involves a lot of deep thought and, for most
problems, a few crucial insights. It is not mechanical. It is
a creative process that has more in common with, say, proofs
in geometry or factorization in algebra than with routine
grinding such as long division in arithmetic or finding
derivatives in calculus.
Then, when you get a leg up on the creative process
and put together a draft of your program, you can start
the easy part:
fighting your way through all those worthless error messages
-- very frustrating, but not as scary
as the creative part.
Creative
work is always scary because you never know when the
insight will come. It's a real kick when it does, though.
Bon appetit!
You could use the Haskell
type Rational to address the problem, but I don't
recommend that approach.
The problem is not with the terms themselves.
The quotient x^n/n! is small enough for the floating
point system on your computer. It's just that the
numerator and denominator are too big, so you can't
compute the quotient in the ordinary, straightforward
way.
You will need to do some algebra on x^n/n!, to find
a way to compute that value without getting
intermediate results in the stratosphere.
In this particular case, your difficulties
probably involve a misunderstanding
of the specificationss for the display function.
It must be a function
with one argument, a string, and it must deliver a string as
its value.
And, you must insert your definition of the display function and
all the other functions you define (that is, 2A-2E + others you
define) in the framework script from Supplied Software.
So, in the framework script, where it says
One way to test to see if you're anywhere close to the right idea
is to test it out by using the definition
THIS:
LIKE THIS:
The reason for this is that Haskell uses indentation level to
mark the beginning and end of definitions. Older languages
use special markings for this purpose, such as matching
brackets ({...} or begin...end) or separators (usually semicolons).
But, good programmers always use indentation to visually
delineate program segments. Bracket and separator marks are
redundant when programs are properly indented. So, Haskell
avoids the visual clutter of bracket and separator marks
by relying solely on indentation.
Now, about those semicolons ...
Strictly speaking, there is no such thing as a hardcoded argument.
Either there is a parameter to allow variation or there isn't.
The question makes me
suspect you that you are trying to do some things that won't work,
such as associating the contents of the file, or
some transformation of its contents, with a name that you will
use elsewhere in your script.
This won't work. You must write a function called
displayDictionSignature
that has one parameter. That parameter will be a string,
and the framework script provided for Team Project A
invokes the function displayDictionSignature with an
argument that is associated with the contents of the
file McCarthy.txt. Those contents are represented as a
Haskell String. You have no choice about this.
In fact, you can't. When you write
So, Hugs thought you were trying to define a function named "def".
Then, when you tried to use the function "remove," it
didn't know what you were talking about.
So, run it on an HP. You wil need to run everything this
semester on an HP. You can do some work on PC Hugs if you
have your own computer, but the final version to be handed
in must be on an HP.
Alas. There just isn't any suitable Hugs available on the
alphas right now. There may be in a few weeks, though.
Watch this space.
Beware!
Don't accidently use a terminal windown on the HP in which
you are running a telnet session with a DEC Alpha.
kennedy% gcc -ansi -c date.c
date.c: In function `f':
date.c:49: warning: return makes integer from pointer without a cast
It's referring to the following part of my code:
char f(char month[100]){
... other statements ...
return (month);
}
(1) Declare f like this: void f(char month[100]), and don't
put a return statement in the function.
(2) Or declare it like this: char *f(char month[100]),
and put in a return statement like the one you're using now
(observe the asterisk preceding the name of the function).
char x[100];
...
strcpy(x, "some stuff");
strcat(x, " ... other stuff ...");
f(x);
...
gcc -ansi -c stringExtras.c
gcc -ansi -c yourProgram.c
gcc -lm yourProgram.o stringExtras.o
a.out
Example:
const char s[] = "some string";
char t[100];
strcpy(t, s); /* at this point, t[] is "some string" */
strcap(t); /* at this point, t[] is "SOME STRING" */
Dear person,
The input you have given me is not in a form that my
designer has made it possible for me to understand.
I wish I could tell you exactly what is wrong with it,
but I really don't know. About all I can do effectively
is process input that my designer anticipated. Outside of
that territory, I get lost fast. I'm truly sorry about
this state of affairs, but I'm just too ignorant to do
any better. I hope you will be able to transform your
input into something that I can recognize and help you
with. I truly want to help, but I just don't know how.
Best wishes for a happy future,
Your humble computer system
In other words, all the error message tells you is that there
is something wrong. You'll have to dig in and figure out what it is.
.
.
.
your definition(s) go here
.
.
.
you replace those lines with the definitions of the functions
you have constructed.
> displayDictionSignature textString = textString
intead of the one you've put together. This definition has the
right type: if it is supplied a string as an argument, it will
deliver a string as a value - not the right string for this
problem, but at least something that will let you gain confidence
that you understand how to use the framework script.
> variableOne = ...
> functionTwo xs = ...
NOT THIS:
> variableOne = ...
>functionTwo xs = ...
If a particular definition covers more than one line
(and some of your definitions will), then all lines
beyond the first line a the multi-line definition must
be indented beyond the first line.
> displayDictionSignature textString =
> second line starts here
> third line starts here (or could be indented further)
> fourth line starts here (could be indented more or
> less than third line, but must be indented further
> than first line of definition)
> next definition starts at same indentation as other first-lines ...
Haskell has an alternate source form that uses semicolons
as separators. This form is more compact, so Hugs translates
what you write into the compact form (with semicolons)
before it interprets your program. When your script is
indented improperly, extra semicolons get inserted in
places where they unexpected. You should interpret the
"unexpected semicolon" error message as an indication
that your indentation is messed up at some point.
When I load it has a script there are no errors. But, when I
run the function it returns the error "remove not a defined
variable." That doesn't make any sense, does it?
you are defining a function named def with parameters f and x.
If you want to define a function named f with one parameter,
you should write
CaptainAhab@mobydick.org -- for example
Or, maybe the instructor recorded the wrong address. Send him a note
with your address, and ask him to check.