C Language track

Lesson 08 · Level 2: Intermediate

Strings

String handling and standard library functions

Level 2: Intermediate4 min readFree lesson

There is no separate "string" data type in C. The string is a char array** terminated by '\0' (the null character). Length/Copy/Compare/Concatenate is handled using the standard functions of <string.h>.

Learning Objectives

  • Understand the null-terminated rules of C strings.
  • Use strlen, strcpy, strcat, and strcmp of <string.h>.
  • Receive one line safely with fgets.
  • Be aware of the risk of buffer overflow.

Why isn't "string" a separate type?

C was designed as a small and fast language, and strings are also expressed as simple char arrays. The null character ('\0') was introduced because a way to signal the end of an array was needed.

char s[] = "Hi";

is stored in memory as follows:

s[0] s[1] s[2]
┌────┬────┬─────┐
│ H │ i │ \0 │ ← '\0' indicates "This is the end!"
└────┴────┴─────┘

Why strlen("Hi") returns 2: Count the number of characters until '\0' is encountered.

Key concepts

1) String expression

char s1[] = "Hello";          // 6 byte ('H','e','l','l','o','\0')
char s2[10] = "Hi";           //The rest is filled with '\0'
char s3[] = {'H','i','\0'};   //Equivalent expression

2) Core functions of <string.h>

function Meaning Caution
strlen(s) Length (excluding null) s must not be NULL
strcpy(dst, src) Copy src to dst dst buffer must be sufficient
strcat(dst, src) Append src to the end of dst Requires space equal to combined length + 1
strcmp(a, b) Compare alphabetically If they are equal, it is 0, if a<b it is negative, if a>b it is positive

3) Enter one line as fgets

char buf[128];
fgets(buf, sizeof(buf), stdin);   //Includes line breaks
buf[strcspn(buf, "\n")] = '\0';   //Remove line breaks

scanf("%s", ...) breaks when it encounters a space, and does not check the input length, so there is a risk of buffer overflow.

4) Character unit processing (<ctype.h>)

function Description
isalpha(c) alphabet?
isdigit(c) number?
tolower(c) / toupper(c) Convert Small/capital-letters

See as example

Example 1 — ex01_basic.c: View length and character by character

Execution result

String: Hello, C!
Length: 9
s[0] = H (code 72)
s[1] = e (code 101)
s[2] = l (code 108)
s[3] = l (code 108)
s[4] = o (code 111)
s[5] = , (code 44)
s[6] = (code 32)
s[7] = C (code 67)
s[8] = ! (Code 33)

Bottom line: the string is ultimately an array of char integers, and the '\0' at the end is not included in the length.

Example 2 — ex02_strops.c: Copy/Concatenate/Compare

char a[64] = "Hello";
char b[]   = ", World!";
char c[64];
strcpy(c, a);
strcat(a, b);

Execution result

a = Hello, World!
c = Hello
strcmp("abc", "abd") = -1
strcmp("abc", "abc") = 0

Key point: strcat concatenates dst starting from the null position, so dst must be a valid string.

Example 3 — ex03_fgets.c: Safe Input

Input: hello c world

Enter a sentence: Input value: "hello c world"
Length: 13

Bottom line: fgets receives a buffer size so it doesn't overflow.

Example 4 — ex04_count.c : Vowel/Consonant count

Input: Hello World

Enter English sentences: Vowels: 3, Consonants: 7

Key point: If you compare after unifying the case with tolower, the branching will be reduced by half.

A different perspective — why string operations seem slow

Every time you call strlen, the compiler looks for '\0' from the beginning.

for (int i = 0; i < strlen(s); i++)   //Length recalculated at each iteration!

When performance is important, find the length only once.

size_t n = strlen(s);
for (size_t i = 0; i < n; i++) ...

The fact that C strings are endless arrays affects both efficiency and safety.

Common Mistakes

  1. Buffer Insufficient: char dst[3]; strcpy(dst, "Hello"); → Adjacent memory corruption.
  2. Missing null termination: If you just do char s[5]; s[0]='H'; s[1]='i';, you don't know where it ends → Garbage output.
  3. String comparison with ==: Compares two pointers, so even if the contents are the same, it is false. Must be strcmp.
  4. Line break remaining after fgets: \n remains at the end, so the output goes down one more line → is removed as strcspn.
  5. Constant string modification: char *p = "hi"; p[0] = 'H'; has undefined behavior. To fix char p[] = "hi";.

Cleanup

  • The C string is a char array ending with '\0'.
  • Length/Copy/Compare/Concatenate <string.h> function.
  • fgets is safer than scanf("%s").
  • For strcat/strcpy, the caller is responsible for whether the dst buffer is sufficient.
  • String comparison is strcmp, absolute ==.

Try it yourself

cd src
gcc -std=c11 -Wall -o ex01 ex01_basic.c   && ./ex01
gcc -std=c11 -Wall -o ex02 ex02_strops.c  && ./ex02
gcc -std=c11 -Wall -o ex03 ex03_fgets.c   && echo "hello c world" | ./ex03
gcc -std=c11 -Wall -o ex04 ex04_count.c   && echo "Hello World"   | ./ex04

