Programming Assignment #2: Smart Arrays COP 3502, Fall 2017 Due: Sunday, Septemb
ID: 3890238 • Letter: P
Question
Programming Assignment #2: Smart Arrays
COP 3502, Fall 2017
Due: Sunday, September 24, before 11:59 PM
Table of Contents
Abstract........................................................................................................2
1. Overview.................................................................................................3
2. SmartArray.h............................................................................................4
3. Function Requirements............................................................................5
4. Compilation and Testing (CodeBlocks)...................................................8
5. Compilation and Testing (Linux/Mac Command Line)..........................9
6. Getting Started: A Guide for the Overwhelmed....................................10
7. Troubleshooting: File Not Found Errors with Mac OS X.....................12
8. Test Cases and the test-all.sh Script.......................................................12
9. Deliverables...........................................................................................12
10. Grading................................................................................................13
11. Special Restrictions.............................................................................13
Abstract
In this programming assignment, you will implement smart arrays (arrays
that expand automatically whenever they get too full). This is an
immensely powerful and awesome data structure, and it will ameliorate
several problems we often encounter with arrays in C (see pg. 3 of this
PDF).
By completing this assignment, you will gain advanced experience
working with dynamic memory management and structs in C. You will
also gain additional experience managing programs that use multiple
source files. In the end, you will have an awesome and useful data
structure that you can reuse in the future.
Attachments
SmartArray.h, testcase{01-05}.c, output{01-05}.txt, names.txt, SmartArray-diagram.pdf, and test-all.sh
Deliverables
SmartArray.c
(Note! Capitalization and spelling of your filename matters!)
1. Overview
A smart array is an array that grows to accommodate new elements whenever it gets too full. As with
normal arrays in C, we have direct access to any index of the smart array at any given time. There are
four main advantages to using smart arrays, though:
1. We do not need to specify the length of a smart array when it is created. Instead, it will
automatically expand when it gets full. This is great when we don’t know ahead of time just
how much data we’re going to end up holding in the array.
2. We will use get() and put() functions to access individual elements of the array, and these
functions will check to make sure we aren’t accessing array positions that are out of bounds.
(Recall that C doesn’t check whether an array index is out of bounds before accessing it during
program execution. That can lead to all kinds of whacky trouble!)
3. If our arrays end up having wasted space (i.e., they aren’t full), we can trim them down to size.
4. In C, if we have to pass an array to a function, we also typically find ourselves passing its
length to that function as a second parameter. With smart arrays, the length will get passed
automatically with the array, as they’ll both be packaged together in a struct.
While some languages offer built-in support for smart arrays (such as Java’s ArrayList class), C does
not. That’s where you come in. You will implement basic smart array functionality in C, including:
1. automatically expanding the smart array’s capacity when it gets full;
2. adding new elements into arbitrary positions in the smart array, or at the end of the smart array;
3. providing safe access to elements at specific positions in the smart array;
4. gracefully signaling to the user (i.e., the programmer (re-)using your code) when he or she
attempts to access an index in the smart array that is out of bounds (instead of just segfaulting);
5. … and more!
In this assignment, your smart array will be designed to hold arrays of strings. A complete list of the
functions you must implement, including their functional prototypes, is given below in Section 3,
“Function Requirements”). You will submit a single source file, named SmartArray.c, that contains all
required function definitions, as well as any auxiliary functions you deem necessary. In SmartArray.c,
you should #include any header files necessary for your functions to work, including SmartArray.h
(see Section 2, “SmartArray.h”).
Note that 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. We realize this is
completely new territory for most of you, so don’t panic. We’ve included instructions on compiling
multiple source files into a single executable (e.g., mixing your SmartArray.c with our SmartArray.h
and testcase01.c) in Sections 4 and 5 (“Compilation and Testing”).
Although we have included 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. SmartArray.h
This header file contains the struct definition and functional prototypes for the smart array functions
you will be implementing. You should #include this file from your SmartArray.c file, like so:
#include "SmartArray.h"
Recall that 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 SmartArray.h in any way, and you should not send SmartArray.h when you
submit your assignment. We will use our own unmodified copy of SmartArray.h when compiling your
program.
If you write auxiliary functions in SmartArray.c (which is strongly encouraged!), you should not add
those functional prototypes to SmartArray.h. Just put those functional prototypes at the top of your
SmartArray.c.
Think of SmartArray.h as a public interface to the SmartArray data structure. It contains only the
functions that the end user (i.e., the programmer (re-)using your code) should call in order to create and
use a SmartArray. You do not want the end user to call your auxiliary functions directly, so you do not
put those functional prototypes in SmartArray.h. That way, the end user doesn’t need to worry about
all your auxiliary functions in order to use an SmartArray; everything just works. (And you don’t have
to worry about the end user mucking everything up by accidentally calling auxiliary functions that he
or she shouldn’t be messing around with!)
The basic struct you will use to implement the smart arrays (defined in SmartArray.h) is as follows:
typedef struct SmartArray
{
char **array; // pointer to array of strings
int size; // number of elements in array
int capacity; // length of array (maximum capacity)
} SmartArray;
The SmartArray struct contains a double char pointer that can be used to set up a 2D char array
(which is just an array of char arrays, otherwise known as an array of strings). array will have to be
allocated dynamically at runtime. It will probably be the bane of your existence for the next week or so.
The struct also has size and capacity variables, which store the number of elements in the array
(initially zero) and the current length (i.e., maximum capacity) of the array, respectively.
3. Function Requirements
In the source file you submit, SmartArray.c, you must implement the following functions. You may
implement any auxiliary functions you need to make these work, as well. Please be sure the spelling,
capitalization, and return types of your functions match these prototypes exactly. In this section, I often
refer to malloc(), but you’re welcome to use calloc() or realloc() instead, as you see fit.
SmartArray *createSmartArray(int length);
Description: Dynamically allocate space for a new SmartArray. Initialize its internal array to be
of length length or DEFAULT_INIT_LEN, whichever is greater. (DEFAULT_INIT_LEN is defined
in SmartArray.h.) Properly initialize pointers in the array to NULL, and set the size and
capacity members of the struct to the appropriate values.
Output: “-> Created new SmartArray of size <N>.” (Output should not include the
quotes. Terminate the line with a newline character, ‘ ’. <N> should of course be the length of
the new array, without the angled brackets.)
Returns: A pointer to the new SmartArray, or NULL if any calls to malloc() failed.
SmartArray *destroySmartArray(SmartArray *smarty);
Description: Free any dynamically allocated memory associated with the SmartArray struct
and return NULL.
Returns: NULL pointer.
SmartArray *expandSmartArray(SmartArray *smarty, int length);
Description: Dynamically allocate a new array of length length. Copy the contents of
smarty’s old array into the new array. Free any memory associated with the old smartyarray
that is no longer in use, then set smartyarray to point to the newly created array. Be sure all
pointers are properly initialized. Update the size and capacity of the SmartArray (if
applicable).
Note: If length is less than or equal to smarty’s current array capacity, or if the smarty pointer
is NULL, you should NOT modify the SmartArray at all. In that case, just return from the
function right away without producing any output.
Output: “-> Expanded SmartArray to size <N>.” (Output should not include the quotes.
Terminate the line with a newline character, ‘ ’. <N> should be the new length of the array,
without the angled brackets. Do NOT produce any output if you the array is not expanded.)
Returns: A pointer to the SmartArray, or NULL if any calls to malloc() failed.
SmartArray *trimSmartArray(SmartArray *smarty);
Description: If smarty’s capacity is greater than its current size, trim the length of the array
to the current size. You will probably want to malloc() a new array to achieve this. If so,
avoid memory leaks as you get rid of the old array. Update any members of smarty that need to
be updated as a result of this action.
Output: “-> Trimmed SmartArray to size <N>.” (Output should not include the quotes.
Terminate the line with a newline character, ‘ ’. <N> should be the new length of the array,
without the angled brackets. Do NOT produce any output if the length of the array is not
reduced by this function.)
Returns: A pointer to the SmartArray, or NULL if malloc() failed or if smarty was NULL.
char *put(SmartArray *smarty, char *str);
Description: Insert a copy of str into the next unused cell of the array. If the array is already
full, call expandSmartArray() to grow the array to length (capacity * 2 + 1) before
inserting the new element. When copying str into the array, only allocate the minimum
amount of space necessary to store the string.
Returns: A pointer to the copy of the new string that was inserted into the array, or NULL if the
string could not be added to the array (e.g., malloc() failed, or smarty or str was NULL).
char *get(SmartArray *smarty, int index);
Description: Attempts to return the element at the specified index. This is where you protect
the user from going out-of-bounds with the array.
Returns: A pointer to the string at position index of the array, or NULL if index was out of
bounds or the smarty pointer was NULL.
char *set(SmartArray *smarty, int index, char *str);
Description: If the array already has a valid string at position index, replace it with a copy of
str. Otherwise, the operation fails and we simply return NULL. Ensure that no more space is
used to store the new copy of str than is absolutely necessary (so, you might have to use
malloc() and free() here).
Returns: A pointer to the copy of the string placed in the SmartArray, or NULL if the operation
failed for any reason (e.g., invalid index, or smarty or str was NULL).
char *insertElement(SmartArray *smarty, int index, char *str);
Description: Insert a copy of str at the specified index in the array. Any elements to the right
of index are shifted one space to the right. If the specified index is greater than the array’s
size, the element being inserted should be placed in the first empty position in the array.
(Continued from previous page…) As with the put() function, if the SmartArray is already full,
call expandSmartArray() to grow the array to length (capacity * 2 + 1) before inserting
the new element. When copying str into the array, only allocate the minimum amount of space
necessary to store the string.
Returns: A pointer to the copy of the string inserted into the array, or NULL if insertion fails for
any reason (e.g., malloc() failed, or smarty or str was NULL).
int removeElement(SmartArray *smarty, int index);
Description: Remove the string at the specified index in the array. Strings to the right of index
are shifted one space to the left, so as not to leave a gap in the array. The SmartArray’s size
member should be updated accordingly. If index exceeds the SmartArray’s size, nothing is
removed from the array.
Returns: 1 if an element was successfully removed from the array, 0 otherwise (including the
case where the smarty pointer is NULL).
int getSize(SmartArray *smarty);
Description: This function returns the number of elements currently in the array. We provide
this function to discourage the programmer from accessing smartysize directly. That way, if
we decide to change the name or meaning of the size variable in our SmartArray struct, the
programmers who download the latest version of our code can get it working right out of the
box; they don’t have to go through their own code and change all instances of smartysize to
something else, as long as we provide them with a getSize() function that works.
Returns: Number of elements currently in the array, or -1 if the smarty pointer is NULL.
void printSmartArray(SmartArray *smarty);
Description: Print all strings currently in the array.
Output: Print all strings currently in the array. Print a newline character, ‘ ’, after each string.
If the SmartArray pointer is NULL, or if the array is empty, simply print “(empty array)”
(without quotes), followed by a newline character, ‘ ’.
double difficultyRating(void);
Returns: 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);
Returns: An estimate (greater than zero) of the number of hours you spent on this assignment.
4. Compilation and Testing (CodeBlocks)
The key to getting a 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, importing
SmartArray.h, testcase01.c, and the SmartArray.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., “SmartArray”).
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.
5. Compilation and Testing (Linux/Mac Command Line)
To compile multiple source files (.c files) at the command line:
gcc SmartArray.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 SmartArray.c testcase01.c -o SmartArray.exe
...and then run the program using:
./SmartArray.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:
./SmartArray.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
6c6
< Size of array: 0
---
> Size of array: -1
seansz@eustis:~$ _
6. 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! We’re here to help in office hours, and here’s my general advice on starting the
assignment (as well as a few hints and spoilers):
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. Start by creating a skeleton SmartArray.c file. Add a header comment, add some standard
#include directives, and be sure to include SmartArray.h from your source file. Then copy
and paste each functional prototype from SmartArray.h into SmartArray.c, and set up all
those functions return dummy values (zero, NULL, etc.). For example:
#include <stdio.h>
#include <stdlib.h>
#include "SmartArray.h"
SmartArray *createSmartArray(int length)
{
return NULL;
}
int getSize(SmartArray *smarty)
{
return 0;
}
// ...and so on.
3. Test that your SmartArray.c source file compiles. 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 SmartArray.h, and you can test
compilation like so:
gcc -c SmartArray.c
Alternatively, you can try compiling it with one of the test case source files, like so:
gcc SmartArray.c testcase01.c
For more details, see Section 5, “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 4,
“Compilation and Testing (CodeBlocks)”. Import SmartArray.h, testcase01.c, and your new
SmartArray.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.)
4. Once you have your project compiling, go back to the list of required functions (Section 3,
“Function Requirements”), and try to implement one function at a time. Always stop to compile
and test your code before moving on to another function!
5. You’ll probably want to start with the createSmartArray() function. (Alternatively,
printSmartArray() might be a good starting point, as well.)
As you work on createSmartArray(), write your own main() function that calls
createSmartArray() and then checks the results. For example, you’ll want to ensure that
createSmartArray() is returning a non-NULL pointer to begin with, and that the fields inside
the SmartArray struct that it created are properly initialized when you examine them back in
main(). If you’re uncertain about how to call certain functions, read through my sample main
files for examples.
6. After writing createSmartArray(), I would probably work on the printSmartArray()
function, because it will be immensely useful in debugging your code as you work. Here’s how
I’d test these functions at first: In your own main() function, call createSmartArray(). Then,
back in main(), manually insert one or two strings into the smart array before passing it to the
printSmartArray() function. Make sure everything works as intended and the output is as
expected. If not, trace carefully through your code to see what went wrong.
7. If you get stuck, draw diagrams. Make boxes for all the variables in your program. If you’re
dynamically allocating memory, diagram them out and make up addresses for all your variables.
Trace through your code carefully using these diagrams.
8. With so many pointers, 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.
9. When looking for a segmentation fault, you should always be able to use printf() and
fflush() to track down the exact line you’re crashing on.
10. 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.)
9. Deliverables
Your source file must not contain a main() function. Do not submit additional source files, and do not
submit a modified SmartArray.h header file. Your source file (without a main() function) should
compile at the command line using the following command:
gcc -c SmartArray.c
It must also compile at the command line if you place it in a directory with SmartArray.h and a test
case file (for example, testcase01.c) and compile like so:
gcc SmartArray.c testcase01.c
10.Grading
The expected scoring breakdown for this programming assignment is:
50% correct output for test cases
25% implementation details (manual inspection of your code)
5% difficultyRating() returns a double in the expected range
5% hoursSpent() returns a double in the expected range
5% source file is named correctly (SmartArray.c); capitalization counts
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 (proper commenting and whitespace) and adherence to
implementation requirements. For example, the graders might inspect your destroySmartArray()
function to see that it is actually freeing up memory properly.
11. Special Restrictions
Please carefully adhere to the following restrictions:
1. It’s very important that you do not include a main() function in your SmartArray.c file. If
your source file has a main() function, it will fail to compile during testing, and you will not
receive credit for the assignment.
2. Please do not use global variables.
3. Please avoid mid-function variable declarations. Within each function, all the variables you use
should be declared at the top of that function.
4. Please do not make system calls; eliminate system("pause") from your vocabulary.
Explanation / Answer
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SmartArray.h"
// this creates a smart array pointer
// our code should create an array that dynamically increases or decreases
SmartArray *createSmartArray(int length)
{
int n=0, i, capacity;
// Dynamically allocate space for a new SmartArray
SmartArray *smarty;
char **temp;
temp = NULL;
smarty = malloc(sizeof(SmartArray));
if(smarty==NULL)
return NULL;
smarty->size = 0;
// Initialize its internal array to be of length length or
// DEFAULT_INIT_LEN
if(length <= DEFAULT_INIT_LEN)
{
temp = malloc(sizeof(char * ) * DEFAULT_INIT_LEN);
n = DEFAULT_INIT_LEN;
}
else if (length > DEFAULT_INIT_LEN )
{
temp = malloc(sizeof(char * ) * length);
n = length;
}
smarty->capacity = n;
if (temp == NULL)
return NULL;
smarty->array=temp;
// initialize pointers in the array to NULL
for (i=0; i<n; i++)
smarty->array[i] = NULL;
printf("-> Created new SmartArray of size %d. ", n );
return smarty;
}
// this function should print the contents of array
// if the array is empty it prints empty array
void printSmartArray(SmartArray *smarty)
{
int i, siz, capacity, n;
if(smarty==NULL)
{
printf("(empty array) ");
return;
}
siz = smarty->size;
capacity = smarty->capacity;
if (smarty->array==NULL)
{
printf("(empty array) ");
return;
}
else if(smarty->array[0]==NULL)
{
printf("(empty array) ");
return;
}
else if(smarty->array!=NULL)
{
for(i=0; i<capacity; i++)
{
if(smarty->array[i]!=NULL)
printf("%s ", smarty -> array[i]);
}
}
}
// free the smart array in reverse order of allocation
// must free the memory in order to avoid leaks
SmartArray *destroySmartArray(SmartArray *smarty)
{
int i, j;
if(smarty==NULL)
return NULL;
// if smarty still exists but the array is null
// must delete smarty and lurking array
if(smarty->array==NULL)
{
free(smarty->array);
free(smarty);
return NULL;
}
for(i=0; i<smarty->capacity; i++)
{
free(smarty->array[i]);
}
free(smarty->array);
free(smarty);
return NULL;
}
char *put(SmartArray *smarty, char *str)
{
// use strlen to find string length
// insert copy of str in next unused cell
int slen , size, capacity;
char *tempVar;
// may want to create a temp variable to store str
tempVar=NULL;
if(smarty==NULL)
return NULL;
if(str==NULL)
return NULL;
size = smarty->size;
capacity = smarty->capacity;
slen = strlen(str);
// expands the array if full
// but really just creates an array of capacity*2 +1 and destroys old
if (size==capacity)
{
expandSmartArray( smarty, (capacity * 2 + 1));
}
tempVar = malloc(sizeof(char) * (slen+1));
if(tempVar==NULL)
return NULL;
strcpy(tempVar, str);
smarty->array[size] = tempVar;
if (str== NULL||smarty->array== NULL||smarty==NULL)
return NULL;
smarty->size = size + 1;
// return the contents of string pointer
return smarty->array[size];
}
// expands smartArray to size of length
SmartArray *expandSmartArray(SmartArray *smarty, int length)
{
int i, cap, si;
char **tempArray;
if(smarty==NULL)
return NULL;
if(smarty->array==NULL)
return NULL;
tempArray=NULL;
si = smarty->size;
cap = smarty->capacity;
if(length <= cap)
{
return NULL;
}
if(cap<length){
// Initialize its internal array to be of length length or DEFAULT_INIT_LEN
tempArray = malloc(sizeof(char * ) * length);
if(tempArray == NULL)
return NULL;
// next copy the old addresses to the temp
for(i=0; i<si; i++)
{
// array is basically temp variable
tempArray[i] = smarty->array[i];
}
for (i=si; i<length; i++)
{
tempArray[i]= NULL;
}
// erase the old smarty array
free(smarty->array);
// copies the temp array address to the old array
smarty->array = tempArray;
smarty->capacity = length;
printf("-> Expanded SmartArray to size %d. ", length);
}
else
{
return NULL;
}
return smarty;
}
// returns the element at the index
// this function protects the user from going out of bounds with the array
char *get(SmartArray *smarty, int index)
{
// if index was out of bounds or if the smarty pointer was null
if((index < 0) || (index > smarty->capacity)|| smarty==NULL)
return NULL;
return smarty->array[index];
}
// sets a string at the index indicated
// if no string null; if it does replace
char *set(SmartArray *smarty, int index, char *str)
{
char *tempVar;
int slen, size;
if((index < 0) || (index > smarty->capacity)|| smarty==NULL||str==NULL)
return NULL;
size = smarty->size;
tempVar=NULL;
slen = strlen(str);
if(smarty->array[index]==NULL)
return NULL;
tempVar = malloc(sizeof(char) * (slen+1));
if(tempVar==NULL)
return NULL;
strcpy(tempVar, str);
free(smarty->array[index]);
smarty->array[index]=tempVar;
if(smarty->array[index] != tempVar)
return NULL;
return smarty->array[index];
}
// insert copy of str at the specified index
// shift all others to the left
char *insertElement(SmartArray *smarty, int index, char *str)
{
// use strlen to find string length
// insert copy of str in next unused cell
int slen , size, capacity, i;
char *tempVar;
char **tempArray;
if((index < 0) || smarty==NULL||str==NULL)
return NULL;
size = smarty->size;
capacity = smarty->capacity;
slen = strlen(str);
tempVar = NULL;
tempArray=NULL;
tempVar = malloc(sizeof(char) * (slen+1));
if(tempVar==NULL)
return NULL;
strcpy(tempVar, str);
if (size==capacity)
{
expandSmartArray( smarty, (capacity * 2 + 1));
}
if (index>=size)
{
smarty->array[size]=tempVar;
if(smarty->array[size] != tempVar)
return NULL;
smarty->size= size +1;
}
else if(index<size)
{
tempArray = malloc(sizeof(char * ) * capacity);
if(tempArray == NULL)
return NULL;
if(index>0)
{
for(i=0; i<index; i++)
tempArray[i]=smarty->array[i];
}
tempArray[index]=tempVar;
// next copy the old addresses to the temp
for(i=index; i<size; i++)
{
tempArray[i+1] = smarty->array[i];
}
for (i=size+1; i<capacity; i++)
{
tempArray[i]= NULL;
}
// copies the temp array address to the old array
smarty->array = tempArray;
smarty->size= size +1;
}
// elements are shifted to the right one space
if(smarty->array[index]==tempVar)
return smarty->array[index];
return NULL;
}
// remove the string at the specified index in array
// no gaps left
int removeElement(SmartArray *smarty, int index)
{
int i, capacity, size;
if (index<0 || smarty==NULL)
return 0;
size = smarty->size;
capacity = smarty->capacity;
if(size<=index)
return 0;
if(smarty->array==NULL)
return 0;
if(smarty->array[index]==NULL)
return 0;
smarty->array[index]= NULL;
size = smarty->size;
for(i=index;i<size; i++)
{
smarty->array[i]=smarty->array[i+1];
}
for(i=size;i<capacity;i++)
{
smarty->array[i]=NULL;
}
smarty->size = size-1;
return 1;
}
int getSize(SmartArray *smarty)
{
int size;
if(smarty==NULL)
return -1;
size = smarty->size;
if(smarty->capacity==0)
return size;
if(smarty->array!=NULL)
return size;
return -1;
}
// trim any extra nodes from the array
SmartArray *trimSmartArray(SmartArray *smarty)
{
int capacity, size, i;
char **tempArray;
tempArray=NULL;
if(smarty==NULL)
return NULL;
size = smarty->size;
capacity = smarty ->capacity;
if(capacity==0)
return NULL;
// what happens if the size is zero
if (size == 0)
{
for(i=0; i<capacity; i++)
free(smarty->array[i]);
free(smarty->array);
smarty->array=NULL;
smarty->capacity=0;
}
else if (capacity>size)
{
tempArray=malloc(sizeof(char*)*size);
if(tempArray == NULL)
return NULL;
smarty->capacity = size;
for(i=0; i<size; i++)
{
tempArray[i] = smarty->array[i];
}
free(smarty->array);
smarty->array=tempArray;
}
// output if length trimmed
printf("-> Trimmed SmartArray to size %d. ", size);
return smarty;
}
double difficultyRating(void)
{
return 5.0;
}
double hoursSpent(void)
{
return 40.0;
}
----------------------------------------------------------------------------
SmartArray.h
----------------------------------------
#ifndef __SMART_ARRAY_H
#define __SMART_ARRAY_H
// Default capacity for new SmartArrays
#define DEFAULT_INIT_LEN 10
typedef struct SmartArray
{
// We will store an array of strings (i.e., an array of char arrays)
char **array;
// Size of array (i.e., number of elements that have been added to the array)
int size;
// Length of the array (i.e., the array's current maximum capacity)
int capacity;
} SmartArray;
// Functional Prototypes
SmartArray *createSmartArray(int length);
SmartArray *destroySmartArray(SmartArray *smarty);
SmartArray *expandSmartArray(SmartArray *smarty, int length);
SmartArray *trimSmartArray(SmartArray *smarty);
char *put(SmartArray *smarty, char *str);
char *get(SmartArray *smarty, int index);
char *set(SmartArray *smarty, int index, char *str);
char *insertElement(SmartArray *smarty, int index, char *str);
int removeElement(SmartArray *smarty, int index);
int getSize(SmartArray *smarty);
void printSmartArray(SmartArray *smarty);
double difficultyRating(void);
double hoursSpent(void);
#endif
-------------------------------------------------------------
testcase01.c / main
-------------------------------------------
#include <stdio.h>
#include <string.h>
#include "SmartArray.h"
int main(void)
{
int i; char buffer[32];
SmartArray *smarty1 = createSmartArray(-1);
SmartArray *smarty2 = createSmartArray(-1);
FILE *ifp = fopen("names.txt", "rb");
// Read all names from the file and add them to smarty1.
while (fscanf(ifp, "%s", buffer) != EOF)
put(smarty1, buffer);
// Add the names to smarty2 in reverse order.
for (i = getSize(smarty1) - 1; i >= 0; i--)
put(smarty2, get(smarty1, i));
// Print the contents of smarty1.
printf(" -- SMART ARRAY 1: -- ");
printSmartArray(smarty1);
// Print the contents of smarty2.
printf(" -- SMART ARRAY 2 (First Names): -- ");
printSmartArray(smarty2);
// Swap last names with first names in smarty2.
for (i = 0; i < getSize(smarty2); i++)
{
if (strcmp(get(smarty2, i), "Daniel") == 0)
set(smarty2, i, "Mandragona");
else if (strcmp(get(smarty2, i), "Kristjan") == 0)
set(smarty2, i, "Arumae");
else if (strcmp(get(smarty2, i), "Karan") == 0)
set(smarty2, i, "Daei-Mojdehi");
else if (strcmp(get(smarty2, i), "Shahidul") == 0)
set(smarty2, i, "Islam");
else if (strcmp(get(smarty2, i), "Fereshteh") == 0)
set(smarty2, i, "Jafariakinabad");
else if (strcmp(get(smarty2, i), "Pierre") == 0)
set(smarty2, i, "LaBorde");
else if (strcmp(get(smarty2, i), "Rachael") == 0)
set(smarty2, i, "Sera");
else if (strcmp(get(smarty2, i), "Richie") == 0)
set(smarty2, i, "Wales");
}
// Print the contents of smarty2.
printf(" -- SMART ARRAY 2 (Last Names): -- ");
printSmartArray(smarty2);
// Print smarty1 (in reverse order) and smarty2, to match up first and last
// names.
printf(" -- COMBINED ARRAYS (First and Last Names): -- ");
for (i = 0; i < getSize(smarty2); i++)
printf("%s %s ", get(smarty1, getSize(smarty1) - 1 - i), get(smarty2, i));
// Add elements from smarty1 to the end of smarty1 (in reverse order).
printf(" ");
for (i = getSize(smarty1) - 1; i >= 0; i--)
printf("Adding %s to smarty1 ... ", put(smarty1, get(smarty1, i)));
// Print the contents of smarty1.
printf(" -- SMART ARRAY 1: -- ");
printSmartArray(smarty1);
// Insert a string at the beginning of array smarty1.
insertElement(smarty1, 0, "List of Names:");
// Print the contents of smarty1.
printf(" -- SMART ARRAY 1: -- ");
printSmartArray(smarty1);
// Remove all elements from smarty1.
while (getSize(smarty1))
removeElement(smarty1, 0);
// Print smarty1, which is now an empty array.
printf(" -- SMART ARRAY 1: -- ");
printSmartArray(smarty1);
// Destroy our smart arrays.
smarty1 = destroySmartArray(smarty1);
smarty2 = destroySmartArray(smarty2);
// Make sure smarty1 is good and destroyed (and that destroySmartArray
// doesn't segfault when passed a NULL pointer).
smarty1 = destroySmartArray(smarty1);
// Print the empty arrays one last time.
printf(" -- SMART ARRAY 1: -- ");
printSmartArray(smarty1);
printf(" -- SMART ARRAY 2: -- ");
printSmartArray(smarty2);
return 0;
}
--------------------------------------------------------------------
names.txt
------------------------------
Karan
Kristjan
Shahidul
Rachael
Daniel
Fereshteh
Richie
Pierre
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.