Vous êtes sur la page 1sur 5

CS107 J Zelenski

Handout #3 Oct 28, 2011

Midterm practice
Midterm Exam: Friday November 4th 11am-12:15pm Gates B01, if your last name begins A-H Annenberg Auditorium, if your last name begins I-Z

There are two rooms, and you are assigned to one according to the first letter of your last name. Please note where to go; you are required to attend your assigned location. SCPD students: Local SCPD students attend the regular on-campus exam. This ensures you will be able to ask questions and receive clarifications with the group. Those outside the Bay Area should arrange for your SCPD site coordinator to administer the exam onsite to you on Friday. Remote students must send e-mail to our SCPD TA Jeff (jchern@stanford.edu) by Monday Oct 31 to initiate arrangements for an on-site exam. Open book/notes You may bring textbooks, notes, handouts, code printouts, etc. to refer to during the exam. No computers, phones, PDAs, or other electronic devices may be used. The exam will include a list of relevant stdlib function prototypes. We are not expecting you to memorize minutiae and the exam will not focus on them. However, don't let the "openbook" nature delude you into not preparing. There will not be time to (re-)learn the material during the exam. You must come facile and knowledgeable to readily answer the questions, only referring to your notes for the occasional detail. Material The exam will concentrate on material covered in the labs and assignments. For the midterm, this means questions that delve into strings, pointers, arrays, function pointers, low-level memory manipulation, and data representation (e.g. bits, ints, floats). IA32 assembly will not be tested on the midterm. When evaluating your C code, we will not be picky about minor syntax/oversights (missing braces around a block of clearly indented code, forgetting to declare an integer variable, we don't ask for #include's etc.), but there are subtleties that matter immensely, e.g., a int** is just one character different than int*, yet there is a world of difference between the two! Practice You're unlikely to do well on a test if you don't understand the core concepts, but there is no guarantee about the inverse. Some students who are quite accomplished in practice don't manage to demonstrate that same proficiency in the exam setting. Writing code on paper under time constraints is different than working at the computer. Most students need practice to adapt their skills. We recommend you sit down with the problems and write out solutions in longhand. This is much more valuable than a passive review of the

2 problem alongside its solution where it is too easy to conclude "ah, yes, I would have done that" only to find yourself sad during the real exam when there is no provided solution to agree with! The rest of this handout is the midterm I gave last quarter in CS107 so you can consider the questions fairly representative in terms of format, difficulty, and content. To conserve paper, I cut back on answer space. The real exam will have more room for your answers and scratch work. We'll distribute solutions in the next lecture. There are also many excellent problems in the K&R and B&O texts if you'd like further practice.

Problem 1: C-strings Write the RemoveRange function that removes a range of characters from a string. The range is specified as a position and a count. The input string str is destructively modified to remove count characters starting as position pos. As an example, removing the range (1, 3) from the string "computer" makes it "cuter". The function does no error-checking to verify the range is valid for the input string. You should implement the function as a single call to memmove as shown below.
void RemoveRange(char *str, int pos, int count) { memmove(________________________________________, ________________________________________, ________________________________________); }

The RemoveRange function could instead be written as a call to strcpy, which is a bit easier to use than memmove. However, memmove is used because it does something essential that strcpy (and memcpy) does not. What is it? The function does no error-checking. Describe in detail the behavior of the invalid call RemoveRange(str, 3, 12) when str points to a heap-allocated copy of "stanford".

Problem 2: Implementing and using generic interfaces For this problem, you will write the CMapPut and CMapMap operations for an alternative implementation of CMap. This implementation is not a hashtable, but instead stores keyvalue pairs in a CVector and uses CVector operations to add, remove, and access entries. We provide the CMapImplementation struct defintion and the CMapCreate function shown below. Your code must work with this code unmodified.

3
struct CMapImplementation { CVector *entries; int valueSize; }; /* Function: CMapCreate * Usage: CMap *cm = CMapCreate (sizeof(short), 10, NULL); * ------------------------------------------------------* Allocates a new empty map to hold values of the specified size * in bytes. The capacity estimates the number of entries this * map will hold. An assert is raised if valueSize or capacity * is non-positive. */ CMap *CMapCreate(int valueSize, int capacity, CMapFreeValueFn unused) { assert(valueSize > 0 && capacity > 0); CMap *cm = (CMap *)malloc(sizeof(CMap)); cm->entries = CVectorCreate(sizeof(char *) + valueSize, capacity, NULL); // we are ignoring freefn cm->valueSize = valueSize; return cm; }

In this CMap implementation, each entry in the CVector is a char* stored contiguously with the value. The char* points to a heap-allocated copy of the key characters. Consider a CMap storing values of type double to associate prices with grocery items. The entries in its CVector would be laid out as diagrammed below.
'()*+&,,,,,,,,,,-./01+&

a) Write the CMapPut function for this implementation of the CMap. You do not need to maintain the entries in the CVector in sorted order. Your function can (and should) call CMapGet to search for any existing entry that should be overwritten. You may assume CMapGet has been written and works correctly.
/* Function: CMapPut * Usage: CMapPut(mymap, "CS107", &val); * -------------------------------------* Associates given key with a new value in this CMap. If there is an * existing value for this key, it is replaced with the new value. * The new value's contents are copied from the memory pointed to by * valueAddr. A copy of the key string is made by the CMap to store * internally within the map. Keys are compared case-sensitively, e.g. * "binky" is not the same key as "BinKy". */ void CMapPut(CMap *cm, const char *key, const void *valueAddr)

{ {

!"##

$"%&

b) Complete the CMapMap function started below for this CMap implementation.
typedef void (*CMapMapEntryFn)(char *key, void *valueAddr, void *data); /* Function: CMapMap * Usage: CMapMap(mymap, PrintEntry, &myData); * -------------------------------------------* Iterates over all of the entries in this CMap and calls mapfn on * each entry. The callback function is called with a char * key, a * pointer to its associated value, and the data pointer. The * data pointer allows the client to pass extra state information if * desired. If no client data is needed, this argument can be NULL. * The entries are accessed in no particular order. */ void CMapMap(CMap *cm, CMapMapEntryFn fn, void *data) { for (int i = 0; i < CVectorCount(cm->entries); i++) { void *entry = CVectorNth(cm->entries, i);

Problem 3: Bits, bytes, and numbers a) Write a function that given a float f will return the next float nearest to f, i.e the immediate neighbor of f on the number line of representable floating point values. The function may return either the left or right neighbor. The function should work correctly for normalized or denormalized inputs, you may ignore exceptional inputs. Hint: there are at least two easy solutions that require no more than a few lines of code.
float Neighbor(float f) {

b) The Mystery function takes an integer and returns a boolean computed as below:
bool Mystery(int n) { return (n & (n-1)) == 0; }

Characterize the result returned by Mystery for the inputs listed in the chart below. If n is positive negative zero true Mystery(n) returns.

5 Problem 4: IA32 assembly1 The following IA32 instructions are the disassembly from the Dinky function:
Dinky: push mov shll mov mov mov movb lea sub pop ret %ebp %esp,%ebp $0x2,0x8(%ebp) 0xc(%ebp),%eax (%eax),%eax 0x10(%ebp),%edx $0x61,(%edx,%eax,1) 0x10(%ebp),%eax $0x4,%eax %ebp # function prolog # first line of C code # second line of C code

# third line of C code # function epilog

Fill in the body of the Dinky function with three lines of C code that compile to the above IA32 instructions. Do not use any typecasts.
void *Dinky(int one, int *two, char *three) { ___________________________________________________ ___________________________________________________ return ____________________________________________ }

Note: In previous quarters, the midterm has included light coverage of IA32, as shown in the problem above. This quarter I have decided to defer testing this material to the final; we will not be testing IA32 on the midterm.