Strings are actually quite similar to pointers in C. Let me try to explain how this code works, where "Line 1" is the first line of main. You may want to copy the code into Programmer's Notepad, Notepad++, or some other text editor with line numbers to follow along. I'll skip the ones that aren't relevant to the main point.
Line 1: buffer is created, and it is an array (i.e. a list) of 128 (BUFFER_LEN) characters. 128 bytes of memory has been allocated.
Line 2: pS is created, and it's a array of 100 (NUM_P) null pointers. It is defined as a char, designating that once the pointers have actual values, they will point to either a single character, or an array of characters (so a string). This is where we first see a string behaving like a pointer. When we assign "buffer" to pbuffer, we're actually assigning the address of buffer. It works the same way as:
Code:
int var = 5;
int *ptr = &var; // Calling *ptr later will return 5
Line 3: pbuffer is created and points to the first character of buffer. We'll be manipulating that later to point to individual characters in buffer.
Line 9: The for loop is going to run through the array of pointers (pS) that was created in line 2. As long as break is never hit, then every pointer in the pS array will be assigned a value.
Line 11: This is just resetting pbuffer, since it will be changing during this for loop.
Line 16: pbuffer and buffer are both the same address right now, so it translates to (0 < BUFFER_LEN-1)
Line 17: pbuffer is incremented, and whatever character you typed is stored to its target. If the key was Enter, then the loop is broken.
Line 33: pbuffer-buffer equals the total number of characters, therefore the length of the string. That amount of memory needs to be reserved so that it doesn't get overwritten.
I should note that this is all called pointer arithmetic, and it is frowned on by some. I usually don't use it because it can yield unexpected results if you do anything wrong. For example, in this case I would have just created an array of strings. It's less efficient memory-wise, but much simpler.
Code:
/* Program 7.13 Generalizing string input */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const size_t MESSAGE_LEN = 128; /* maximum length of each message */
const size_t NUM_P = 100; /* maximum number of strings */
int main(void)
{
char ListOfStrings[NUM_P][MESSAGE_LEN] = {{0}}; // Creates 100 strings that are 128 characters long, then fills them with null characters
int i = 0; /* Loop counter */
int num = 0; // Character number in array
printf("\nYou can enter up to %u messages each up to %u characters.", NUM_P, MESSAGE_LEN-1);
for(i = 0 ; i<NUM_P ; i++) {
num = 0;
printf("\nEnter %s message, or press Enter to end\n", i>0? "another" : "a");
while ((num < MESSAGE_LEN-1) && ListOfStrings[i][num] != '\n') {
ListOfStrings[i][num] = (char)getchar();
num++;
};
if (num == 1) break; // Only one key was entered before the while loop closed, which means it was Enter
}
/* Output all the strings */
printf("\nIn reverse order, the strings you entered are:\n");
while(--i >= 0)
printf("\n%s", ListOfStrings[i]); /* Display strings last to first */
return 0;
}
In the above, 12800 bytes are always allocated, even if you only type one character, where as the original version only uses what memory is necessary. However, 13KB is an insignificant amount of RAM on computers today, so as long as it isn't something big, you can get by with wasting a tiny bit of space.