You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用scanf()提取URL域名后缀并实现数组匹配索引查询?

能不能用scanf()提取URL域名后缀?

嘿,这个问题问得好!咱们直接说结论:用scanf()能实现针对简单场景的提取,但它的局限性很大,处理复杂URL时容易出错。如果你的URL格式比较固定(比如最多三个点,像www.xxx.com或www.xxx.com.tr这种),可以凑合用;但如果要应对各种不规则的URL,还是用字符串处理函数(比如strrchr、strtok这类)更稳妥。

先看scanf()的实现思路

scanf()的核心是靠格式控制符来匹配和提取内容,咱们可以利用%*[^.]来跳过任意非.的字符,%*c跳过.本身,然后精准抓取我们想要的部分。

但这里有个问题:你给出的两个例子格式不一样——一个是两个点的www.stackoverflow.com,要提取最后一个.后的com;另一个是三个点的www.google.com.tr,要提取倒数第二个.和最后一个.之间的com。纯scanf很难同时兼容这两种情况,因为它是按顺序匹配的,必须预先知道URL的结构(比如有几个点),不然匹配会出错:

  • 用%*[^.]%*c%*[^.]%*c%s的话,www.stackoverflow.com能正确提取com,但www.google.com.tr会读取到com.tr,不符合需求;
  • 换用%*[^.]%*c%*[^.]%*c%[^.]%*c%s,只能提取www.google.com.tr里的com,但对www.stackoverflow.com会匹配失败,因为没有足够的.。

所以纯scanf只能处理固定格式的URL,得结合额外逻辑(比如先统计点的数量)才能勉强兼容你的示例场景,灵活性很差。

更靠谱的方案:结合字符串函数

既然你本来就打算写函数实现,那不如直接用C标准库的字符串函数,逻辑更清晰,也能处理更多场景。比如这个思路:

  1. 从右往左找第一个.(也就是最后一个点),记为last_dot;
  2. 再从last_dot的左边找前一个.,记为prev_dot;
  3. 如果prev_dot存在(URL至少两个点),提取prev_dot+1到last_dot之间的内容;如果不存在(只有一个点),提取last_dot+1到结尾的内容;
  4. 把提取到的后缀和你的数组匹配,返回索引或-1。

给你写个示例代码:

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

// 匹配后缀的数组
const char* suffixes[] = {"com", "org", "net", "edu"};
const int suffix_count = sizeof(suffixes)/sizeof(suffixes[0]);

int findSuffixIndex(const char* url) {
    // 找最后一个点
    char* last_dot = strrchr(url, '.');
    if (!last_dot) return -1; // 没有点,无效URL

    // 找倒数第二个点
    char* prev_dot = strrchr(url, '.');
    if (prev_dot == last_dot) {
        prev_dot = strrchr(url, '.', last_dot - url - 1);
    }

    char* target_suffix;
    // 临时截断字符串,方便提取
    char original_char = *last_dot;
    if (prev_dot) {
        target_suffix = prev_dot + 1;
        *last_dot = '\0';
    } else {
        target_suffix = last_dot + 1;
    }

    // 遍历数组匹配
    int index = -1;
    for (int i = 0; i < suffix_count; i++) {
        if (strcmp(target_suffix, suffixes[i]) == 0) {
            index = i;
            break;
        }
    }

    // 恢复原URL的字符
    if (prev_dot) *last_dot = original_char;
    return index;
}

int main() {
    char url[256];
    printf("输入URL:");
    fgets(url, sizeof(url), stdin);
    // 去掉fgets带来的换行符
    url[strcspn(url, "\n")] = '\0';

    int index = findSuffixIndex(url);
    if (index != -1) {
        printf("匹配到后缀%s,索引为%d\n", suffixes[index], index);
    } else {
        printf("未匹配到后缀,返回-1\n");
    }

    return 0;
}

这个代码能完美处理你提到的两种情况:

  • 输入www.stackoverflow.com,提取com,匹配数组返回0;
  • 输入www.google.com.tr,提取com,匹配数组返回0;
  • 输入www.example.org,提取org,返回1。

回到你的问题:scanf到底能不能?

如果一定要用scanf,那只能针对固定格式的URL做处理,比如先统计URL里的点数量,再用对应的格式字符串。比如:

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

int main() {
    char url[256];
    char suffix[32];
    printf("输入URL:");
    scanf("%s", url);

    // 统计点的数量
    int dot_count = 0;
    for (int i = 0; url[i]; i++) {
        if (url[i] == '.') dot_count++;
    }

    if (dot_count == 2) {
        // 格式:xxx.xxx.xxx,提取最后一个xxx
        sscanf(url, "%*[^.]%*c%*[^.]%*c%s", suffix);
    } else if (dot_count == 3) {
        // 格式:xxx.xxx.xxx.xxx,提取倒数第二个xxx
        char temp[32];
        sscanf(url, "%*[^.]%*c%*[^.]%*c%s%*c%s", suffix, temp);
    } else {
        printf("格式不支持\n");
        return -1;
    }

    // 匹配数组逻辑
    const char* suffixes[] = {"com", "org", "net", "edu"};
    const int suffix_count = sizeof(suffixes)/sizeof(suffixes[0]);
    int index = -1;
    for (int i = 0; i < suffix_count; i++) {
        if (strcmp(suffix, suffixes[i]) == 0) {
            index = i;
            break;
        }
    }

    printf("后缀:%s,索引:%d\n", suffix, index);
    return index;
}

但这个代码的问题很明显:只能处理2个或3个点的URL,要是URL有1个点(比如example.com)或者更多点(比如a.b.c.d.e.com),就直接失效了。而且scanf读取URL时遇到空格会停止,也不符合实际URL的使用场景。

所以总结一下:scanf可以做,但只适合非常固定的简单场景,大部分情况下,用字符串处理函数写自定义函数会更可靠、灵活。

内容的提问来源于stack exchange,提问作者SarpSTA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:56:34