Can I get help with Computer Science?

profilexfire51
tests.zip

testcases/testcase02.c

// Sean Szumlanski // COP 3502, Fall 2017 // ================== // Varg: testcase02.c // ================== // A simple test of the mostFrequentChar() function. #include <stdio.h> #include "Varg.h" int main(void) { char c = mostFrequentChar(7, 'a', 'b', 'c', 'd', 'd', 'b', 'a'); if (c == 'd') printf("Hooray!\n"); else printf("fail whale :(\n"); return 0; }

testcases/testcase05.c

// Sean Szumlanski // COP 3502, Fall 2017 // ================== // Varg: testcase05.c // ================== // A simple test of the fancyMostFrequentChar() function. #include <stdio.h> #include "Varg.h" int main(void) { char c = fancyMostFrequentChar('a', 'a', 'b', 'b', 'a', '\0'); if (c == 'a') printf("Hooray!\n"); else printf("fail whale :(\n"); return 0; }

testcases/output05.txt

Hooray!

testcases/testcase06.c

// Sean Szumlanski // COP 3502, Fall 2017 // ================== // Varg: testcase06.c // ================== // A simple test of the mostFrequentChar() function. #include <stdio.h> #include "Varg.h" int main(void) { char c = mostFrequentChar(0); if (c == '\0') printf("Hooray!\n"); else printf("fail whale :(\n"); return 0; }

testcases/output06.txt

Hooray!

testcases/output02.txt

Hooray!

testcases/output03.txt

Hooray!

testcases/output04.txt

Hooray!

testcases/testcase04.c

// Sean Szumlanski // COP 3502, Fall 2017 // ================== // Varg: testcase04.c // ================== // A simple test of the mostFrequentChar() function. #include <stdio.h> #include "Varg.h" int main(void) { char c = mostFrequentChar(5, 'a', 'a', 'b', 'b', 'a'); if (c == 'a') printf("Hooray!\n"); else printf("fail whale :(\n"); return 0; }

testcases/output01.txt

Hooray!

testcases/testcase01.c

// Sean Szumlanski // COP 3502, Fall 2017 // ================== // Varg: testcase01.c // ================== // Boundary check to make sure your difficultyRating() and hoursSpent() // functions are implemented correctly. #include <stdio.h> #include "Varg.h" int main(void) { int success = 1; if (difficultyRating() < 1.0 || difficultyRating() > 5.0) success = 0; if (hoursSpent() <= 0.0) success = 0; printf("%s\n", success ? "Hooray!" : "fail whale :("); return 0; }

testcases/testcase03.c

// Sean Szumlanski // COP 3502, Fall 2017 // ================== // Varg: testcase03.c // ================== // A simple test of the fancyMostFrequentChar() function. #include <stdio.h> #include "Varg.h" int main(void) { char c = fancyMostFrequentChar('a', 'b', 'c', 'd', 'd', 'b', 'a', '\0'); if (c == 'd') printf("Hooray!\n"); else printf("fail whale :(\n"); return 0; }

testcases/test-all.sh

#!/bin/bash # Sean Szumlanski # COP 3502, Fall 2017 # ================= # Varg: test-all.sh # ================= # You can run this script at the command line like so: # # bash test-all.sh # # For more details, see the assignment PDF. NUM_TEST_CASES=6 for i in `seq -f "%02g" 1 $NUM_TEST_CASES`; do echo -n "Checking testcase$i... " # Attempt to compile. gcc Varg.c testcase$i.c -lm 2> /dev/null compile_val=$? if [[ $compile_val != 0 ]]; then echo "fail (failed to compile)" continue fi # Run program. Capture return value to check whether it crashes. ./a.out > myoutput$i.txt 2> /dev/null execution_val=$? if [[ $execution_val != 0 ]]; then echo "fail (program crashed)" continue fi # Run diff and capture its return value. diff myoutput$i.txt output$i.txt > /dev/null diff_val=$? # Output results based on diff's return value. if [[ $diff_val != 0 ]]; then echo "fail (output does not match)" else echo "PASS!" fi done # Clean up the executable file. rm -f a.out # Clean up the output files generated by this script. for i in `seq -f "%02g" 1 $NUM_TEST_CASES`; do rm -f myoutput$i.txt done echo "" echo "WHOA THERE! Before you submit your program, please be aware that these test" echo "cases are not comprehensive. The test cases I wrote for you are just a sort" echo "of starter pack, designed to show you how you can write test cases for your" echo "programs, which you can do even before you've completed the functions you're" echo "working on. You should create additional test cases in order to fully test" echo "the functionality and correctness of your program."

