C++ String strcspn() Function

Beginner
⏱️ 10 min read
📚 Updated: Jul 2026
🎯 5 Examples
Parsing / scanning

What You’ll Learn

The strcspn() function measures how many characters appear at the start of a C-string before any character from a reject set shows up. The name means complement span—span of characters not in the set. It is handy for splitting tokens, skipping to delimiters, and lightweight parsing without building a full parser.

01

Prefix Length

Count from start.

02

Reject Set

Chars in str2.

03

size_t Return

Character count.

04

vs strspn()

Accept vs reject.

05

Delimiters

Commas, spaces, @.

06

<cstring>

C library function.

Definition and Usage

In C++, strcspn() is declared in <cstring>. It walks str1 from left to right and stops at the first character that matches any character stored in str2. The return value is the number of characters scanned before that stop—not including the stopping character itself.

Think of str2 as a bag of forbidden characters, not a phrase to find. Passing "aeiou" stops at the first vowel. Passing ",;" stops at the first comma or semicolon. Order and duplicates in str2 do not change the result.

💡
Beginner Tip

If strcspn(text, " ") returns 5, the first word is five characters long and the space (if any) starts at index 5. You can copy that prefix with strncpy or slice a std::string using the same index.

📝 Syntax

Function signature and a typical call:

C++
#include <cstring>

size_t strcspn(const char* str1, const char* str2);

// Example:
size_t n = strcspn("C++ Programming", "aeiou");
// n == 6  (prefix "C++ Pr" has no vowels)

Parameters

  • str1 — the C-string to scan (must be null-terminated).
  • str2 — a set of characters; scanning stops when any of them is found in str1.

Return Value

Returns the length of the initial segment of str1 that contains no characters from str2. If every character of str1 is allowed, the return value equals strlen(str1).

⚡ Quick Reference

FunctionStops when…Counts…
strcspn()Char is in reject setPrefix without those chars
strspn()Char is not in accept setPrefix of only those chars
strchr()Specific char foundPointer to first match
strpbrk()Any char from set foundPointer to first match
Scan
strcspn(s, set)

Prefix length

Vowels
strcspn(s, "aeiou")

Until first vowel

Word
strcspn(s, " \t")

Until whitespace

Include
#include <cstring>

Header file

Examples Gallery

Compile with g++ strcspn.cpp -std=c++17 -o strcspn. Each example prints the span length and explains what stopped the scan.

📚 Getting Started

Count characters until the first member of a reject set appears.

Example 1 — Prefix Without Vowels

Find how many leading characters of "C++ Programming" contain no vowels.

C++
#include <iostream>
#include <cstring>

int main() {
    const char* text = "C++ Programming";

    std::size_t length = std::strcspn(text, "aeiou");

    std::cout << "Prefix length (no vowels): " << length << "\n";
    std::cout << "Prefix text: ";
    for (std::size_t i = 0; i < length; ++i) {
        std::cout << text[i];
    }
    std::cout << "\n";

    return 0;
}

How It Works

Scanning stops at 'o' in "Programming" (index 6). Characters C + + space P r contain no vowels, so the count is 6.

Example 2 — Length of the First Word

Use whitespace as the reject set to measure the first word in a sentence.

C++
#include <iostream>
#include <cstring>

int main() {
    const char* sentence = "Hello, C++ world!";

    std::size_t wordLen = std::strcspn(sentence, " \t\n");

    std::cout << "First word length: " << wordLen << "\n";
    std::cout << "First word: ";
    for (std::size_t i = 0; i < wordLen; ++i) {
        std::cout << sentence[i];
    }
    std::cout << "\n";

    return 0;
}

How It Works

The scan stops at the space after "Hello,". Punctuation is not in the reject set, so it stays part of the prefix. Add punctuation to str2 if you need letters only.

📈 Practical Patterns

Parsing emails, comparing with strspn, and reading CSV fields.

Example 3 — Username Before @

Extract the local part of an email address by stopping at @.

C++
#include <iostream>
#include <cstring>

int main() {
    const char* email = "learner@codetofun.com";

    std::size_t atPos = std::strcspn(email, "@");

    std::cout << "Username length: " << atPos << "\n";
    std::cout << "Username: ";
    for (std::size_t i = 0; i < atPos; ++i) {
        std::cout << email[i];
    }
    std::cout << "\n";

    if (email[atPos] == '@') {
        std::cout << "Domain starts at: " << (email + atPos + 1) << "\n";
    }

    return 0;
}

How It Works

strcspn returns the index of @ when it is the first reject character encountered. Pointer arithmetic email + atPos + 1 skips past the delimiter to the domain.

Example 4 — strcspn() vs strspn()

See complementary behavior on the same string and character set.

C++
#include <iostream>
#include <cstring>

int main() {
    const char* line = "   trim me";
    const char* spaces = " \t";

    std::size_t leadingSpaces = std::strspn(line, spaces);
    std::size_t tokenLen = std::strcspn(line + leadingSpaces, spaces);

    std::cout << "Leading spaces: " << leadingSpaces << "\n";
    std::cout << "Token length:     " << tokenLen << "\n";
    std::cout << "Token: ";
    for (std::size_t i = 0; i < tokenLen; ++i) {
        std::cout << line[leadingSpaces + i];
    }
    std::cout << "\n";

    return 0;
}

How It Works

strspn counts leading spaces (accept set). Then strcspn on the remainder counts characters until the next space (reject set). Together they implement a simple trim-and-tokenize pattern.

Example 5 — First CSV Field

Read characters until a comma or newline delimiter.

C++
#include <iostream>
#include <cstring>

int main() {
    const char* row = "C++,Java,Python";

    std::size_t fieldLen = std::strcspn(row, ",\n");

    std::cout << "Field 1 length: " << fieldLen << "\n";
    std::cout << "Field 1: ";
    for (std::size_t i = 0; i < fieldLen; ++i) {
        std::cout << row[i];
    }
    std::cout << "\n";

    const char* rest = row + fieldLen;
    if (*rest == ',') {
        ++rest;
        std::size_t field2Len = std::strcspn(rest, ",\n");
        std::cout << "Field 2: ";
        for (std::size_t i = 0; i < field2Len; ++i) {
            std::cout << rest[i];
        }
        std::cout << "\n";
    }

    return 0;
}

How It Works

Each call finds one field length. Advancing the pointer past the delimiter and calling strcspn again parses the next column—a minimal hand-rolled CSV reader.

🚀 Common Use Cases

  • Tokenizing input — split on spaces, tabs, or custom delimiters.
  • CSV / config parsing — read fields separated by commas or equals signs.
  • Validating prefixes — measure an identifier before the first illegal symbol.
  • Path or URL segments — stop at /, ?, or @.
  • Pairing with strspn() — skip padding, then read the meaningful token.

🧠 How strcspn() Works

1

Start at str1[0]

Initialize counter to zero and read the first character of str1.

Start
2

Check reject set

Search str2 for the current character. If found, stop immediately.

Test
3

Advance and count

If not in the set, increment counter and move to the next character until '\0'.

Loop
#

Return count

The final counter is the complement span length—a size_t with no pointer returned.

📝 Notes

  • The return value is a length, not an index of the stopping character (though they coincide when a stop character exists).
  • If no character from str2 appears in str1, the result is strlen(str1).
  • str2 is a character set, not a substring pattern—do not confuse with strstr.
  • Both arguments must be valid null-terminated C-strings.
  • For complex parsing, consider std::string, streams, or a regular-expression library.

⚡ Optimization

Standard libraries implement strcspn() efficiently, often with lookup tables for ASCII sets. For repeated scans on huge buffers, profile your code. In modern C++, a single pass with iterators or std::string::find_first_of may be clearer while offering similar performance for typical input sizes.

Conclusion

strcspn() answers one focused question: how long is the prefix of str1 before any character from str2 shows up? Use it for delimiters, reject sets, and quick C-string tokenization alongside strspn().

Next, learn strerror() to turn system error numbers into readable messages—essential when file and network calls fail.

💡 Best Practices

✅ Do

  • Treat str2 as a set of delimiter characters
  • Combine with strspn to skip padding then read tokens
  • Check whether a delimiter exists after the span (e.g., s[n] == ',')
  • Use meaningful reject sets: " \t\n", ",;", "@"
  • Prefer std::string views when building larger parsers

❌ Don’t

  • Expect str2 to match as a whole substring
  • Assume the return value points into the string—it is a count
  • Forget that punctuation stays in the prefix unless listed in str2
  • Call on non-null-terminated buffers
  • Build a full CSV/JSON parser from strcspn alone without edge-case tests

Key Takeaways

Knowledge Unlocked

Five things to remember about strcspn()

Use these points when scanning C-string prefixes.

5
Core concepts
🚫 02

Reject Set

Chars in str2.

Input
🔄 03

vs strspn

Complement ops.

Compare
04

Delimiters

Split tokens.

Parse
📝 05

size_t

Length, not pointer.

Return

❓ Frequently Asked Questions

strcspn() scans str1 from the start and counts characters until it hits any character that also appears in str2 (the reject set). It returns that count—the length of the initial segment of str1 that contains none of the characters listed in str2.
size_t strcspn(const char* str1, const char* str2); Include <cstring>. str1 is the string to scan; str2 is a set of characters to stop on (not a substring to match).
A size_t count of characters in the prefix of str1 before the first character from str2. If no character from str2 appears in str1, it returns the length of str1. If str1 is empty, it returns 0.
strspn() counts how many initial characters of str1 are all members of the accept set in str2. strcspn() counts initial characters that are NOT in str2—they are complementary operations. strspn stops at the first character not in the set; strcspn stops at the first character in the set.
str2 is treated as a set of individual characters, not a substring. Passing "aeiou" means stop on any vowel. The order of characters in str2 does not matter, and duplicates in str2 have no extra effect.
No. It comes from the C standard library via <cstring> (same family as strcpy and strcmp). Modern C++ code may use std::string methods or std::find_first_of, but strcspn() is still useful for lightweight C-string parsing.
Did you know?

The sibling function strpbrk() returns a pointer to the first matching character, while strcspn() returns how many characters came before that match. If you need the address, use strpbrk; if you only need the length, strcspn is enough.

Continue the String Functions Series

Parse prefixes with strcspn(), then decode system errors with strerror().

Next: strerror() →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful