1.2 数据结构之 字符串

本文介绍了C语言中的sprintf()函数用于格式化输出字符串,strtok()及其安全性改进strtok_s的使用,以及strlen计算字符串长度、strcat连接字符串、strcmp比较字符串和基本的字符串处理函数如strcpy和atoi。还演示了如何应用这些函数在reverseWords函数中反转单词

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

编程总结

strtoul) 函数

C 库函数 unsigned long int strtoul(const char *str, char **endptr, int base) 把参数 str 所指向的字符串根据给定的 base 转换为一个无符号长整数(类型为 unsigned long int 型),base 必须介于 2 和 36(包含)之间,或者是特殊值 0。

unsigned long int strtoul(const char *str, char *endptr, int base)
str – 要转换为无符号长整数的字符串。
endptr – 对类型为 char
的对象的引用,其值由函数设置为 str 中数值后的下一个字符。
base – 基数,必须介于 2 和 36(包含)之间,或者是特殊值 0。

#include <stdio.h>
#include <stdlib.h>
int main()
{
   char str[30] = "2030300 This is test";
   char *ptr;
   long ret;
   ret = strtoul(str, &ptr, 10);
   printf("数字(无符号长整数)是 %lu\n", ret);
   printf("字符串部分是 |%s|", ptr);
   return(0);
}

在这里插入图片描述

sprintf() 函数

C 库函数 int sprintf(char *str, const char *format, …) 发送格式化输出到 str 所指向的字符串.

#include <stdio.h>
#include <math.h>

#define M_PI     3.1415926
int main(void)
{
	char str[80];
	int  res = 0;

	sprintf(str, "Pi 的值 = %f %d 0x%x", M_PI, M_PI, M_PI);
	puts(str);

	return(0);
}

在这里插入图片描述

strtok()函数 与 strtok_s()函数

char* strtok (char* str,constchar* delimiters );
函数功能:
  切割字符串,将str切分成一个个子串
函数参数:
  str:在第一次被调用的时间str是传入需要被切割字符串的首地址;在后面调用的时间传入NULL。
  delimiters:表示切割字符串(字符串中每个字符都会 当作分割符)。
函数返回值:
  当s中的字符查找到末尾时,返回NULL;
  如果查不到delimiter所标示的字符,则返回当前strtok的字符串的指针。

char * strtok(char *restrict str,const char *restrict delim);
//      1)需要切割的字符串,2)分隔符;返回值:切割完的有效字符串作为返回值返回
char * strtok_s(char *restrict str,rsize_t *restrict strmax,const char *restrict delim,char **restrict ptr);
//      1)需要切割的字符串,2)分隔符,3)存放分割后的原子符串;返回值:切割完的有效字符串作为返回值返回

  1. 在第一次调用时,strtok()必需给予参数s字符串,往后的调用则将参数s设置成NULL。每次调用成功则返回指向被分割出片段的指针。
  2. 需要注意的是,使用该函数进行字符串分割时,会破坏被分解字符串的完整,调用前和调用后的s已经不一样了
  3. 第一次分割之后,原字符串str是分割完成之后的第一个字符串,剩余的字符串存储在一个静态变量中,因此多线程同时访问该静态变量时,则会出现错误。
  4. strtok_s 这个函数将剩余的字符串存储在buf变量中,而不是静态变量中,从而保证了安全性。

以上4点内容,我们将在下面代码实践里得到印证
首先,下面代码里的 buf token plim buf 的含义,请内化熟记下来:

char *reverseWords(char *s)
{
	char strs[MAXSIZE] = { "  the   sky   is  blue " };
	const char *plim = " ";   // 存放分隔符
	char  *buf;               // 存放分割后的原子符串
	char  *token;             // 返回值,切割完的字符串
	int    i = 0;

	token = strtok_s(strs, plim, &buf);
	while (token != NULL) {
		printf("[%d] -- strs  is :%s\n", i, strs);
		printf("[%d] -- plim  is :%s\n", i, plim);
		printf("[%d] -- buf   is :%s\n", i, buf);
		printf("[%d] -- token is :%s\n", i, token);
		token = strtok_s(NULL, plim, &buf); // 在这个单词后面插入一个NULL表示断开
	}
	return s;
}

