</>CodexBash
C
CBeginner12 min

Input, output and strings

Reading numbers and words with scanf, strings as character arrays ending in a null byte, the string.h functions, and the safe way to read a line.

Indexing and slicing a stringstep 1/5
p
0
y
1
t
2
h
3
o
4
n
5
s = pythonlen = 6
Each character has a position, starting at 0. A string of length 6 has positions 0 to 5.

Reading numbers with scanf#

scanf reads from the keyboard using the same placeholders as printf, with one difference: you pass the address of each variable, written with &:

int a, b;
scanf("%d %d", &a, &b);
printf("%d\n", a + b);

&a means "where a lives in memory". scanf needs that to put the value there. Forgetting the & is a classic crash.

For long long use %lld, and for double use %lf (with scanf; printf uses %f for doubles).

scanf returns how many values it read, which lets you read until the input runs out:

int x;
long long total = 0;
while (scanf("%d", &x) == 1) {
    total += x;
}

Strings are character arrays#

C has no string type. A string is an array of char ending in a special character, '\0', called the null terminator, that marks the end:

char name[] = "Asha";
// stored as: 'A' 's' 'h' 'a' '\0'   -- five bytes, not four

Everything about C strings follows from this. Their length is found by walking to the '\0', and an array must have room for it.

char word[6] = "hello";   // 5 letters + '\0' = 6: fits exactly
char tiny[5] = "hello";   // no room for '\0': not a proper string

Reading a word#

char word[100];
scanf("%99s", word);      // no &: an array name is already an address

%s stops at the first space. The 99 limits how much is read, leaving room for the '\0' in an array of 100, so long input cannot overflow it.

Reading a whole line#

fgets reads a line including spaces, and never more than you allow:

char line[200];
fgets(line, sizeof line, stdin);
line[strcspn(line, "\n")] = '\0';   // remove the newline fgets keeps

Never use gets. It has no size limit and was removed from the language because of it.

string.h#

#include <string.h>

strlen("hello")            // 5: counts up to '\0'
strcpy(dest, src)          // copy src into dest (dest must be big enough)
strcat(dest, src)          // append src to dest
strcmp(a, b)               // 0 if equal, negative or positive otherwise
strchr(s, 'x')             // pointer to the first 'x', or NULL

Two rules that catch everyone:

  • Compare strings with strcmp, never ==. a == b compares addresses, so two strings with the same letters are "not equal".
  • strlen walks the whole string every time. Do not put it in a loop condition; call it once.
int n = strlen(s);
for (int i = 0; i < n; i++) { ... }

Walking a string#

Loop until the terminator, or to the length:

int vowels = 0;
for (int i = 0; s[i] != '\0'; i++) {
    char c = tolower(s[i]);            // <ctype.h>
    if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
        vowels++;
    }
}

<ctype.h> has isalpha, isdigit, isalnum, isspace, tolower and toupper.

Key points#

  • scanf needs & before each number variable; %lf reads a double.
  • A string is a char array ending in '\0', which needs a byte of its own.
  • Limit what %s reads (%99s), and read lines with fgets, never gets.
  • Compare with strcmp, not ==; call strlen once, not in a loop.

Next: making decisions with if and switch.

Practise it

The same idea, in the order it is worth meeting it.

  1. Not startedIs it a palindromeEasy
Create a free account to track your progress