README.txt 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. This assignment has the following purposes:
  2. 1. Allocate memory when the program runs. You do not know the amount
  3. of memory needed in advance. Your program will allocate memory only
  4. after the program knows the file to read. Your program will be
  5. checked to determine whether the program uses memory correctly. You
  6. will receive zero if the program allocates memory whose size is
  7. independent of the input file.
  8. 2. Use the built-in quicksort function (qsort). This function is
  9. general and can take arrays of different types. To use this
  10. function, your program needs to provide "comparison" functions.
  11. This assignment asks you to write a program that reads integers and
  12. strings. You are encouraged to use fscanf to read integer and fgets
  13. to read strings. Please read the Linux manual about these two
  14. functions.
  15. Your program needs to have the following functions:
  16. * Read the integers (or strings) from a file and store the data in
  17. memory. You do not know the length of the file and have to read the
  18. file once, counting the amount of data. After knowing the amount of
  19. data, allocate enough memory to store the data, read the file again
  20. and store the data in memory.
  21. * Sort the data. You MUST NOT write the sorting function yourself,
  22. instead, a sort function (qsort) has been provided for you in the C
  23. library. It is very important for you to understand how qsort
  24. function works. The main task is to write appropriate comparison
  25. functions for integers and for strings.
  26. * Write the sorted data into a file.
  27. * Release the allocated memory.
  28. * You can assume that MAXIMUM_LENGTH is the maximum length of each
  29. line of a file. It is defined for you already.
  30. *************
  31. * IMPORTANT *
  32. *************
  33. When your program allocates memory, you must allocate enough memory
  34. to store the data but not more. You cannot assume an input file
  35. has, for example, 1000 lines. If you do so, you will definitely
  36. receive zero in this assignment.
  37. #define LARGESIZE 10000
  38. Student stu[LARGESIZE];
  39. /* allocate a large array, regardless of the size of the input file */
  40. The teaching staff will inspect your program to ensure that you do
  41. not violate this rule. You will receive zero even if your program
  42. passes the test-cases.
  43. You should never have any global variable or static variable.
  44. The input files are stored in the inputs directory. The expected
  45. outputs are stored in the expected directory. Your program's
  46. outputs are stored in the outputs directory.
  47. You should read the files stored in outputs/valgrind-log* and check
  48. whether your program has any invalid memory access or memory leak.
  49. NOTE:
  50. Type "make" to compile the source code.
  51. Type "make clean" to remove generated files.
  52. Now, it is time to take a look at Makefile. Please read this, it is very important for you to know
  53. how Makefile works and soon be able to write your own Makefile.
  54. It is impossible to write a C program using a single file.
  55. When you include a header file, you are already using multiple files.
  56. You do not implement printf, do you? Where does it come from?
  57. It comes from C libraries, such as libc.so in /usr/lib/.
  58. Why is C designed in this way? What are the advantages of writing a program using multiple files?
  59. * Reduce redundant work. Many frequently used functions are supported by libraries.
  60. You don't have to write your own printf, scanf, or fopen.
  61. *Improve portability. Some functions handle low-level activities related to hardware,
  62. such as reading files from a disk or sending packets through a network.
  63. It is better to isolate the hardware-specific in libraries so that your program can run on different computers,
  64. as long as your program uses the correct libraries (usually need to recompile the source code).
  65. * Enhance performance. Libraries are well optimized so your program can have better performance.
  66. * Partition work for collabortion. When you write a large program with other people,
  67. it is natural to break the work into smaller units. Each of you is responsibile for some units.
  68. Each unit is stored in a single file.
  69. * Save compilation time. Compiling a large program can take hours.
  70. If the whole program is in a single file and you change only one line,
  71. you have to wait for hours to check whether your change is correct.
  72. A better solution is to break the program into many files and compile
  73. only the files affected by your change.
  74. Then the object files are linked. This may take a few seconds, much better than a few hours.
  75. The last advantage is critical in developing large programs.
  76. This is an important reason to separate compilation from linking.
  77. Here is a simple example:
  78. ex1: main2.o f1.o f2.o
  79. gcc -Wall -Wshadow main2.o f1.o f2.o -o ex1
  80. main2.o: main2.c f1.h f2.h
  81. gcc -Wall -Wshadow -c main2.c
  82. f1.o: f1.c f1.h
  83. gcc -Wall -Wshadow -c f1.c
  84. f2.o: f2.c f2.h
  85. gcc -Wall -Wshadow -c f2.c
  86. clean:
  87. rm *.o ex1
  88. You should always have
  89. -Wall -Wshadow
  90. after gcc. They will give you warning messages that likely come from errors.
  91. The first line means the program ex1 depends on three files:
  92. main2.o, f1.o, and f2.o. A .o file is called an object file.
  93. If these three files are available, the second line uses gcc to link
  94. the three object files and create the executable called ex1.
  95. Please notice that the command gcc is after a TAB, not space.
  96. How are the three object files are created?
  97. They are created by the following three rules.
  98. The file main2.o requires three files: main2.c, f1.h, and f2.h.
  99. The following line uses gcc to compile (with the -c flag) main2.c and create the object file main2.o.
  100. The same situation applies to f1.o and f2.o. How do you use Makefile? Simply type
  101. make
  102. and you will see the following messages
  103. gcc -Wall -Wshadow -c main2.c
  104. gcc -Wall -Wshadow -c f1.c
  105. gcc -Wall -Wshadow -c f2.c
  106. gcc -Wall -Wshadow main2.o f1.o f2.o -o ex1
  107. What is so important about Makefile? It is the dependence rules.
  108. ex1: main2.o f1.o f2.o
  109. says that the executable main depends on main.o, f1.o, and f2.o.
  110. If any of the three object files has been changed, execute the following command
  111. gcc -Wall -Wshadow main.o f1.o f2.o -o main
  112. How does make know whether f1.o has changed? It checks the following rule
  113. f1.o: f1.h f1.c
  114. If f1.h or f1.c is changed, execute the following command
  115. gcc -Wall -Wshadow -c f1.c
  116. If neither f1.h nor f1.c has changed, then f1.c will not be compiled.
  117. How does the computer know whether a file has been changed?
  118. It compares the time of the files. If f1.c's time is later than f1.o's time,
  119. make thinks f1.c has been changed and generates a new f1.o. If you the following command
  120. touch f1.c
  121. the time of f1.c is set to the current time and it is later than f1.o's time. Now, type
  122. make
  123. again and you will see the following message
  124. gcc -c f1.c
  125. gcc -Wall -Wshadow main.o f1.o f2.o -o ex1
  126. The message means that f1.c is compiled again and a newer version of main is created.
  127. Notice that f2.c is not recompiled. This saves time.
  128. If a file has not changed, it is unnecessary to compile it again. The last rule says, if you type
  129. make clean
  130. the object files and main are deleted.
  131. In Makefile, anything after # is treated as a comment.
  132. We can define symbols in Makefile. For example
  133. GCC = gcc
  134. CFLAGS = -Wall -Wshadow
  135. ex1: main2.o f1.o f2.o
  136. $(GCC) $(CFLAGS) main2.o f1.o f2.o -o ex1
  137. main2.o: main2.c f1.h f2.h
  138. $(GCC) $(CFLAGS) -c main2.c
  139. f1.o: f1.h f1.c
  140. $(GCC) $(CFLAGS) -c f1.c
  141. f2.o: f2.h f2.c
  142. $(GCC) $(CFLAGS) -c f2.c
  143. clean:
  144. rm *.o ex1
  145. If we decide to use another compiler, we can change this line
  146. GCC = gcc
  147. without changing any other lines because GCC is substituted in the following lines.
  148. We can also change the flags by adding -g for debugging or -O for optimization.
  149. We can also create a symbol OBJS that represents all object files:
  150. GCC = gcc
  151. CFLAGS = -Wall -WShadow
  152. OBJS = main2.o f1.o f2.o
  153. ex1: $(OBJS)
  154. $(GCC) $(CFLAGS) $(OBJS) -o ex1
  155. main2.o: main2.c f1.h f2.h
  156. $(GCC) $(CFLAGS) -c main2.c
  157. f1.o: f1.h f1.c
  158. $(GCC) $(CFLAGS) -c f1.c
  159. f2.o: f2.h f2.c
  160. $(GCC) $(CFLAGS) -c f2.c
  161. clean:
  162. rm *.o ex1
  163. Now let's try to understand the following lines in the Makefile of this programming assignment.
  164. test0: pa05
  165. @$(VALGRIND) --log-file=outputs/intmemoutput0 ./pa05 i inputs/intinput0 outputs/intoutput0
  166. @$(VALGRIND) --log-file=outputs/strmemoutput0 ./pa05 s inputs/strinput0 outputs/stroutput0
  167. @diff -w outputs/intoutput0 expected/intexpected0
  168. @diff -w outputs/stroutput0 expected/strexpected0
  169. pa05 will compile your program since we earlier have defined
  170. pa05: $(OBJS) $(HDRS)
  171. $(GCC) $(CFLAGS) $(OBJS) -o $@
  172. $(VALGRIND) --log-file=outputs/intmemoutput0
  173. tells valgrind to put memory log-file in outputs directory
  174. (This is where you will go to check what happens if you have
  175. any memory leakage or other errors) with name intmemoutput0.
  176. ./pa05 i inputs/input0 outputs/intoutput0 will execute your object file with three arguments
  177. i, inputs/input0 and outputs/intoutput0
  178. Prof. Lu will cover more of this in the future lecture but I highly encourage you
  179. to take a peek of pa05.c to see what these three arguments are and how they are used in
  180. the main program and later passed to your functions. Your input takes from inputs/input0
  181. and the output of the program will be stored in outputs/intoutput0.
  182. Last but not the least,
  183. @diff -w outputs/intoutput0 expected/intexpected0 will test your output with the expected
  184. output, [ERROR] will be displayed if these two files are different.
  185. That's all, folks. And please use gdb when there is something wrong with your program.