| ex1.c | fib.h | fib.c |
#include <stdio.h>
#include "fib.h"
int main()
{
int n;
fscanf(stdin,"%i",&n);
fprintf(stdout,"f(%i) = %i\n",n,fib(n));
return 0;
}
|
int fib(int n); |
#include "fib.h"
int fib(int n)
{
if (n < 2)
return 1;
else
return fib(n-1) + fib(n-2);
}
|
Most of your programs for this class will be single file programs, but we're starting out with multiple files because it's important that you understand the process. Creating a program consists of two phases: compiling and linking.
bash$ gcc -c ex1.c ← compiles source code file ex1.c to object code file ex1.o bash$ gcc -c fib.c ← compiles source code file fib.c to object code file fib.o bash$ gcc -o lab3p0 fib.o ex1.o ← links ex1.o and fib.o into the executable file lab3p0Each source code file gets compiled into an object code file, which is a compiled chunk of an actual program. This is the compilation phase. In the link phase, all these chunks of compiled code get put together to create an actual program. This includes linking in object code for standard libraries, like stdio or stdlib.
From the perspective of a little programmer, it might seem like a pain that each file gets compiled separately. However, imagine you're a developer for MS Word ... there are thousands of source files, and you just fixed a type in one. Do you want to wait hours for everything to compile? No, just recompile the one file you changed when you fixed the typo, and leave the rest unchanged. Then relink --- which is lots faster than compiling --- and you're done. This is referred to an incremental compilation.
After than pep talk about incremental compilation, here's a trick to speed things up. The one line
bash$ gcc -o lab3p0 ex1.c fib.cis exactly equivalent to the three lines above. So for small programs, you usually just create the program this way.
~wcbrown/bin/httpcat www.engr.udayton.edu/faculty/jkissock/gsod/ILCHICAG.txtfor Baltimore do this:
~wcbrown/bin/httpcat www.engr.udayton.edu/faculty/jkissock/gsod/MDBALTIM.txtYour ultimate job is to write a program that takes a temperature range as command-line arguments and reads data in this average-daily-temperature format. For example, here are the days in LA with an average temp above 80:
bash$ ~wcbrown/bin/httpcat www.engr.udayton.edu/faculty/jkissock/gsod/CALOSANG.txt | lab3p1 80 100 9 3 1998 84.600000 9 29 2005 80.500000 10 24 2007 80.800000 4 27 2008 81.500000 6 22 2008 80.300000 10 1 2008 81.100000
month (whitespace) day (whitespace) year (whitespace) temperature (newline)and prints out to standard output all lines whose temperature is between 10 and 20 degrees.
bash$ ~wcbrown/bin/httpcat www.engr.udayton.edu/faculty/jkissock/gsod/MSJACKSO.txt | lab3p1 2 3 1996 17.900000 2 4 1996 15.100000 2 5 1996 19.800000Make sure you compile and test this! This part doesn't take much more than fprintf, fscanf, and a loop!
bash$ ~wcbrown/bin/httpcat www.engr.udayton.edu/faculty/jkissock/gsod/MSJACKSO.txt | lab3p1 10 22 2 3 1996 17.900000 2 4 1996 15.100000 2 5 1996 19.800000 1 24 2003 21.100000 1 9 2010 21.100000Command line arguments in a C program are, of course, totally new. So here's a word of explanation. If, instead of defining
main as "int
main()"
you define it like this:
int main(int argc, char **argv)the argument
argc gets set to the number of
elements in the process's argv vector
and argv is ... well, it's the
processes argv vector. Remember, if you
call the program like this:
bash$ lab3p1 10 20then
argv[0] = "lab3p1", argv[1] =
"10",
and argv[2] = "20". So argv
is an array of strings, and in C strings are arrays
of chars, thus the type
of argv is char**. It's an
array of arrays of char.
Now, argv[1] and argv[2]
are strings, but they're strings that represent
numbers. What we need is a way to convert a string
representing the number to the actual number. For
type int, this funciton
is atoi. For type double it
is atof. Use man and you should be able
to figure out how they work. Don't forget to actually
test this!
lab3p1: Error! Not enough arguments!and exits with return value 1. Remember, this is an error, so it has to be printed to stderr, not stdout. [Note: when your program does this, if you are running it with its input piped from
httpcat's output, you'll also get some
error messages from httpcat.] Assuming you
saved the MSJACKSO.txt data in a file
named tmp, here are some example runs:
bash$ cat tmp | lab3p1 Error: too few arguments! bash$ cat tmp | lab3p1 10 Error: too few arguments! bash$ cat tmp | lab3p1 10 22 2 3 1996 17.900000 2 4 1996 15.100000 2 5 1996 19.800000 1 24 2003 21.100000 1 9 2010 21.100000
Your job in this part is to create a little utiliy that builds that name for you. Here's an example in action:
bash$ lab3p2 Chicago IL 9 ILChicago ILCHICAGO ILCHICAG.txt bash$ lab3p2 Los Angeles CA 12 CALosAngeles CALOSANGELES CALOSANG.txt bash$ lab3p2 New York NY 9 NYNewYork NYNEWYORK NYNEWYOR.txt
bash$ lab3p2 Las Vegas NV 10To compute the length of a C-style string, use the strlen function. Do a "man" to find out more about the function, including which library to
include.
bash$ lab3p2 Los Angeles CA 12 CALosAngeles CALOSANGELES CALOSANG.txtTo do the concatenation, use the
strcat
function. Don't know how? Read the man page!
toupper. Don't know it? "man" it!
bash$ lab3p2 Los Angeles CA 12 CALosAngeles CALOSANGELES
bash$ lab3p2 Los Angeles CA 12 CALosAngeles CALOSANGELES CALOSANG.txt
ans.txt with answers to the following
questions:
1. When you call lab3p1 with too few arguments, like this:
bash$ ~wcbrown/bin/httpcat www.engr.udayton.edu/faculty/jkissock/gsod/MSJACKSO.txt | lab3p1
You not only see your error message, you also see some error messages
from the httpcat script. How could you change the command line so
that those error messages (httpcat's, that is) did not appear?
2. In the Part 1 solution lab3p1, you print out the "average daily
temperature". When you read it in, there was only one digit to the
right of the decimal place. How would you call fprintf to print it
out with just one digit to the right of the decimal place?
3. There is some missing data for most cities in Part 1. Missing
data has temperature of -99. Suppose we decided to print out a
warning message for each date with missing temperature data. Should
that be printed to stdout or stderr? Give a convincing argument to
back up your answer.
4. What is the type of argv[1]?
5. Do a "man" on strdup.
a. Explain what strdup does?
b. How does strdup indicate that it has failed?
c. If you make the call foo = strdup(bar), what type
does foo have?
d. If you make the call foo = strdup(bar), explain why
you eventually should call free(foo)?