C语言 字符串解析strchr/strrchr/strtok//strtok_r函数使用

news2025/1/12 3:42:14

在程序中,解析用户输入的参数(命令行参数)是很常见的操作,本文将讲解C语言中常见的一些解析字符串函数使用方法。

1 strchr

1.1 描述

strchr() 用于查找字符串中的一个字符,并返回该字符在字符串中第一次出现的位置。其原型定义在头文件 <string.h> 中。
char *strchr(const char *str, int c) 在参数 str 所指向的字符串中搜索第一次出现字符 c(一个无符号字符)的位置。
strchr() 函数返回的指针指向字符串中的字符,如果要将该指针用作字符串,应该将其传递给其他字符串处理函数,例如 printf() 或 strncpy()。

1.2 声明

char *strchr(const char *str, int c)
str – 要查找的字符串。
c – 要查找的字符。
如果在字符串 str 中找到字符 c,则函数返回指向该字符的指针,如果未找到该字符则返回 NULL。

1.3 实例
#include <stdio.h>
#include <string.h>

int main()
{
    const char *str = "https://10.229.89.210/home/data/1.txt";
    const char ch = 'd';
    char *ptr;

    ptr = strchr(str, ch);

    if (ptr != NULL)
    {
        printf("字符 '%c 出现的位置为 %ld。\n",ch,  ptr - str + 1);
        printf("|%c| 之后的字符串是 - |%s|\n", ch, ptr);
    }
    else
    {
        printf("没有找到字符 'd' 。\n");
    }
    return (0);
}

在这里插入图片描述

2 strrchr

2.1 描述

char *strrchr(const char *str, int c) 在参数 str 所指向的字符串中搜索最后一次出现字符 c(一个无符号字符)的位置。其原型定义在头文件 <string.h> 中。

2.2 声明

char *strrchr(const char *str, int c)
str – C 字符串。
c – 要搜索的字符。以 int 形式传递,但是最终会转换回 char 形式。
返回值
该函数返回 str 中最后一次出现字符 c 的位置。如果未找到该值,则函数返回一个空指针

2.3 实例

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

int main()
{
    const char *str = "https://10.229.89.210/home/data/1.txt";
    const char ch = '/';
    char *ptr;

    ptr = strrchr(str, ch);

    if (ptr != NULL)
    {
        printf("字符 '%c 出现的位置为 %ld。\n",ch,  ptr - str + 1);
        printf("|%c| 之后的字符串是 - |%s|\n", ch, ptr);
    }
    else
    {
        printf("没有找到字符 'd' 。\n");
    }
    return (0);
}

在这里插入图片描述

3 strtok

3.1 描述

char *strtok(char *str, const char *delim) 分解字符串 str 为一组字符串,delim 为分隔符。

3.2 声明

char *strtok(char *str, const char *delim)
str – 要被分解成一组小字符串的字符串。
delim – 包含分隔符的 C 字符串。
该函数返回被分解的第一个子字符串,如果没有可检索的字符串,则返回一个空指针。

3.3 实例

3.3.1 实例1

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

int main()
{
    char *str = "https://10.229.89.210/home/data/1.txt";

    char *str1 = malloc(sizeof(char) * (strlen(str) + 1));
    strcpy(str1, str);
    const char ch = '/';
    char *ptr;
    char *ptr1;
    ptr = strtok(str, ":");
    //ptr1 = strtok(str1, ":");

    if (ptr != NULL)
    {
    //   printf("%s\n", str);     // strtok会修改
       printf("%s\n", ptr);
    //   printf("\n%s\n\n", ptr1);
    //   printf("\n|%c| 之后的字符串是 - |%s|\n\n", ch, ptr);
    }
    else
    {
        printf("\n没有找到字符 'd' 。\n");
    }
    return (0);
}
结果:段错误 (核心已转储)

3.3.2 实例2

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

int main()
{
    char *str = "https://10.229.89.210/home/data/1.txt";

    char *str1 = malloc(sizeof(char) * (strlen(str) + 1));
    strcpy(str1, str);
    // char str2[64]; strcpy(str2, str);   ==> 数组也可以,如果不习惯 malloc/free匹对使用
    const char ch = '/';
    char *ptr;
    char *ptr1;
    //ptr = strtok(str, ":");
    ptr1 = strtok(str1, ":");

    if (ptr1 != NULL)
    {
    //   printf("%s\n", str);     // strtok会修改str参数值
    //   printf("%s\n", ptr);
       printf("\n%s\n\n", ptr1);
    //   printf("\n|%c| 之后的字符串是 - |%s|\n\n", ch, ptr);
    }
    else
    {
        printf("\n没有找到字符 'd' 。\n");
    }
	free(str1);
    return (0);
}
结果正确: https