在这里插入图片描述
1)先看执行完第一次 strtok_s 几个变量的值如下:
(https://img-blog.csdnimg.cn/20210530175245262.png)
可看出 原 strs 发生了改变(将开头的分隔符跳过然后返回一个指针指向str中的第一个单词,印证了第2点),plim没变。buf 存放原字符串切割后的子串,token存切割的字符串 – “the”;

2)第二次及后续调用我们传入的 strs 是NULL,表示断开.
在这里插入图片描述
第四次时,token会返回NULL,不满足while循环退出。
在这里插入图片描述

strlen函数

计算字符串的实际长度,不包括’\0’。

算法:从第一个字符开始扫描,直到遇见第一个’\0’,停止扫描,返回字符串长度。

int strlen(const char *str)
{	
        int n=0;
        assert(str!=NULL);
        while(*str++!='\0')
	        ++n;
        return n;
}

strcat函数

strcat函数:将源字符串str2添加到目的字符串str1的末尾,同时覆盖str1末尾的’\0’,并在新的str1末尾添加’\0’,返回指向str1的指针。

算法:扫描str1,直到遇见’\0’,将str2逐个字符添加到str1末尾,最后添加’\0’。

char *strcat(char *str1, const char *str2)
{
	char *p=str1;
	assert( (str1!=NULL) && (str2!=NULL) ); 
	while(*str1!='\0')
		str1++;
	while(*str1++=*str2++);
	return p;
}

strcmp函数

strcmp函数:比较str1和str2两个字符串的大小,若str1>str2,则返回正数;若str1<str2,则返回负数;若str1==str2,则返回0。

算法:逐个比较str1和str2的每个字符,若相等且未遇见’\0’,则继续比较下一个字符,否则,返回str1和str2的差值。

int strcmp(const char *str1, const char *str2)
{	
	assert( (str1!=NULL) && (str2!=NULL) );
	while(*str1 && *str2&& (*str1==*str2)) 
	{
		str1++;
		str2++;
	}
	return *str1 - *str2;
}

strcpy函数

strcpy函数:将字符串str2(包括NULL)复制到字符串str1,返回指向str1的指针。

算法:将str2中逐个字符添加到str1指向的地址空间,必须保证str1指向的地址空间足够大。

char *strcpy(char *str1, const char *str2) 
{	
	char *p=str1;
	assert( (str1!=NULL) && (str2!=NULL) );
	while(*str1++=*str2++);
	return p; 
}

atoi函数(ascii to integer) – 字符串转换成整型

atoi函数是将字符串转换成整数
算法:首先跳过空格或制表符,再判断符号,最后通过减去’0’转化整数,跳过非数值,返回转换后的整数。

int main()
{
	int ret = atoi("-123");
	printf("%d\n", ret);
}
int atoi(char *str)
{
	int sum = 0, sign = 1;
	char *p = str;
	assert(str!=NULL);
	if(' '==*p||'\t'==*p)
		p++;
	if('-'==*p)
		sign=-1;
	if('-'==*p||'+'==*p)
		p++;
	while(*p >= '0' && *p <= '9')
	{
		sum = sum*10 + *p - '0';
		p++;
	}
	return sign * sum;
}

itoa函数(integer to ascii)

是C语言中的一个非标准函数,用于将整数转换为字符串 – 非标准的,LeetCode上无法使用该函数

# include <stdio.h>
# include <stdlib.h>
void main (void)
{
	int num = 100;
	char str[25];
	itoa(num, str, 10);
	printf("The number 'num' is %d and the string 'str' is %s. \n" ,
	num, str);
}
void itoa(int num, char str[])
{
	int i=0, j=0, sign=num;
	char tmp[10];
	if(num < 0)
		num =- num;	
	do
	{
		tmp[i++] = num % 10 + '0';
		num /= 10;
	}while(num > 0);
	if(sign < 0)
		tmp[i++] = '-';
	tmp[i] = '\0';
	i--;
	while(i >= 0)	
	{
		str[j] = tmp[i];
		j++;
		i--;
	}
	str[j]='\0';
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值