Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

Programming Assignment #1: Varg1 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

Programming Assignment #1: Varg1

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. Its 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

You have 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

Varg.c

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

1. Overview

In this assignment, youll 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 dont panic. Weve 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.

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 youre 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, youll 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

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 ) 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

Weve 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 dont violate the program specification, but

which havent already been covered in the test cases included with the assignment?

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 Cs 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 Cs 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 its

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 havent 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 dont need to know any more about ASCII than what

Ive written up in this section.)

To see a characters 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 youve created (even if its 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. Youll have to

swap them out as you test your code.

!

14. Deliverables

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

Contents of 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

Contents of varsum.c

// ============== // 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 #include

// 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 ", 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 ", 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; }

Contents of testcase01.c

// ================== // Varg: testcase01.c // ================== // Boundary check to make sure your difficultyRating() and hoursSpent() // functions are implemented correctly.

#include #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 ", success ? "Hooray!" : "fail whale :(");

return 0; }

contents of testcase02.c

// ================== // Varg: testcase02.c // ================== // A simple test of the mostFrequentChar() function.

#include #include "Varg.h"

int main(void) { char c = mostFrequentChar(7, 'a', 'b', 'c', 'd', 'd', 'b', 'a');

if (c == 'd') printf("Hooray! "); else printf("fail whale :( ");

return 0; }

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Logidata+ Deductive Databases With Complex Objects Lncs 701

Authors: Paolo Atzeni

1st Edition

354056974X, 978-3540569749

Students also viewed these Databases questions

Question

What are some of the reasons for poor decisions?

Answered: 1 week ago