4 strtok_r

4.1 声明
char *strtok_r(char *str, const char *delim, char **saveptr);
函数的返回值是 排在前面的 被分割出的字串,或者为NULL,
str是传入的字符串。需要注意的是 :第一次使用strtok_r之后,要把str置为NULL,
delim指向依据分割的字符串。常见的空格“ ” 逗号“,”等
saveptr保存剩下待分割的字符串。

比如:按空格分割 字符串 “first second third”,

分第一次得字串"first",然后saveptr指向了"second third"

分第2次得字串"second",然后saveptr指向了"third"
分第3次得字串"third",然后saveptr指向了NULL
结束。

#include <stdio.h>
#include <string.h>
#include<stdlib.h>
int main()
{
    // Our input string
    char input_string[] = "https:/10.229.89.210/home/data/1.txt";

    // Our output token list
    char **token_list = NULL;
    token_list = (char **)malloc(sizeof(char *) * 64);


    // A pointer, which we will be used as the context variable
    // Initially, we will set it to NULL
    char *context = NULL;

    // To get the value of the context variable, we can pass it's address
    // strtok_r() to automatically populate this context variable, and refer
    // it's context in the future
    char *token = strtok_r(input_string, "/", &context);

    int num_tokens = 0; // Index to token list. We will append to the list

    while (token != NULL)
    {
        // Keep getting tokens until we receive NULL from strtok()
        token_list[num_tokens] = strdup(token); // Copy to token list
        num_tokens++;
        token = strtok_r(NULL, "/", &context); // We pass the context variable to strtok_r
    }

    // Print the list of tokens
    printf("Token List:\n");
    for (int i = 0; i < num_tokens; i++)
    {
        printf("%s\n", token_list[i]);
    }
    free(token_list);
    return 0;
}

参考链接:
1 strtok函数缺陷再探
2 strtok () 和 strtok_r ()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/430525.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数学知识】一文学会算法中的数学知识(1.1)

目录 一.数论 1.质数 (1)质数的判断 (2)分解质因数&#xff08;数几个质数相乘&#xff09; (3)求1-n的所有质数 2.约数 (1)试除法求所有约数 (2)约数个数和约数之和 (3)最大公约数&#xff08;欧几里得算法 &#xff09; 一.数论 1.质数 在大于1 的整数&#x…

全回显SSRF测试两则

之前遇到可回显SSRF&#xff0c;并没有怎么去深入&#xff0c;可能漏洞点支持file协议更偏向于任意文件读取&#xff0c;不会去思考可回显SSRF的深入利用&#xff1b;直到读了pmiaowu师傅的可回显SSRF直接搭建成了代理进行内网渗透&#xff0c;后面遇到了两个可回显SSRF&#x…

【Kafka】Kafka为什么快?

Kafka之所以快的原因有三个&#xff1a;顺序读写、页缓存、零拷贝。 顺序读写 Kafka依赖磁盘来存储和缓存消息。 在我们的印象中&#xff0c;磁盘的读写速度会比内存的读写速度慢&#xff0c;但这是在随机读写场景下的比较。 实际上&#xff0c;磁盘的顺序读写能力不容小觑&am…

Spring IoC注解开发

Component 组件 Controller 控制器 Service 业务 Repository 仓库 其实他们四个本质都一样&#xff0c;只不过另外三个是Component的别名&#xff0c;在不同层使用容易区分 首先需要加入aop依赖&#xff0c;如果你事先加入spring-context依赖&#xff0c;则会关联加入ao…

亚马逊、temu、速卖通、国际站卖家如何利用好测评补单这张王牌?

大家好我是亚马逊测评珑哥。 现在越来越多的跨境电商平台入局&#xff0c;目前跨境电商平台亚马逊、TEMU、ozon、ebay、wish、lazada、敦煌、shopee、速卖通、poshmark、阿里国际站、沃尔玛、newegg、美客多等跨境平台的卖家都在递增&#xff0c;大家都知道&#xff0c;随着各…

javaEE 初阶 — 第一个 servlet 程序

文章目录 Servlet 是什么第一个 Servlet 程序1 创建项目2 引入依赖3 创建目录结构4 代码编写5 打包程序6 部署7 验证 如何使用 tomcat 插件打包及部署1 什么是插件2 插件的安装3 插件的使用4 可能会出现的问题 Servlet 是什么 Servlet 是一种实现 动态页面 的技术&#xff0c;是…

DataX和MongoDB之间的数据导入导出案例

DataX和MongoDB之间的数据导入导出案例 文章目录DataX和MongoDB之间的数据导入导出案例0. 写在前面1. MongoDB前置知识1.1 基础概念详解1.1.1 数据库1.1.2 集合1.1.3 文档&#xff08;Document&#xff09;2. DataX 导入导出案例2.1 读取 MongoDB 的数据导入到 HDFS2.1.1 编写配…

