Advertisement
Guest User

Untitled

a guest
Jan 16th, 2019
4,295
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.61 KB | None | 0 0
  1. /*
  2.  
  3. Lab 1 is (hopefully) an easy way to get familiar with some
  4. of the tools used in this class; the autograder, makefile, and get_opt.
  5.  
  6. get_opt is a function in the C libraries that processes options
  7. input on the command line at runtime. For example, a program
  8. might be compiled and run like so:
  9.  
  10. g++ main.cpp --std=c++17 -o main
  11. ./main
  12.  
  13. There was an argument provided to the g++ compiler: '--std=c++17'.
  14. The program recognizes the '--' string and identifies
  15. it as an argument. Get_opt will essentially do this for you,
  16. all you need to do is make sure it knows what look for, and what to
  17. do if it finds something. An example of how you might run a project
  18. in EECS 281 is as follows (using the makefile that we provide):
  19.  
  20. make
  21. ./lab1 -p 2 < test.txt
  22.  
  23. Other examples of valid command lines (the first uses the long version
  24. of print, the second specifies the -n or --name also):
  25. ./lab1 --print 2 < test.txt
  26. ./lab1 -p 2 -n < test.txt
  27.  
  28. This brings the EECS 281 makefile to attention. There are instructions
  29. in the makefile and we will go over it in class, but there are a few places
  30. that you need to edit with your program information. The makefile will
  31. save you a lot of time when compiling your programs and submitting to the
  32. autograder. In fact, it is required that you include a makefile with your
  33. autograder submissions.
  34.  
  35. */
  36.  
  37. #include <vector>
  38. #include <iostream>
  39. #include <algorithm> // std::sort
  40. #include <getopt.h>
  41. #include "sorting.h"
  42.  
  43.  
  44.  
  45.  
  46.  
  47. // ----------------------------------------------------------------------------
  48. // MusicLibrary Declarations
  49. // ----------------------------------------------------------------------------
  50.  
  51.  
  52. class MusicLibrary {
  53.  
  54. public:
  55.  
  56. // Read in the CSV music file through stdin.
  57. void read_data();
  58.  
  59. // Read and process command line arguments.
  60. void get_options(int argc, char** argv);
  61.  
  62. // Sort and print the data.
  63. void run();
  64.  
  65.  
  66. private:
  67.  
  68. // Holds all of the song objects for the program.
  69. std::vector<Song> music;
  70.  
  71. // The number of songs to print after sorting.
  72. int num_print = 2;
  73.  
  74. // Signifies what we attribute we are sorting by.
  75. char policy = '\0';
  76. };
  77.  
  78.  
  79.  
  80.  
  81. // ----------------------------------------------------------------------------
  82. // Driver
  83. // ----------------------------------------------------------------------------
  84.  
  85.  
  86.  
  87.  
  88. int main(int argc, char** argv) {
  89.  
  90. try {
  91. // Instantiate a music library.
  92. MusicLibrary library;
  93.  
  94. // Read and process the command line options.
  95. library.get_options(argc, argv);
  96.  
  97. // Read in the provided file through stdin.
  98. library.read_data();
  99.  
  100. // Sort the data with the provided policy and print
  101. // the first 'num_print' songs.
  102. library.run();
  103. }
  104.  
  105. // Catch runtime_errors, print the message, and exit the
  106. // program with a non-zero status.
  107. catch (std::runtime_error& e) {
  108. std::cerr << e.what() << std::endl;
  109. return 1;
  110. }
  111.  
  112. // All done!
  113. return 0;
  114. }
  115.  
  116.  
  117.  
  118.  
  119.  
  120. // ----------------------------------------------------------------------------
  121. // MusicLibrary Definitions
  122. // ----------------------------------------------------------------------------
  123.  
  124.  
  125. /*
  126.  
  127. This program can be run with five different command line options:
  128.  
  129. [--print | -p] <num_print>
  130. Determines how many songs to print.
  131.  
  132. [--name | -n]
  133. Sorts by song title
  134.  
  135. [--artist | -a]
  136. Sorts by song artist
  137.  
  138. [--listens | -l]
  139. Sorts by number of listens that a song has.
  140.  
  141. [--help | -h]
  142. Displays a helpful message! We wrote one for you,
  143. so feel free to take a look for additional clarification.
  144.  
  145. These are the options you will be incorporating into get_options!
  146. The program could be run like so:
  147.  
  148. ./lab1 --print 3 --artist
  149.  
  150. Equivallentaly,
  151.  
  152. ./lab1 -p 3 -a
  153.  
  154. */
  155.  
  156.  
  157. // Read and process command line options.
  158. void MusicLibrary::get_options(int argc, char** argv) {
  159. int option_index = 0, option = 0;
  160.  
  161. // Don't display getopt error messages about options
  162. opterr = false;
  163.  
  164.  
  165. // use getopt to find command line options
  166. struct option longOpts[] = { { "print", required_argument, nullptr, 'p' },
  167. { "help", no_argument, nullptr, 'h' },
  168. { "listens", no_argument, nullptr, "l" },
  169. { "name", no_argument, nullptr, "n" },
  170. { "artist", no_argument, nullptr, "a" },
  171. { nullptr, 0, nullptr, '\0' }
  172. };
  173.  
  174. /*
  175.  
  176. */
  177. while ((option = getopt_long(argc, argv, "p:hlna", longOpts, &option_index)) != -1) {
  178. switch (option) {
  179. case 'p':
  180. num_print = std::atoi(optarg);
  181. break;
  182.  
  183. case 'n':
  184. policy = 'n';
  185. break;
  186.  
  187. case 'l':
  188. policy = 'l';
  189. break;
  190.  
  191. case 'a':
  192. policy = 'a';
  193. break;
  194.  
  195.  
  196.  
  197. case 'h':
  198. std::cout << "This program reads a CSV file that contains song names,\n"
  199. << "the artist who wrote them, and the number of plays each song\n"
  200. << "has on Spotify. It then outputs the number of songs specified\n"
  201. << "in the command line arguments (the print option), which\n"
  202. << "defaults to 2, sorted by the option specified (one of name,\n"
  203. << "artist, or listens).\n"
  204. << "Usage: \'./lab1\n\t[--listens | -l]\n"
  205. << "\t[--name | -n]\n"
  206. << "\t[--artist | -a]\n"
  207. << "\t[--print | -p] <# of songs to print>\n"
  208. << "\t[--help | -h]\n"
  209. << "\t< <CSV Music File>\'" << std::endl;
  210. exit(0);
  211. }
  212. }
  213.  
  214. // After all the options have been processed,
  215. // check to make sure a sorting policy has been selected.
  216. // If one has not been selected, we will default to
  217. // sorting by song title (name).
  218. if (!policy)
  219. policy = 'n';
  220.  
  221.  
  222. // If num_print is still 0, then we are just
  223. // wasting time sorting, so throw an error.
  224. if (!num_print)
  225. throw std::runtime_error("No print argument was provided!"
  226. " This program will have no tangible results. Exiting...");
  227. }
  228.  
  229.  
  230. /*
  231.  
  232. An important concept in efficiency is portrayed in the next function,
  233. but it can be easy to miss. std::vector::reserve(size_t new_capacity)
  234. is a function that reserves the EXACT amount of memory necessary to
  235. fit 'new_capacity' number of elements. We will go over exactly why
  236. this is helpful in the first few weeks of class; for now just know
  237. that it is limiting wasted memory in our program, as well as cutting
  238. down on a non-trivial amount of time that would normally be lost
  239. growing the vector. This is not important with a sample file with
  240. six songs, but there are autograder tests with thousands of songs
  241. that it will make a difference in.
  242.  
  243. std::vector::reserve allocates the memory and increases the CAPACITY
  244. of the array, but not the SIZE of the array. This means those objects
  245. don't actually exist yet, and a call to std::vector::size will portray that.
  246. To increase the size of the array and insert objects then, we will still
  247. use std::vector::push_back. If one was to use std::vector::resize(size_t new_size)
  248. instead, they would be increasing both the size as well as the capacity of
  249. the array, and there would be 'new_size' many default constructed elements
  250. in the array if the array was initially empty.
  251.  
  252. */
  253.  
  254.  
  255. // Read data into the program through stdin.
  256. void MusicLibrary::read_data() {
  257.  
  258. Song song;
  259. std::string plays;
  260. int num_songs = 0;
  261.  
  262. // Read in the first number to find the number
  263. // of songs in the file.
  264. // Also consume the new line after the integer.
  265. std::cin >> num_songs >> std::ws;
  266.  
  267. // Reserve the exact amount of memory needed
  268. // to fit all the songs.
  269. music.reserve(num_songs);
  270.  
  271. // Read to the end of the CSV file.
  272. while (std::getline(std::cin, song.name, ',')) {
  273.  
  274. // Skip comments.
  275. if (song.name[0] == '#') {
  276. size_t pos = 0;
  277.  
  278. // If there is a newline, we have consumed
  279. // part of a song, so adjust the string.
  280. if ((pos = song.name.find_last_of('\n')) != std::string::npos)
  281. // Need a +1 here to move past the \n
  282. song.name = song.name.substr(pos + 1);
  283.  
  284. // Otherwise just grab the rest of the line.
  285. else {
  286. std::getline(std::cin, song.name);
  287. continue;
  288. }
  289. }
  290.  
  291. // Get the rest of the line.
  292. std::getline(std::cin, song.artist, ',');
  293. std::cin >> song.plays >> std::ws;
  294.  
  295. // Put the song into the music list.
  296. music.push_back(song);
  297. }
  298.  
  299. // If we didn't read in any data, throw an error.
  300. if (!music.size())
  301. throw std::runtime_error("No data was read in! Refer to the help option to see program usage.");
  302. }
  303.  
  304.  
  305. // Sort and print the data.
  306. void MusicLibrary::run() {
  307.  
  308. // Determine our sorting policy and sort.
  309. if (policy == 'n') {
  310. std::sort(music.begin(), music.end(), Song::NameSort());
  311. }
  312.  
  313. else if (policy == 'a') {
  314. std::sort(music.begin(), music.end(), Song::ArtistSort());
  315. }
  316. else if (policy == 'l') {
  317. std::sort(music.begin(), music.end(), Song::ListensSort());
  318. }
  319.  
  320.  
  321. // Print out the first num_print songs with the
  322. // overloaded stream insertion operator.
  323. for (int i = 0; i < num_print; ++i)
  324. std::cout << music[i] << std::endl;
  325. }
  326.  
  327.  
  328.  
  329. ------
  330.  
  331.  
  332. ## EECS 281 Advanced Makefile
  333.  
  334. # How to use this Makefile...
  335. ###################
  336. ###################
  337. ## ##
  338. ## $ make help ##
  339. ## ##
  340. ###################
  341. ###################
  342.  
  343. # IMPORTANT NOTES:
  344. # 1. Set EXECUTABLE to the command name given in the project specification.
  345. # 2. To enable automatic creation of unit test rules, your program logic
  346. # (where main() is) should be in a file named project*.cpp or specified
  347. # in the PROJECTFILE variable.
  348. # 3. Files you want to include in your final submission cannot match the
  349. # test*.cpp pattern.
  350.  
  351. # enables c++17 on CAEN
  352. PATH := /usr/um/gcc-6.2.0/bin:$(PATH)
  353. LD_LIBRARY_PATH := /usr/um/gcc-6.2.0/lib64
  354. LD_RUN_PATH := /usr/um/gcc-6.2.0/lib64
  355.  
  356. # TODO
  357. # Change EXECUTABLE to match the command name given in the project spec.
  358. EXECUTABLE = lab1
  359. DEBUG = $(EXECUTABLE)_debug
  360.  
  361. # designate which compiler to use
  362. CXX = g++
  363.  
  364. # list of test drivers (with main()) for development
  365. TESTSOURCES = $(wildcard test*.cpp)
  366. # names of test executables
  367. TESTS = $(TESTSOURCES:%.cpp=%)
  368.  
  369. # list of sources used in project
  370. SOURCES = $(wildcard *.cpp)
  371. SOURCES := $(filter-out $(TESTSOURCES), $(SOURCES))
  372. # list of objects used in project
  373. OBJECTS = $(SOURCES:%.cpp=%.o)
  374.  
  375.  
  376. # If main() is in another file delete the line above, edit and uncomment below
  377. PROJECTFILE = lab1.cpp
  378.  
  379. # name of the tar ball created for submission
  380. PARTIAL_SUBMITFILE = partialsubmit.tar.gz
  381. FULL_SUBMITFILE = fullsubmit.tar.gz
  382.  
  383. # name of the perf data file, only used by the clean target
  384. PERF_FILE = perf.data*
  385.  
  386. #Default Flags (would prefer -std=c++17 but Mac/Xcode/Clang doesn't support)
  387. CXXFLAGS = -std=c++1z -Wconversion -Wall -Werror -Wextra -pedantic
  388.  
  389. # make release - will compile "all" with $(CXXFLAGS) and the -O3 flag
  390. # also defines NDEBUG so that asserts will not check
  391. release: CXXFLAGS += -O3 -DNDEBUG
  392. release: all
  393.  
  394. # make debug - will compile "all" with $(CXXFLAGS) and the -g flag
  395. # also defines DEBUG so that "#ifdef DEBUG /*...*/ #endif" works
  396. debug: EXECUTABLE := $(DEBUG)
  397. debug: CXXFLAGS += -g3 -DDEBUG
  398. debug: clean all
  399.  
  400. # make profile - will compile "all" with $(CXXFLAGS) and the -pg flag
  401. profile: CXXFLAGS += -pg
  402. profile: clean all
  403.  
  404. # make static - will perform static analysis in the matter currently used
  405. # on the autograder
  406. static:
  407. cppcheck --enable=all --suppress=missingIncludeSystem $(SOURCES) *.h *.hpp
  408.  
  409. # highest target; sews together all objects into executable
  410. all: $(EXECUTABLE)
  411.  
  412. $(EXECUTABLE): $(OBJECTS)
  413. ifeq ($(EXECUTABLE), executable)
  414. @echo Edit EXECUTABLE variable in Makefile.
  415. @echo Using default a.out.
  416. $(CXX) $(CXXFLAGS) $(OBJECTS)
  417. else
  418. $(CXX) $(CXXFLAGS) $(OBJECTS) -o $(EXECUTABLE)
  419. endif
  420.  
  421. # Automatically generate any build rules for test*.cpp files
  422. define make_tests
  423. ifeq ($$(PROJECTFILE),)
  424. @echo Edit PROJECTFILE variable to .cpp file with main\(\)
  425. @exit 1
  426. endif
  427. SRCS = $$(filter-out $$(PROJECTFILE), $$(SOURCES))
  428. OBJS = $$(SRCS:%.cpp=%.o)
  429. HDRS = $$(wildcard *.h *.hpp)
  430. $(1): CXXFLAGS += -g3 -DDEBUG
  431. $(1): $$(OBJS) $$(HDRS) $(1).cpp
  432. $$(CXX) $$(CXXFLAGS) $$(OBJS) $(1).cpp -o $(1)
  433. endef
  434. $(foreach test, $(TESTS), $(eval $(call make_tests, $(test))))
  435.  
  436. alltests: clean $(TESTS)
  437.  
  438. # rule for creating objects
  439. %.o: %.cpp
  440. $(CXX) $(CXXFLAGS) -c $*.cpp
  441.  
  442. # make clean - remove .o files, executables, tarball
  443. clean:
  444. rm -f $(OBJECTS) $(EXECUTABLE) $(DEBUG) $(TESTS) $(PARTIAL_SUBMITFILE) $(FULL_SUBMITFILE) $(PERF_FILE)
  445. rm -Rf *.dSYM
  446.  
  447. # make partialsubmit.tar.gz - cleans, runs dos2unix, creates tarball omitting test cases
  448. PARTIAL_SUBMITFILES=$(filter-out $(TESTSOURCES), $(wildcard Makefile *.h *.hpp *.cpp))
  449. $(PARTIAL_SUBMITFILE): $(PARTIAL_SUBMITFILES)
  450. rm -f $(PARTIAL_SUBMITFILE) $(FULL_SUBMITFILE)
  451. -dos2unix $(PARTIAL_SUBMITFILES)
  452. COPYFILE_DISABLE=true tar -vczf $(PARTIAL_SUBMITFILE) $(PARTIAL_SUBMITFILES)
  453. @echo !!! WARNING: No test cases included. Use 'make fullsubmit' to include test cases. !!!
  454.  
  455. # make fullsubmit.tar.gz - cleans, runs dos2unix, creates tarball including test cases
  456. FULL_SUBMITFILES=$(filter-out $(TESTSOURCES), $(wildcard Makefile *.h *.hpp *.cpp test*.txt))
  457. $(FULL_SUBMITFILE): $(FULL_SUBMITFILES)
  458. rm -f $(PARTIAL_SUBMITFILE) $(FULL_SUBMITFILE)
  459. -dos2unix $(FULL_SUBMITFILES)
  460. COPYFILE_DISABLE=true tar -vczf $(FULL_SUBMITFILE) $(FULL_SUBMITFILES)
  461. @echo !!! Final submission prepared, test cases included... READY FOR GRADING !!!
  462.  
  463. # shortcut for make submit tarballs
  464. partialsubmit: $(PARTIAL_SUBMITFILE)
  465. fullsubmit: $(FULL_SUBMITFILE)
  466.  
  467. define MAKEFILE_HELP
  468. EECS281 Advanced Makefile Help
  469. * This Makefile uses advanced techniques, for more information:
  470. $$ man make
  471.  
  472. * General usage
  473. 1. Follow directions at each "TODO" in this file.
  474. a. Set EXECUTABLE equal to the name given in the project specification.
  475. b. Set PROJECTFILE equal to the name of the source file with main()
  476. c. Add any dependency rules specific to your files.
  477. 2. Build, test, submit... repeat as necessary.
  478.  
  479. * Preparing submissions
  480. A) To build 'partialsubmit.tar.gz', a tarball without tests used to find
  481. buggy solutions in the autograder. This is useful for faster autograder
  482. runs during development and free submissions if the project does not
  483. build.
  484. $$ make partialsubmit
  485. B) Build 'fullsubmit.tar.gz' a tarball complete with autograder test cases.
  486. ALWAYS USE THIS FOR FINAL GRADING! It is also useful when trying to
  487. find buggy solutions in the autograder.
  488. $$ make fullsubmit
  489.  
  490. * Unit testing support
  491. A) Source files for unit testing should be named test*.cpp. Examples
  492. include test_input.cpp or test3.cpp.
  493. B) Automatic build rules are generated to support the following:
  494. $$ make test_input
  495. $$ make test3
  496. $$ make alltests (this builds all test drivers)
  497. C) If test drivers need special dependencies, they must be added manually.
  498. D) IMPORTANT: NO SOURCE FILES THAT BEGIN WITH test WILL BE ADDED TO ANY
  499. SUBMISSION TARBALLS.
  500.  
  501. * Static Analysis support
  502. A) Matches current autograder style grading tests
  503. B) Usage:
  504. $$ make static
  505. endef
  506. export MAKEFILE_HELP
  507.  
  508. help:
  509. @echo "$$MAKEFILE_HELP"
  510.  
  511. #######################
  512. # TODO (begin) #
  513. #######################
  514. # individual dependencies for objects
  515. # Examples:
  516. # "Add a header file dependency"
  517. # project2.o: project2.cpp project2.h
  518. #
  519. # "Add multiple headers and a separate class"
  520. # HEADERS = some.h special.h header.h files.h
  521. # myclass.o: myclass.cpp myclass.h $(HEADERS)
  522. # project5.o: project5.cpp myclass.o $(HEADERS)
  523. #
  524. # ADD YOUR OWN DEPENDENCIES HERE
  525. lab1.o: lab1.cpp sorting.h
  526.  
  527. #test_thing: test_thing.cpp class.o functions.o
  528.  
  529. #class.o: class.cpp class.h
  530.  
  531. #functions.o: functions.cpp functions.h
  532.  
  533. #project0.o: project0.cpp class.h functions.h
  534.  
  535. ######################
  536. # TODO (end) #
  537. ######################
  538.  
  539. # these targets do not create any files
  540. .PHONY: all release debug profile static clean alltests partialsubmit fullsubmit help
  541. # disable built-in rules
  542. .SUFFIXES:
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement