ZetCode

C strspn 函数

最后修改:2025 年 4 月 8 日

字符串操作在 C 编程中至关重要,而 strspn 是分析字符串内容的关​​键函数。本教程将深入介绍 strspn,包括其语法、用法和实际应用。我们将通过示例探讨如何验证输入和解析字符串。理解 strspn 有助于在保持程序安全性和可靠性的同时,创建健壮的字符串处理功能。

什么是 strspn?

strspn 函数计算字符串的初始段的长度,该段完全由另一个字符串中的字符组成。它在 string.h 中声明,并接受两个参数:要检查的字符串和可接受字符的集合。strspn 返回字符串开头匹配字符的数量。为了安全起见,在处理之前务必验证输入,以防止缓冲区溢出。

strspn 的基本用法

此示例演示了 strspn 的基本用法,用于查找数字。

basic_span.c
#include <stdio.h>
#include <string.h>

int main() {
    const char *str = "12345abc";
    const char *digits = "0123456789";
    
    size_t span = strspn(str, digits);

    printf("String: %s\n", str);
    printf("Initial digit span: %zu\n", span);

    return 0;
}

在此,strspn 扫描 str 并计算开头的多少个字符与 digits 中的字符匹配。它返回 5,因为“12345”都是数字。该函数在遇到不在数字集中的“a”时停止。这对于验证字符串格式或提取数字前缀非常有用。%zu 格式说明符可正确打印 size_t 返回值。

使用 strspn 验证输入

strspn 可以验证字符串是否只包含允许的字符。

input_validation.c
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

bool is_valid_hex(const char *str) {
    const char *hex_chars = "0123456789ABCDEFabcdef";
    return strspn(str, hex_chars) == strlen(str);
}

int main() {
    const char *test1 = "1A3F9C";
    const char *test2 = "1G5H9Z";

    printf("%s is %s\n", test1, is_valid_hex(test1) ? "valid" : "invalid");
    printf("%s is %s\n", test2, is_valid_hex(test2) ? "valid" : "invalid");

    return 0;
}

此示例检查字符串是否只包含十六进制字符。is_valid_hex 函数在整个字符串由十六进制数字组成时返回 true。strspn 扫描字符串,直到找到一个非十六进制字符。通过将跨度长度与字符串长度进行比较,我们可以验证整个输入。此技术对于清理用户输入很有用。

解析数字前缀

此示例展示了如何从字符串中提取和转换数字前缀。

parse_prefix.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
    const char *data = "42apples";
    const char *digits = "0123456789";
    
    size_t num_len = strspn(data, digits);
    
    if (num_len > 0) {
        char num_str[20] = {0};
        strncpy(num_str, data, num_len);
        int number = atoi(num_str);
        
        printf("Numeric prefix: %d\n", number);
        printf("Remaining string: %s\n", data + num_len);
    } else {
        printf("No numeric prefix found\n");
    }

    return 0;
}

在这里,strspn 查找 data 中数字前缀的长度。然后,我们将此前缀复制到临时缓冲区并将其转换为整数。字符串的其余部分也可供进一步处理。这种方法对于解析混合格式的字符串很有用。请注意,strncpy 在具有适当大小缓冲区的安全场景下使用。

查找标记边界

strspn 可帮助识别字符串处理中的标记边界。

token_boundaries.c
#include <stdio.h>
#include <string.h>

void print_tokens(const char *str, const char *delims) {
    const char *ptr = str;
    
    while (*ptr) {
        size_t span = strspn(ptr, delims);
        ptr += span;  // Skip delimiters
        
        size_t len = strcspn(ptr, delims);
        if (len > 0) {
            printf("Token: %.*s\n", (int)len, ptr);
            ptr += len;
        }
    }
}

int main() {
    const char *text = "  apple, banana;  cherry ";
    const char *delimiters = " ,;";
    
    print_tokens(text, delimiters);
    return 0;
}

此代码同时使用 strspnstrcspn 对字符串进行标记。strspn 跳过前导分隔符,而 strcspn 查找下一个分隔符。这种组合有效地将字符串拆分为标记。%.*s 格式以指定长度打印子字符串。此技术对于自定义字符串解析很有用。

验证文件名

此示例演示了使用 strspn 进行文件名验证。

filename_validation.c
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

bool is_valid_filename(const char *name) {
    const char *valid_chars = 
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz"
        "0123456789-_.";
    
    if (strlen(name) == 0 || strlen(name) > 255) return false;
    if (name[0] == '.') return false;
    
    return strspn(name, valid_chars) == strlen(name);
}

int main() {
    const char *test1 = "document.pdf";
    const char *test2 = "bad*file.txt";

    printf("%s is %s\n", test1, is_valid_filename(test1) ? "valid" : "invalid");
    printf("%s is %s\n", test2, is_valid_filename(test2) ? "valid" : "invalid");

    return 0;
}

此代码检查文件名是否只包含允许的字符。strspn 验证整个字符串是否由有效字符组成。其他检查可确保长度正确并防止隐藏文件(以“.”开头)。这比简单的字符搜索更健壮。始终将 strspn 与其他验证结合使用以确保完全安全。

使用 strspn 的最佳实践

来源

C strspn 文档

本教程探讨了 strspn 函数,从基本用法到高级验证技术。正确使用时,它可以提供高效的字符串分析,同时有助于防止因格式错误的输入而导致的安全问题。

作者

我叫 Jan Bodnar,是一名敬业的程序员,对编码充满热情。自 2007 年以来,我通过 1,400 多篇文章和 8 本电子书分享了我的专业知识。凭借十多年的教学经验,我致力于使编程变得易于理解且引人入胜。

列表 C 标准库