As you clearly know by now, C is not object-oriented and has no classes. Also, there is no string type (as a first-class type, anyway) in C, but there is a standard encoding which is an array of characters with a '\0', or NULL character marking the end of the string. Furthermore, the <string.h> library provides many string functions that operate on null-terminated arrays of char. The '\0' char (null character) is preferred to using NULL (which is a pointer value) although you might see NULL used synonymously for '\0' — please don't write code like that.
We first looked at the program
In the program, fname allocates 10 contiguous bytes (recall that sizeof(char) is one byte), each of which is uninitialized (has indeterminate value). The variable name, on the other hand, has 5 bytes allocated (remember that we need one "extra" byte for the '\0'), and they are initialized to 'M', 'a', 'r', 'k', and '\0' respectively. Lastly, the variable prof has 4 bytes allocated (sizeof a pointer is 4 bytes), and stores the address of the null-terminated string "Stehlik".
Thus
char name[] = "Mark";is equivalent to writing
char name[5] = { 'M', 'a', 'r', 'k', '\0' };
Let's look at strings to examine more details about strings, including some common string library functions from <string.h>. Be careful not to re-size this document too much in your browser because the embedded diagrams do not re-size with the text.
We then looked at the program
Pop Quiz #1: What does matrix[1,2] reference?
Let's look at 2-Dstrings to examine some more details of 2-D arrays of char. As before, be careful not to re-size this document too much in your browser because the embedded diagrams do not re-size with the text.
A simple application of 2-D character arrays (arrays of strings) might require us to read a dictionary into a fixed-size array from a text file.
Lastly, we looked at
In the call to loadDictionary(), note that when you pass an array, you provide the name without brackets (recall this is the starting address of the array in memory, the address of dictionary[0]). Of course, if you only wanted to pass a single row of the matrix to a function that receives a single string, you would use one subscript to select that row of the matrix. We also pass the name of the input file and address of wordCount.
Pop Quiz #2: Why do we pass the address of wordCount?
In the prototype of loadDictionary(), note that we declare only the second dimension (columns) in brackets and leave the first dimension (rows) unspecified. You could put both values in but the compiler would just ignore it anyway! It is just clearer to leave the first (rows) dimension out since it's not used.
Pop Quiz #3: Try to think like the compiler and deduce why it must have the column dimension in the prototype of an incoming 2-D array parameter.
Our read loop in loadDictionary() repeatedly calls fscanf() until either EOF is reached or the array is full (it's important to check this when reading into an array - remember, there are no ArrayOutOfBounds exceptions in C)! Note that we fscanf() our word into wordBuffer which is a 1-D string of the same dimension as each row in our 2-D array. After reading into wordBuffer, we then strcpy() the word into the next available row of the array. Make sure you run the program on both datafiles (10-words.txt and 105-words.txt) to see what happens.
NOTE: It was not necessary to use wordBuffer as intermediate storage in this case and then strcpy() it over. We could have just done this:
while ((fscanf(inFile, "%s", dictionary[*wordCount]) > 0) && (*wordCount < MAX_WORDS)) { (*wordCount)++; printf("%3d: %s\n", *wordCount, dictionary[*wordCount]); }
Even though we didn't need to use a separate buffer for this example, it will come in handy for Lab 2 where we're storing an array of dynamically allocated char *'s instead of an array of compile-time fixed-size arrays of char. Remember that the string library doesn't care whether your array of characters is allocated at compile-time or run-time.
Pop Quiz #4: What DOES the string library care about with respect to any string it is operating on?
Assume the name of the 2-D array is matrix. The compiler gets the address of the first element of the first row from the value of the name matrix because its name is the address of the first element. Then the compiler multiplies the column dimension specified in the prototype by the index given in the square brackets to calculate the offset from the beginning of the array. The sum of the two is the start address of the i'th row in the matrix. Thus, the expression matrix[i] produces the address of the i'th row.