模板的分离编译

目录 &#xff1a; 1.分离编译概念 2.模板是不支持分离编译的 3.报链接错误的原因 4.如何解决 ----------------------------------------------------------------------------------------------------------------------- 1.分离编译概念 一个程序由若干个源文件共同实现&a…

java版工程项目管理系统源码 Spring Cloud+Spring Boot+Mybatis+Vue+ElementUI+前后端分离 功能清单

ava版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目显示1…

Eureka单机搭建

Eureka简介 Eureka Spring Cloud Eureka 是Netflix 开发的注册发现组件&#xff0c;本身是一个基于 REST 的服务。提供注册与发现&#xff0c;同时还提供了负载均衡、故障转移等能力 Eureka3个角色 服务中心&#xff0c;服务提供者&#xff0c;服务消费者 Eureka Server&a…

(leetcode C语言)1. 两数之和 9. 回文数

目录 1. 两数之和 思路 代码 9. 回文数 思路 思路1 代码1 思路2 代码2 1. 两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只…

设计模式-创建型模式之建造者模式

5. 建造者模式5.1. 模式动机无论是在现实世界中还是在软件系统中&#xff0c;都存在一些复杂的对象&#xff0c;它们拥有多个组成部分&#xff0c;如汽车&#xff0c;它包括车轮、方向盘、发送机等各种部件。而对于大多数用户而言&#xff0c;无须知道这些部件的装配细节&#…

linux系统安装和配置网关

Linux 目前国内 Linux 更多的是应用于服务器上&#xff0c;而桌面操作系统更多使用的是 Windows 安装linux虚拟机 网址 VMware下载网址 点击Workstation 16 Pro for Windows下载 安装CentOS centO下载网址 依次点击 7.6.1810/ isos/ x86_64/ CentOS-7-x86_64…

改善供应商关系的八种方法

与供应商保持良好关系的重要性有很多原因。最重要的是&#xff0c;它使每个人的日常工作更加愉快。它还可以为你获得更好的交易&#xff0c;有助于协作并增强商誉。 但是&#xff0c;每个供应商都是不同的&#xff0c;建立牢固的关系可能很棘手。本文将解释企业如何建立并操持…

TypeScript(十二)模块

目录 引言 d.ts声明文件 declare关键字 全局声明 全局声明方式 全局声明一般用作 函数声明 在.ts中使用declare 外部模块&#xff08;文件模块&#xff09; 模块关键字module 声明模块 模块声明方式 模块通配符 模块导出 模块嵌套 模块的作用域 模块别名 内部…

机器学习:皮尔逊相关系数——影评相关性分析案例

机器学习&#xff1a;皮尔逊相关系数——影评相关性分析案例 文章目录机器学习&#xff1a;皮尔逊相关系数——影评相关性分析案例:rocket:1、皮尔逊相关系数概念及公式:rocket:2、案例代码部分皮尔逊&#xff08;pearson&#xff09;相关系数、 斯皮尔曼&#xff08;spearman&…

vue2 和 vue3 共存

1.共存的前置条件 1.1 之前全局安装的 vue2 或者 vue3 的脚手架进行卸载&#xff0c;使用 npm命令卸载vue2 npm uninstall vue-cli -g 再使用 vue -V 查看版本出现以下提示为卸载完成 vue3卸载要使用命令npm uninstall vue/cli -g 1.2 安装cnpm 在命令行中输入 npm install -…

java面试题(SpringBoot)

SpringBoot 1.什么是SpringBoot&#xff1f;有什么优点&#xff1f; springboot是spring的子项目&#xff0c;是spring组件的一站式解决方案&#xff0c;简化了使用的难度&#xff0c;简省了配置 优点&#xff1a; 容易上手&#xff0c;提升开发效率内置web容器管理第三方工…

第六章 物理层

数据通信基础 数据通信基本概念 消息与信息&#xff1b;消息是信息的载体 消息&#xff1a;人类能够感知的描述信息&#xff1a;抽象概念&#xff0c;可以理解为消息中所包含的有意义的内容 通信&#xff1a;一点精确或近似地再生另一点的信息信号&#xff1a;传递信息的载体…

提高客户忠诚度的 5 种方法

提高客户忠诚度是成功经营企业的最重要因素之一。忠诚的客户也更有可能向他们的朋友和家人推荐您的业务&#xff0c;从而开辟更多的收入来源。所以您需要将您的战略重点放在建立作为企业主的客户忠诚度上。 提高客户忠诚度的 5种方法 1.优先考虑客户服务 作为企业应该积极主动…