Kodewick
Lesson 13 of 30Contents

Strings

Lesson 13 of 30 · Part 2 · Functions and arrays · about 15 minutes

C has no special "string type". A piece of text is kept in a char array and printed with %s:

main.c
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}
Output
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:

main.c
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}
Output
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'.

Guess first

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}

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':

main.c
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}
Output
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:

main.c
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}
Output
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:

main.c
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}
Output
A 65
C
32
7
CharactersCodes
'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.

main.c
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}
Output
4 words

You can change the characters in the array too. Swap each space for an underscore:

main.c
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}
Output
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:

main.c
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}
Output
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.

Exercise 1

Count a letter

Count how many times a appears in word, and print a appears 3 times.

It should print
a appears 3 times
exercise1.c
1#include <stdio.h>2 3int main(void) {4    char word[] = "banana";5 6    return 0;7}
Output
Press Run or Ctrl+Enter
Exercise 2

Backwards

Print word backwards: olleh, then a new line.

It should print
olleh
exercise2.c
1#include <stdio.h>2 3int main(void) {4    char word[] = "hello";5 6    return 0;7}
Output
Press Run or Ctrl+Enter
Exercise 3

All caps

Turn every lowercase letter in text into uppercase, leave the other characters alone, then print HELLO, WORLD 2.

It should print
HELLO, WORLD 2
exercise3.c
1#include <stdio.h>2 3int main(void) {4    char text[] = "Hello, World 2";5 6    return 0;7}
Output
Press Run or Ctrl+Enter

What you learned

  • A string is a char array with a '\0' at the end: "cat" takes 4 bytes.
  • 'c' is one character and "cat" is a string; %c prints a character, %s a string.
  • %s and 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.