Varg.h

#ifndef __VARG_H #define __VARG_H // Functional Prototypes char mostFrequentChar(int n, ...); char fancyMostFrequentChar(char c, ...); double difficultyRating(void); double hoursSpent(void); #endif

Varg.pdf

Programming Assignment #1: Varg1

COP 3502, Fall 2017

Due: Sunday, September 3, before 11:59 PM

Table of Contents

Abstract........................................................................................................2

1. Overview.................................................................................................3

2. Important Note: Test Case Files Look Wonky in Notepad......................3

3. Adopting a Growth Mindset....................................................................3

4. Writing Variadic Functions......................................................................4

5. Varg.h.......................................................................................................4

6. Test Cases and the test-all.sh Script.........................................................5

7. Output......................................................................................................5

8. Function Requirements............................................................................5

9. Input Specifications Are a Contract.........................................................7

10. ASCII Character Values.........................................................................7

11. Compilation and Testing (CodeBlocks).................................................8

12. Compilation and Testing (Linux/Mac Command Line)........................9

13. Getting Started: A Guide for the Overwhelmed..................................10

14. Deliverables.........................................................................................11

15. Grading................................................................................................12

1 “Varg” is not a real word. It’s a portmanteau of var and arg, which in this case stand for “variable number of arguments.” The correct technical term for functions that take a variable number of arguments is “variadic.”

Abstract

In COP 3223 (Introduction to C Programming), you encountered many functions – such as printf() – that were capable of taking a different number of arguments every time you call them. However, the functions you wrote in that class probably never had that ability; instead, they were always restricted to taking the same number of arguments each time they were called.

In this programming assignment, you will write two variadic function s – that is, functions that take a variable number of arguments. By completing this assignment, you will acquire a new, advanced C programming skill. Because of one of the restrictions placed on the functions, you will also gain a small amount of experience developing an algorithm with a focus on runtime efficiency.

On the software engineering side of things, you will learn to construct programs that use multiple source files and custom header (.h) files. This assignment will also help you hone your ability to acquire new knowledge by reading technical specifications. If you end up pursing a career as a software developer, the ability to rapidly digest technical documentation and work with new software libraries will be absolutely critical to your work, and this assignment will provide you with a gentle exercise in doing just that.

Finally, this assignment is specifically designed to require relatively few lines of code so that you can make your first foray into the world of Linux without a huge, unwieldy, and intimidating program to debug. As the semester progresses, the programming assignments will become more lengthy and complex, but for now, this assignment should provide you with a gentle introduction to debugging in a foreign development environment.

Attachments

Varg.h, varsum.c, testcase{01-06}.c, output{01-06}.txt, and test-all.sh

Deliverables

Varg.c

(Note! Capitalization and spelling of your filename matters!)

1. Overview

In this assignment, you’ll write two variadic functions – functions that take variable numbers of arguments, just like printf() is capable of doing. (There are also two other functions for you to write. A complete list of required functions, including their functional prototypes, is given below in Section 8, “Function Requirements”.)

You will submit a single source file, named Varg.c, that contains all required function definitions, as well as any auxiliary functions you deem necessary. In Varg.c, you will have to #include any header files necessary for your functions to work, including the custom Varg.h file we have distributed with this assignment (see Section 5, “Varg.h”).

