String Basics

A C string is like a necklace ending with a transparent bead -- each bead is a character, and the last one is the invisible terminator \0 that signals "the necklace ends here".

Character Arrays and Strings

C has no dedicated string type. A string is essentially a character array terminated by \0 (the null character). The ASCII value of \0 is 0, and it marks the end of the string.

C
char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'};

This array has 6 elements: 5 visible characters plus 1 \0. Without \0, it is just an ordinary character array and cannot be used as a string.

String literals (double quotes) automatically append \0 at the end:

C
char str[] = "Hello";

The array length is 6 (5 characters + 1 \0); the compiler calculates it automatically. You can also specify a larger length; the extra positions are filled with \0:

C
char str[10] = "Hello";

str[5] through str[9] are all \0.

💡 Tip: Single quotes 'H' denote a character (1 byte); double quotes "Hello" denote a string (with an implicit \0). They are not the same.

String Declaration and Initialization

Character Array Style

C
char s1[] = "abc";
char s2[10] = "abc";
char s3[] = {'a', 'b', 'c', '\0'};

All three are equivalent to the string "abc". Note that s3 requires a manually added \0.

Character Pointer Style

C
const char *s4 = "abc";

s4 points to the first character of a string literal. String literals are stored in a read-only region; attempting to modify them is undefined behavior:

C
s4[0] = 'A';

This is wrong. Character arrays, however, are modifiable:

C
s1[0] = 'A';

Legal -- the contents of s1 become "Abc".

⚠️ Note: Use const when pointing a pointer at a string literal; the compiler will warn you if you try to modify it.

Pointers vs Arrays

C
char arr[] = "hello";
const char *ptr = "hello";

String Input and Output

printf and scanf

Use the %s format specifier for string input and output:

C
char name[20];
scanf("%s", name);
printf("Hello, %s!\n", name);

scanf stops reading at whitespace (space, newline, tab), so it cannot read an entire line containing spaces.

scanf does not check the buffer size; input exceeding the array length causes an overflow. You can limit the read length:

C
scanf("%19s", name);

This reads at most 19 characters, leaving 1 position for \0.

puts and gets

puts outputs a string and automatically appends a newline:

C
char msg[] = "Hello";
puts(msg);

This is equivalent to printf("%s\n", msg);.

gets reads an entire line (including spaces) until a newline:

C
char line[100];
gets(line);
🔥 Common Mistake: Never use gets! It does not check the buffer size -- if input exceeds the array capacity, it writes out of bounds. It is one of the most dangerous C functions and was completely removed in C11.

fgets

fgets is the safe replacement for gets:

C
char line[100];
fgets(line, sizeof(line), stdin);

The parameters are: the storage buffer, the maximum number of bytes to read (including \0), and the input stream. fgets retains the newline at the end of the string (if a newline was read and there is still space).

Common pattern for removing the trailing newline:

C
#include <stdio.h>
#include <string.h>

int main(void) {
    char line[100];
    fgets(line, sizeof(line), stdin);

    int len = strlen(line);
    if (len > 0 && line[len - 1] == '\n') {
        line[len - 1] = '\0';
    }

    printf("[%s]\n", line);
    return 0;
}

Example

Read the user's name and a line of self-introduction:

C
#include <stdio.h>
#include <string.h>

void trim_newline(char *s) {
    int len = strlen(s);
    if (len > 0 && s[len - 1] == '\n') {
        s[len - 1] = '\0';
    }
}

int main(void) {
    char name[30];
    char intro[200];

    printf("Enter your name: ");
    fgets(name, sizeof(name), stdin);
    trim_newline(name);

    printf("Introduce yourself: ");
    fgets(intro, sizeof(intro), stdin);
    trim_newline(intro);

    printf("\n--- Personal Info ---\n");
    printf("Name: %s\n", name);
    printf("Intro: %s\n", intro);

    return 0;
}
▶ Try it Yourself
TEXT
Enter your name: Alice
Introduce yourself: I am a C beginner

--- Personal Info ---
Name: Alice
Intro: I am a C beginner

The strlen Function

strlen is declared in <string.h> and returns the length of the string (not including \0):

C
#include <string.h>

char s[] = "Hello";
printf("%zu\n", strlen(s));

Output: 5. Note that sizeof(s) is 6 (including \0), while strlen(s) is 5 (excluding \0).

How strlen works: it counts characters from the beginning until it encounters \0:

C
size_t my_strlen(const char *s) {
    size_t len = 0;
    while (s[len] != '\0') {
        len++;
    }
    return len;
}

If a character array does not end with \0, strlen will keep reading until it happens to encounter a zero byte, which is very dangerous.

Introduction to Character Pointers

A character pointer can point to either a character array or a string literal:

C
char arr[] = "world";
const char *ptr = "world";

ptr = arr;
printf("%s\n", ptr);

A pointer can be reassigned to point to a different string, but an array name is a constant and cannot be modified:

C
ptr = "another string";

Legal. But:

C
arr = "another string";

Illegal -- an array name cannot be assigned.

Traversing a string with a pointer:

C
const char *p = "Hello";
while (*p != '\0') {
    printf("%c", *p);
    p++;
}
printf("\n");

*p dereferences to get the current character; p++ moves to the next character position. The pointer stride is determined by the pointed-to type; char * moves 1 byte per step.

Example

Print a string in reverse using a character pointer:

C
#include <stdio.h>
#include <string.h>

void print_reverse(const char *s) {
    const char *p = s + strlen(s) - 1;
    while (p >= s) {
        putchar(*p);
        p--;
    }
    putchar('\n');
}

int main(void) {
    print_reverse("Hello");
    print_reverse("ABCDEF");
    return 0;
}
▶ Try it Yourself
TEXT
olleH
FEDCBA

First, move the pointer p to the last character of the string (one position before \0), then output characters from back to front.

❓ FAQ

Q What is the difference between 'a' and "a"?
A 'a' is a character constant occupying 1 byte; "a" is a string constant occupying 2 bytes ('a' plus '\0'), and its type is char[].
Q Why do sizeof and strlen give different results for strings?
A sizeof returns the total memory occupied by the array (including \0); strlen returns the number of characters before \0.
Q What happens when fgets reads a newline?
A fgets stores the newline in the buffer. You typically need to manually check for it and replace it with \0 to remove it.
Q Can I modify the contents of a string literal through a character pointer?
A No. String literals are stored in a read-only segment; modification is undefined behavior. Use a character array if you need to modify the contents.

📖 Summary

📝 Exercises

  1. Write a program that uses fgets to read a line of text and counts the number of letters, digits, and other characters.
  2. Write a function void str_replace_char(char *s, char old, char new_ch) that replaces all occurrences of old in string s with new_ch.
  3. Write a function that calculates the length of a string using character pointers, without using strlen.
100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