Strings
C has no special "string type". A piece of text is kept in a char array and printed with %s:
1#include <stdio.h>2 3int main(void) {4 char city[] = "Paris";5 char greeting[20] = "Good morning";6 printf("%s, %s!\n", greeting, city);7 return 0;8}
Good morning, Paris!
char city[] = "Paris"; lets the compiler size the array to fit the string; greeting[20] sets aside 20 bytes and uses only the first part. %s in printf prints from the start of the array, one character at a time, until it reaches the end of the string. Where is the end? That comes next.
A string is a char array
"cat" looks like 3 characters, but it takes 4 bytes: at the end there is a '\0', a character whose value is 0, meaning "the string stops here". These two lines make exactly the same array:
1#include <stdio.h>2 3int main(void) {4 char a[] = {'c', 'a', 't', '\0'};5 char b[] = "cat";6 printf("%s %s\n", a, b);7 printf("%zu %zu\n", sizeof a, sizeof b);8 printf("%c\n", b[1]);9 return 0;10}
cat cat 4 4 a
Single quotes, 'c', make one character; double quotes, "cat", make a string. They are not the same thing. Press Step and see b drawn as 4 cells, the last one holding '\0'.
What does this print?
1#include <stdio.h>2 3int main(void) {4 char word[] = "hello";5 printf("%zu\n", sizeof word);6 return 0;7}
hello has 5 letters, plus the '\0' at the end: 6 bytes. The array always needs one more byte than the text.
The '\0' at the end
'\0' is the only thing that marks how long a string is. To find how many characters a string has, count from the start until you reach '\0':
1#include <stdio.h>2 3int main(void) {4 char name[] = "Alexandra";5 int len = 0;6 while (name[len] != '\0') {7 len++;8 }9 printf("%s has %d letters\n", name, len);10 return 0;11}
Alexandra has 9 letters
%s works the same way: it stops at '\0'. So if you put a '\0' in the middle, the rest isn't printed, even though it is still in the array:
1#include <stdio.h>2 3int main(void) {4 char word[] = "sunflower";5 word[3] = '\0';6 printf("%s\n", word);7 printf("%c\n", word[4]);8 return 0;9}
sun l
Characters are numbers
Inside the computer, every character is a small whole number called its code. English letters, digits and common symbols use the ASCII codes: 'A' is 65, 'a' is 97, '0' is 48. The same char prints as a character with %c and as a number with %d:
1#include <stdio.h>2 3int main(void) {4 char c = 'A';5 printf("%c %d\n", c, c);6 printf("%c\n", c + 2);7 printf("%d\n", 'a' - 'A');8 printf("%d\n", '7' - '0');9 return 0;10}
A 65 C 32 7
| Characters | Codes |
|---|---|
'0' to '9' | 48 to 57 |
'A' to 'Z' | 65 to 90 |
'a' to 'z' | 97 to 122 |
'\0' | 0 |
The letters come in order, so 'A' + 2 is 'C'; a lowercase letter is 32 more than its uppercase one; and '7' - '0' turns the character '7' into the number 7.
Letters outside English, like é or ß, don't fit in one char. The web and most systems use UTF-8, where such a letter takes 2 or more bytes. Printing a whole string is fine, but looking at it byte by byte gets confusing, so the examples here that count characters use plain English text.
Character by character
Loop from index 0 up to '\0' and you can check each character. For example, count the spaces: one more than the number of spaces is the number of words.
1#include <stdio.h>2 3int main(void) {4 char text[] = "the quick brown fox";5 int spaces = 0;6 for (int i = 0; text[i] != '\0'; i++) {7 if (text[i] == ' ') {8 spaces++;9 }10 }11 printf("%d words\n", spaces + 1);12 return 0;13}
4 words
You can change the characters in the array too. Swap each space for an underscore:
1#include <stdio.h>2 3int main(void) {4 char file[] = "my summer photos.jpg";5 for (int i = 0; file[i] != '\0'; i++) {6 if (file[i] == ' ') {7 file[i] = '_';8 }9 }10 printf("%s\n", file);11 return 0;12}
my_summer_photos.jpg
Press Step and watch the cells of the array change one by one.
When the array is too small
To hold a string, an array needs at least one byte more than the text, for the '\0'. Below, "hello" is copied letter by letter into word, which has only 4 bytes. The first 4 fit; the fifth goes out of bounds:
1#include <stdio.h>2 3int main(void) {4 char text[] = "hello";5 char word[4];6 for (int i = 0; text[i] != '\0'; i++) {7 word[i] = text[i];8 }9 printf("Copied\n");10 return 0;11}
index 4 out of bounds for type 'char [4]'What happened: Stopped at line 7. This goes past the end of an array (or a string). Real C would read or overwrite whatever is next in memory.
Real C won't stop you: the extra bytes land on top of some other variable, and the program may carry on and only act strangely later. Our engine stops on the line where it goes out of bounds. Press "see how it went wrong", or press Step and watch what happens when i reaches 4.
Tip: Write char a[] = "..." with no size and let the compiler count. Then you can't forget the '\0'.
Practice
Write the code, then press Check. A hint costs nothing; the answer is there when you need it.
Count a letter
✓Count how many times a appears in word, and print a appears 3 times.
a appears 3 times
1#include <stdio.h>2 3int main(void) {4 char word[] = "banana";5 6 return 0;7}
Backwards
✓Print word backwards: olleh, then a new line.
olleh
1#include <stdio.h>2 3int main(void) {4 char word[] = "hello";5 6 return 0;7}
All caps
✓Turn every lowercase letter in text into uppercase, leave the other characters alone, then print HELLO, WORLD 2.
HELLO, WORLD 2
1#include <stdio.h>2 3int main(void) {4 char text[] = "Hello, World 2";5 6 return 0;7}
What you learned
- A string is a
chararray with a'\0'at the end:"cat"takes 4 bytes. 'c'is one character and"cat"is a string;%cprints a character,%sa string.%sand your loops both use'\0'to know where to stop:for (int i = 0; s[i] != '\0'; i++).- Characters are numbers:
'A'is 65,'a' - 'A'is 32,'7' - '0'is 7. Letters outside English take more than one byte in UTF-8. - The array needs one extra byte for the
'\0'; if the text doesn't fit, you go out of bounds.