Note: You will not write a main() function in the source file you submit! Rather, we will compile your source file with our own main() function(s) in order to test your code. We have attached example source files that have main() functions, which you can use to test your code. You can write your own main() functions for testing purposes, but the code you submit must not have a main() function. We realize this is completely new territory for most of you, so don’t panic. We’ve included instructions for compiling multiple source files into a single executable (e.g., mixing your Varg.c with our Varg.h and testcaseXX.c files) in Sections 11 and 12 of this PDF.

Although we have included test cases with sample main() functions to get you started with testing the functionality of your code, we encourage you to develop your own test cases, as well. Ours are by no means comprehensive. We will use much more elaborate test cases when grading your submission.

Start early. Work hard. Good luck!

2. Important Note: Test Case Files Look Wonky in Notepad

Included with this assignment are several test cases, along with output files showing exactly what your output should look like when you run those test cases. You will have to refer to those as the gold standard for how your output should be formatted. Please note that if you open those files in Notepad, they will appear to be one long line of text. That’s because Notepad handles end-of-line characters differently from Linux and Unix-based systems. One solution is to view those files in an IDE (like CodeBlocks), or you could use a different text editor (like Atom or Sublime).

3. Adopting a Growth Mindset

A word of advice before we dive in to the details: When faced with an assignment like this, which has many different facets, some of which might appear foreign and/or challenging, it’s important not to look at it as an instrument that is being used to measure how much you already know (whether that’s knowledge of programming, operating systems, or even what some might call “natural intellectual capability”). Rather, it’s important to view this assignment as a chance to learn something new, grow your skill set, and embrace a new challenge.

It’s also important to view intellectual capability as something that can grow and change over one’s lifetime. Adopting that mindset will allow you to reap greater benefits from this assignment (and from

all your college-level coursework) regardless of the grades you earn.

For more on the importance of adopting a growth mindset throughout your academic career and how that can impact your life, see the following:

Growth Mindset vs Fixed Mindset: An Introduction (Watch time: 2 min 42 sec)

The Power of Belief – Mindset and Success (Watch time: 10 min 20 sec)

4. Writing Variadic Functions

One of the trickiest things about writing a variadic function is that you must somehow tell the function how many arguments you’re passing to it. When you call printf(), you do this implicitly, because printf() goes through your first argument (a string), and every time it sees a conversion code (such as “%d” or “%c”), it knows there is another input argument waiting to be processed. By reading the format string, the function figures out how many arguments to read after the initial one.

Included with this assignment is a file called varsum.c, which I wrote to show you how to implement a simple function to add up an arbitrary number of integer arguments passed to a function. The file has two versions of that function: mySum() and myOtherSum(). The only difference between the two implementations is how each function figures out how many integers it will be processing.

From that source file, you’ll see that when writing a variadic function, all the magic happens with the va_list data type and the va_start and va_arg functions. In order to use va_list, va_start, and va_arg, you must include stdarg.h at the top of your source code, like so:

#include <stdarg.h>

Note that stdarg.h is a standard system library, just like stdio.h and string.h.

5. Varg.h

Included with this assignment is a customer header file that includes functional prototypes for all the functions you will be implementing. You should #include this file from your Varg.c file, like so:

#include "Varg.h"

The “quotes” (as opposed to <brackets>) indicate to the compiler that this header file is found in the same directory as your source, not a system directory.

You should not modify Varg.h in any way, and you should not send Varg.h when you submit your assignment. We will use our own unmodified copy of Varg.h when compiling your program.

If you write auxiliary functions (“helper functions”) in your Varg.c file (which is strongly encouraged!), you should not add those functional prototypes to Varg.h. Our test case programs will not call your helper functions directly, so they do not need any awareness of the fact that your helper functions even exist. (We only list functional prototypes in a header file if we want multiple source files

to be able to call those functions.) So, just put the functional prototypes for any helper functions you write at the top of your Varg.c file.

Think of Varg.h as a bridge between source files. It contains functional prototypes for functions that might be defined in one source file (such as your Varg.c file) and called from a different source file (such as the testcaseXX.c files we have provided with this assignment).