Application:

  • Add one line from ex01 to s[2] = '\0'; and print it. Observe how the string breaks.
  • If you copy the c[] buffer in ex02 with a buffer that is too small (e.g. char c[3]), what kind of warning/error will appear?

Example files

The runnable files used in this lesson. Copy them into your own project and experiment.

src/ex01_basic.cC
#include <stdio.h>
#include <string.h>

int main(void) {
    char s[] = "Hello, C!";

    printf("String: %s\n", s);
    printf("Length: %zu\n", strlen(s));

    /*Print one character at a time*/
    for (size_t i = 0; s[i] != '\0'; i++) {
        printf("s[%zu] = %c (code %d)\n", i, s[i], s[i]);
    }
    return 0;
}
src/ex02_strops.cC
#include <stdio.h>
#include <string.h>

int main(void) {
    char a[64] = "Hello";
    char b[]   = ", World!";
    char c[64];

    strcpy(c, a);
    strcat(a, b);

    printf("a = %s\n", a);
    printf("c = %s\n", c);
    printf("strcmp(\"abc\", \"abd\") = %d\n", strcmp("abc", "abd"));
    printf("strcmp(\"abc\", \"abc\") = %d\n", strcmp("abc", "abc"));
    return 0;
}
src/ex03_fgets.cC
#include <stdio.h>
#include <string.h>

int main(void) {
    char line[128];

    printf("Enter sentence:");
    if (fgets(line, sizeof(line), stdin) == NULL) return 1;

    line[strcspn(line, "\n")] = '\0';   /*Remove \n at the end*/

    printf("Input value: \"%s\"\n", line);
    printf("Length: %zu\n", strlen(line));
    return 0;
}
src/ex04_count.cC
#include <stdio.h>
#include <ctype.h>
#include <string.h>

int main(void) {
    char buf[256];
    printf("Enter an English sentence:");
    if (fgets(buf, sizeof(buf), stdin) == NULL) return 1;
    buf[strcspn(buf, "\n")] = '\0';

    int vowels = 0, consonants = 0;
    for (size_t i = 0; buf[i] != '\0'; i++) {
        char ch = (char)tolower((unsigned char)buf[i]);
        if (ch >= 'a' && ch <= 'z') {
            if (ch == 'a' || ch == 'e' || ch == 'i' ||
                ch == 'o' || ch == 'u')
                vowels++;
            else
                consonants++;
        }
    }

    printf("Vowel: %d, Consonant: %d\n", vowels, consonants);
    return 0;
}

Assignment

Problem 1

Input an English string and convert it to all uppercase and print it. (Using toupper of <ctype.h>)

  • File name: hw01.c

Problem 2

Input a string and determine if it is a palindrome. Without case sensitivity.

Input: Level
It's a palindrome.
  • File name: hw02.c

Problem 3

Print the number of occurrences of a specific character (char) in a string.

Sentence: hello world
Character to look for: l
'l' appears 3 times.
  • File name: hw03.c
Show the reference solution

Try the assignment yourself first — comparing your attempt with a working solution is where most of the learning happens.

hw01.cC
#include <stdio.h>
#include <ctype.h>
#include <string.h>

int main(void) {
    char buf[256];
    printf("Enter sentence:");
    if (fgets(buf, sizeof(buf), stdin) == NULL) return 1;
    buf[strcspn(buf, "\n")] = '\0';

    for (size_t i = 0; buf[i] != '\0'; i++)
        buf[i] = (char)toupper((unsigned char)buf[i]);

    printf("%s\n", buf);
    return 0;
}
hw02.cC
#include <stdio.h>
#include <ctype.h>
#include <string.h>

int main(void) {
    char buf[256];
    printf("Enter sentence:");
    if (fgets(buf, sizeof(buf), stdin) == NULL) return 1;
    buf[strcspn(buf, "\n")] = '\0';

    int len = (int)strlen(buf);
    int palindrome = 1;
    for (int i = 0, j = len - 1; i < j; i++, j--) {
        char a = (char)tolower((unsigned char)buf[i]);
        char b = (char)tolower((unsigned char)buf[j]);
        if (a != b) { palindrome = 0; break; }
    }

    printf("%s\n", palindrome ? "It's a palindrome." : "It's not a palindrome.");
    return 0;
}
hw03.cC
#include <stdio.h>
#include <string.h>

int main(void) {
    char buf[256];
    char target;

    printf("Sentence:");
    if (fgets(buf, sizeof(buf), stdin) == NULL) return 1;
    buf[strcspn(buf, "\n")] = '\0';

    printf("Characters to look for:");
    scanf(" %c", &target);

    int count = 0;
    for (size_t i = 0; buf[i] != '\0'; i++)
        if (buf[i] == target) count++;

    printf("'%c' appears %d times.\n", target, count);
    return 0;
}

Learn this lesson with a mentor

Work through the C Language track on your own, or join a guided cohort at our Pitampura campus and online.

Call NowEnroll Now