Objective-C Programming_ The Big Nerd Ranch Guide - Aaron Hillegass [85]
return 0;
}
Build it and run it.
Notice that you don’t need to malloc and free memory for a string literal. It is a constant and appears in memory only once, so the compiler takes care of its memory use. As a side-effect of its constant-ness, bad things happen if you try to change the characters in the string. Add a line that should crash your program:
char *start = "Love";
start[2] = 'z';
printf("%s has %zu characters\n", start, strlen(start));
When you build and run it, you should get a EXC_BAD_ACCESS signal. You tried to write into memory that you are not allowed to write in.
To enable the compiler to warn you about writing to constant parts of memory, you can use the const modifier to specify that a pointer is referring to data that must not be changed. Try it:
const char *start = "Love";
start[2] = 'z';
printf("%s has %zu characters\n", start, strlen(start));
Now when you build, you should get an error from the compiler.
Delete the problematic line (start[2] = 'z';) before continuing.
You can use the escape sequences mentioned above in your string literals. Use a few:
const char *start = "A backslash after two newlines and a tab:\n\n\t\\";
printf("%s has %zu characters\n", start, strlen(start));
printf("The third letter is \'%c\'\n", start[2]);
return 0;
}
Build and run it.
Converting to and from NSString
If you are using C strings in an Objective-C program, you will need to know how to make an NSString from a C string. The NSString class has a method for this:
char *greeting = "Hello!";
NSString *x = [NSString stringWithCString:greeting encoding:NSUTF8StringEncoding];
You can also get a C string from an NSString. This is a little trickier because NSString can handle some characters that certain encodings cannot. It is a good idea to check that the conversion can occur:
NSString *greeting = "Hello!";
const char *x = NULL;
if ([greeting canBeConvertedToEncoding:NSUTF8StringEncoding]) {
x = [greeting cStringUsingEncoding:NSUTF8StringEncoding];
}
You do not own the resulting C string; the system will eventually free it for you. You are guaranteed that it will live at least as long as the current autorelease pool, but if you are going to need the C string to live for a long time, you should copy it into a buffer you’ve created with malloc().
Challenge
Write a function called spaceCount() that counts the space characters (ASCII 0x20) in a C string. Test it like this:
#include int main (int argc, const char * argv[]) { const char *sentence = "He was not in the cab at the time."; printf("\"%s\" has %d spaces\", sentence, spaceCount(sentence)); return 0; } Remember: when you run into '\0', you have reached the end of the string! 35 C Arrays Imagine that you wanted to write a program that would calculate the average of 3 grades. Create a new C Command Line Tool project and name it gradeInTheShade. Edit main.c: #include #include float averageFloats(float *data, int dataCount) { float sum = 0.0; for (int i = 0; i < dataCount; i++) { sum = sum + data[i]; } return sum / dataCount; } int main (int argc, const char * argv[]) { // Create an array of floats float *gradeBook = malloc(3 * sizeof(float)); gradeBook[0] = 60.2; gradeBook[1] = 94.5; gradeBook[2] = 81.1; // Calculate the average float average = averageFloats(gradeBook, 3); // Free the array free(gradeBook); gradeBook = NULL; printf("Average = %.2f\n", average); return 0; } Build and run it. Figure 35.1 Pointers on the stack to a buffer of floats malloc() allocates a buffer on the heap, so you need to make sure that you free it when you are
In the last chapter, we worked with C strings, and a C string turned out to be a list of characters packed one next to the other in memory. C arrays are lists of other data types packed one next to the other in memory. Just as with strings, you deal with the list by holding onto the address of the first one.