6. Test Cases and the test-all.sh Script

We’ve included multiple test cases with this assignment, which show some ways in which we might test your code. These test cases are not comprehensive. You should also create your own test cases if you want to test your code comprehensively. In creating your own test cases, you should always ask yourself, “How could these functions be called in ways that don’t violate the program specification, but which haven’t already been covered in the test cases included with the assignment?”

We’ve also included a script, test-all.sh, that will compile and run all test cases for you. You can run it on Eustis by placing it in a directory with Varg.c, Varg.h, and all the test case files, and typing:

bash test-all.sh

7. Output

The functions you write for this assignment should not produce any output. If your functions cause anything to print to the screen, it will interfere with our test case evaluation.

Please be sure to disable or remove any printf() statements you have in your code before submitting this assignment.

8. Function Requirements

In the source file you submit, Varg.c, you must implement the following functions. You may implement auxiliary functions (helper functions) to make these work, as well, although that is probably unnecessary for this assignment. Please be sure the spelling, capitalization, and return types of your functions match these prototypes exactly.

char mostFrequentChar(int n, ...);

Description: This function takes a single non-negative integer, n, followed by a list of exactly n lowercase, alphabetic characters (any characters on the range ‘a’ through ‘z’), and returns the most frequently occurring character it received as input. If multiple characters are tied for the distinction of “most frequently occurring,” you should return the first one that occurred that number of times when processing the argument list from left to right. For example, when processing the input to the function call mostFrequentChar(5, 'a', 'b', 'b', 'a', 'c'),

both ‘a’ and ‘b’ are tied (with two occurrences each), but the first character to rack up two occurrences when reading the list in order (from left to right) is ‘b’. (For further examples, see the test cases included with this assignment.)

Special Restriction: As you read the list of input arguments, you are not allowed to store that list anywhere in memory (for example, in a linked list or a string). In other words, you can read the list of arguments passed to your function exactly once. You should not try to save that list in memory so that you can re-read it multiple times within your function.

Output: This function should not print anything to the screen.

Return Value: The most frequently occurring character in the argument list. (See the description above for an explanation of how to handle ties.) If n is equal to zero, your function should return the ‘\0’ character, which is C’s null sentinel.

char fancyMostFrequentChar(char c, ...);

Description: This function takes as its input a list of characters. The function is guaranteed to receive at least one argument. The last argument passed to the function will always be the ‘\0’ character, which is C’s null sentinel. All other characters in the list will be lowercase, alphabetic characters (any characters on the range ‘a’ through ‘z’). Your function should return the most frequently occurring character in the list. In the event of ties, you should handle them in the same way that the mostFrequentChar() function handles ties (described above). Note that it’s possible for ‘\0’ to be the only argument given, in which case you should return ‘\0’.

Special Restriction: This function is subject to the same special restriction listed above for the mostFrequentChar() function.

Output: This function should not print anything to the screen.

Return Value: The most frequently occurring character in the argument list. (See the description above for an explanation of how to handle ties.) If ‘\0’ is the only argument passed to this function, then you should return ‘\0’.

double difficultyRating(void);

Output: This function should not print anything to the screen.

Return Value: A double indicating how difficult you found this assignment on a scale of 1.0 (ridiculously easy) through 5.0 (insanely difficult).

double hoursSpent(void);

Output: This function should not print anything to the screen.

Return Value: An estimate (greater than zero) of the number of hours you spent on this assignment.

9. Input Specifications Are a Contract

In testing, you can rest assured that we will only call your functions in ways that jive with the function descriptions above. For example, we will never call mostFrequentChar() without specifying an integer as the first argument, and that integer is always guaranteed to correctly indicate the number of arguments that follow. Similarly, we will never call fancyMostFrequentChar() without ending the list of parameters with a null sentinel (‘\0’), and neither function will receive unexpected characters in the argument list (such as a capital ‘Q’ or punctuation marks such as ‘!’).

10. ASCII Character Values

Note: If you haven’t thought about how to solve this problem yet, it might not be immediately obvious why the information in this section might be useful to you in this assignment.

In C, each character has an underlying integer value called its ASCII value. (ASCII is an international standard for character numbering. If you want to read more about the topic, see the ASCII article on Wikipedia. For this assignment, however, you don’t need to know any more about ASCII than what I’ve written up in this section.)

To see a character’s underlying integer value, you can always just print it as an integer, like so:

printf("%d", 'a');

The ASCII value for ‘a’ is 97, so the above line of code should print out 97.

Lowercase letters are numbered sequentially: ‘a’ is 97, ‘b’ is 98, ‘c’ is 99, and so on. If for some reason you wanted to convert the characters ‘a’ through ‘z’ to integers 0 through 25 (maybe so you could use them to access indices in an array of length 26?), you could just subtract 97 from those characters. For example:

printf("%d", 'a' - 97); // 'a' - 97 = 97 – 97 = 0 printf("%d", 'b' - 97); // 'b' - 97 = 98 – 97 = 1 printf("%d", 'c' - 97); // 'c' - 97 = 99 – 97 = 2

Personally, I never hard-code the value 97 when converting characters to integers (partly because I never used to be able to remember it off the top of my head). Instead, I just use ‘a’ in place of 97, because the math will always work out:

printf("%d", 'a' - 'a'); // 'a' - 'a' = 97 – 97 = 0 printf("%d", 'b' - 'a'); // 'b' - 'a' = 98 – 97 = 1 printf("%d", 'c' - 'a'); // 'c' - 'a' = 99 – 97 = 2

Continued on the following page...

11. Compilation and Testing (CodeBlocks)

The key to getting multiple files to compile into a single program in CodeBlocks (or any IDE) is to create a project. Here are the step-by-step instructions for creating a project in CodeBlocks, which involves importing Varg.h, testcase01.c, and the Varg.c file you’ve created (even if it’s just an empty file so far).

1. Start CodeBlocks.

2. Create a New Project (File -> New -> Project).

3. Choose “Empty Project” and click “Go.”

4. In the Project Wizard that opens, click “Next.”

5. Input a title for your project (e.g., “Varg”).

6. Choose a folder (e.g., Desktop) where CodeBlocks can create a subdirectory for the project.

7. Click “Finish.”

Now you need to import your files. You have two options:

1. Drag your source and header files into CodeBlocks. Then right click the tab for each file and choose “Add file to active project.”

– or –

2. Go to Project -> Add Files.... Browse to the directory with the source and header files you want to import. Select the files from the list (using CTRL-click to select multiple files). Click “Open.” In the dialog box that pops up, click “OK.”

You should now be good to go. Try to build and run the project (F9).

Note that if you import both testcase01.c and testcase02.c, the compiler will complain that you have multiple definitions for main(). You can only have one of those in there at a time. You’ll have to swap them out as you test your code.

Yes, constantly swapping out the test cases in your project will be a bit annoying. You can avoid this if you’re willing to migrate away from an IDE and start compiling at the command line instead. If you’re interested in doing that in Windows, please look around online for instructions on how to make that happen, and see a TA in office hours if you get stuck. Alternatively, you might consider installing Linux on a separate partition of your hard drive. If you take that approach, just be sure to back up your hard drive first.

Note! Even if you develop your code with CodeBlocks on Windows, you ultimately have to transfer it to the Eustis server to compile and test it there. See the following page (Section 12, “ Compilation and Testing (Linux/Mac Command Line)”) for instructions on command line compilation in Linux.

12. Compilation and Testing (Linux/Mac Command Line)

To compile multiple source files (.c files) at the command line:

gcc Varg.c testcase01.c

By default, this will produce an executable file called a.out, which you can run by typing:

./a.out

If you want to name the executable file something else, use:

gcc Varg.c testcase01.c -o Varg.exe

...and then run the program using:

./Varg.exe

Running the program could potentially dump a lot of output to the screen. If you want to redirect your output to a text file in Linux, it’s easy. Just run the program using the following command, which will create a file called whatever.txt that contains the output from your program:

./Varg.exe > whatever.txt

Linux has a helpful command called diff for comparing the contents of two files, which is really helpful here since we’ve provided several sample output files. You can see whether your output matches ours exactly by typing, e.g.:

diff whatever.txt output01.txt

If the contents of whatever.txt and output01.txt are exactly the same, diff won’t have any output. It will just look like this:

seansz@eustis:~$ diff whatever.txt output01.txt

seansz@eustis:~$ _

If the files differ, it will spit out some information about the lines that aren’t the same. For example:

seansz@eustis:~$ diff whatever.txt output01.txt

1c1

< fail whale :(

---

> Hooray!

seansz@eustis:~$ _

13. Getting Started: A Guide for the Overwhelmed

Okay, so, this might all be overwhelming, and you might be thinking, “Where do I even start with this assignment?! I’m in way over my head!”

Don’t panic! There are plenty of TA office hours where you can get help, and here’s my general advice on starting the assignment:

1. First and foremost, start working on this assignment early. Nothing will be more frustrating than running into unexpected errors or not being able to figure out what the assignment is asking you to do on the day that it is due.

2. Secondly, glance through this entire PDF to get a general overview of what the assignment is asking you to do, even if you don’t fully understand each section right away.

3. Thirdly, before you even start programming, open up the test cases and sample output files included with this assignment and trace through a few of them to be sure you have an accurate understanding of what the function calls are supposed to be doing.

4. Once you’re ready to begin coding, start by creating a skeleton Varg.c file. Add a header comment with your name and NID, add some standard #include directives, and be sure to #include "Varg.h" from your source file. Then copy and paste each functional prototype from Varg.h into Varg.c, transform those prototypes into functions by removing the semicolon and setting up curly braces for each function signature, and then set up all those functions to return dummy values (some arbitrary char or float, as appropriate).

5. Test that your Varg.c source file compiles. Do this before you’ve even taken a stab at making the functions work! If you’re at the command line on a Mac or in Linux, your source file will need to be in the same directory as Varg.h, and you can test compilation like so:

gcc -c Varg.c

Alternatively, you can try compiling it with one of the test case source files, like so:

gcc Varg.c testcase01.c

For more details, see Section 12, “ Compilation and Testing (Linux/Mac Command Line).”

If you’re using an IDE (i.e., you’re coding with something other than a plain text editor and the command line), open up your IDE and start a project using the instructions above in Section 11, “ Compilation and Testing (CodeBlocks)”. Import Varg.h, testcase01.c, and your new Varg.c source file, and get the program compiling and running before you move forward. (Note that CodeBlocks is the only IDE we officially support in this class.)

6. Once you have your project compiling, go back to Section 8, “Function Requirements”, and read through the function requirements. Do some brainstorming on how you want to solve the problem. Don’t even try to write any code yet. Just assume you’ll be able to get your function to

read all the arguments one by one, and think about what you’ll do with each argument as you receive it.

7. Load up varsum.c and give it a read. You might need to read it a couple times before it all starts to click. Don’t be discouraged by that. Your brain is re-wiring yourself as you read, and setting itself up to comprehend documents like that much more rapidly in the future.

8. Once you kind of have a grasp of how to write variadic functions (even if it feels a bit vague at first), dive in fearlessly. Be bold! Go back to the list of required functions (Section 8, “Function Requirements”), and try to implement one function at a time, while referring to varsum.c regularly. Always stop to compile and test your code before moving on to another function! Throughout the semester, if you frequently stop to check whether your code is compiling, you will save yourself a lot of headaches.

9. If you get stuck while working on this assignment, draw diagrams on paper or a whiteboard. Make boxes for all the variables in your program. Trace through your code carefully, step by step, using these diagrams.

10. You’re bound to encounter errors in your code at some point. Use printf() statements liberally to verify that your code is producing the results you think it should be producing (rather than making assumptions that certain components are working as intended). You should get in the habit of being immensely skeptical of your own code and using printf() to provide yourself with evidence that your code does what you think it does.

11. If you encounter a segmentation fault, you should always be able to use printf() and fflush() to track down the exact line you’re crashing on.

12. This semester (especially in later programs), you’ll need to examine a lot of debugging output. You might want to set up a function that prints debugging strings only when you #define a DEBUG value to be something other than zero, so you can easily flip debugging output on and off. (Just be sure to remove your debugging statements before you submit your assignment, so your code is nice and clean and easy for us to read.)

13. When you find a bug, or if your program is crashing on a huge test case, don’t trace through hundreds of iterations of some for-loop to track down the error. Instead, try to cook up a new main() function with a very small test case (as few lines as possible) that directly calls the function that’s crashing. The less code you have to trace through, the easier your debugging tasks will be.

14. Deliverables

Submit a single source file, named Varg.c, via Webcourses. The source file should contain definitions for all the required functions (listed above), as well as any auxiliary functions you need to make them work.

Your source file must not contain a main() function. Do not submit additional source files, and do not submit a modified Varg.h header file. Your source file (without a main() function) should compile at

the command line using the following command:

gcc -c Varg.c

It must also compile at the command line if you place it in a directory with Varg.h and a test case file (for example, testcase01.c) and compile like so:

gcc Varg.c testcase01.c

Be sure to include your name and NID as a comment at the top of your source file.

15. Grading

The tentative scoring breakdown (not set in stone) for this programming assignment is:

50% correct output for test cases

25% implementation details (manual inspection of your code)

5% difficultyRating() is implemented correctly

5% hoursSpent() is implemented correctly

5% source file is named correctly (Varg.c); spelling and capitalization count

10% adequate comments and whitespace; source includes student name and NID

Note! Your program must be submitted via Webcourses, and it must compile and run on Eustis to receive credit. Programs that do not compile will receive an automatic zero.

Your grade will be based largely on your program’s ability to compile and produce the exact output expected. Even minor deviations (such as capitalization or punctuation errors) in your output will cause your program’s output to be marked as incorrect, resulting in severe point deductions. The same is true of how you name your functions and their parameters. Please be sure to follow all requirements carefully and test your program throughly.

Additional points will be awarded for style (appropriate commenting and whitespace) and adherence to implementation requirements. For example, the graders might inspect your mostFrequentChar() and fancyMostFrequentChar() functions to see whether they meet the special requirement listed in the function descriptions above.

Start early. Work hard. Good luck!

  • Programming Assignment #1: Varg
  • Abstract
  • 1. Overview
  • 2. Important Note: Test Case Files Look Wonky in Notepad
  • 3. Adopting a Growth Mindset
  • 4. Writing Variadic Functions
  • 5. Varg.h
  • 6. Test Cases and the test-all.sh Script
  • 7. Output
  • 8. Function Requirements
  • 9. Input Specifications Are a Contract
  • 10. ASCII Character Values
  • 11. Compilation and Testing (CodeBlocks)
  • 12. Compilation and Testing (Linux/Mac Command Line)
  • 13. Getting Started: A Guide for the Overwhelmed
  • 14. Deliverables
  • 15. Grading

varsum.c

// Sean Szumlanski // COP 3502, Fall 2017 // ============== // Varg: varsum.c // ============== // A program to illustrate the creation of variadic functions (functions that // can take a variable number of parameters). // // SEE ALSO: // http://www.lysator.liu.se/c/c-faq/c-7.html#7-1 #include <stdio.h> #include <stdarg.h> // mySum() takes any number of integers as its arguments, with the following // restriction: the first argument MUST be the number of integers to follow. // For example, to sum 1, 2, and 3, the proper function call would be: // // mySum(3, 1, 2, 3); // // Notice that since there are three integers to be summed, the first argument // to the function is 3. int mySum(int first, ...); // myOtherSum() takes any number of integers as its arguments, but has a // different restriction: the last integer to be summed will be zero, and zero // cannot occur anywhere else in the list of arguments. That is to say, the // function will know to stop summing as soon as it encounters a zero. // // For example, the following two functional calls will have the same result: // // myOtherSum(1, 2, 3, 0); // myOtherSum(1, 2, 3, 0, 6, 2, 7, 4, 8, 0); int myOtherSum(int first, ...); int main(void) { int d; // Recall that mySum() requires us to tell it how many integers it is // summing up. So in the function call below, the first 5 says, "You're // about to see five integers. Sum them up!" d = mySum(5, 1, 2, 3, 4, 5); printf("Result of mySum(): %d\n", d); // myOtherSum, on the other hand, will keep reading integers until it // encounters zero. That is why we terminate the following list of arguments // with a zero. Otherwise, the function would keep on summing, accessing // unpredictable parts of memory in a dangerous attempt to read more // integers! d = myOtherSum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0); printf("Result of myOtherSum(): %d\n", d); return 0; } // First and foremost: when dealing with an arbitrary number of arguments to a // function, we always capture the first argument explicitly into a variable, // and then shuttle the rest off to a list, using elipses. Here, we know that // the first argument to mySum() will always be an integer, so we capture it in // a variable of type int called "first." int mySum(int first, ...) { // We're going to hold the sum in a variable called "total," which we // initialize to zero. We're also going to use p and i to hold integers // later in the function. int total = 0; int p, i; // Now this is where things get crazy. We're declaring a variable of type // va_list, called "argp." Basically, argp, is going to hold our list of // arguments to this function! To be clear: va_list is a data type, just // like int, char, float, and so on. va_list argp; // This is how we initialize argp. The line basically means, "Okay, argp is // a list of arguments to this function. But where does it start? Well, it // starts with the first variable passed to this function, which we // conveniently named "first." If we had captured that variable under a // different name, we would use that name below. va_start(argp, first); // Now we're ready to get our arguments, one by one, using a loop. Remember // that the variable "first" tells us how many there are, so we want to loop // "first" number of times. for (i = 0; i < first; i++) { // The line below tells us to get the value of the next argument from // the list. (This will start by pulling the variable after "first," // because "first" itself isn't included in the "..." portion of the // list.) // // We have to tell the va_arg() function where to look for these // arguments, as well as what type of data we are pulling. We've got all // the information we need about our arguments stored in the variable // called "argp," so that's our first argument to the va_arg() function. // We also know that we're only dealing with integers, so the second // argument to va_arg() is int -- the type of data we're reading. If we // were reading a different type of data, we would replace "int" with // that data type (e.g., "double"). There are some exceptions here, // though, which your compiler might warn you about if you encounter // them. ;) // // The resulting value is stored in p. // // After we pull an integer out of argp, it is removed from the list, // and the next time we call the va_arg function, it will give us the // next integer in the list. p = va_arg(argp, int); // And of course, we want to add p to total in order to keep track of // the sum as we go. Recall that "total" was intialized to zero at the // beginning of the program. total += p; } // This frees up any lingering memory associated with the argp variable and // helps ensure that we don't have any memory leaks emanating from this // function. va_end(argp); // Finally, the loop has terminated and we now return the value of "total," // which should be the sum of all the arguments passed to mySum() (except // for the first argument, which was just an argument count). return total; } int myOtherSum(int first, ...) { // These first lines are the same as above, except that we initialize // "total" to the value of "first," since in this function, the first // argument is actually part of the sequence of integers that we want to // sum. We also don't need the variable "i" that was used in the mySum() // function, because we don't use a for-loop in this one. int total = first; int p; va_list argp; // If the first argument was zero, then we don't even look for more // arguments, because the function is supposed to stop summing as soon as we // see a zero. if (total == 0) return 0; // Our list setup is the same as before. va_start(argp, first); // Here we just keep pulling integers off of the argp list until we see a // zero. Recall that the zero is our cue to stop. while ((p = va_arg(argp, int)) != 0) total += p; // This frees up any lingering memory associated with the argp variable and // helps ensure that we don't have any memory leaks emanating from this // function. va_end(argp); // And finally, return the sum. return total; }