02c语言——字符串相关操作

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

一、字符串基本概念

1.定义:
在c语言中不存在字符串这种数据类型,是通过字符数组来对字符串进行模拟。
2.字符串的初始化:
正确:char buf[100] = {0};或者char buf[] = “adsdasda”;
注意:(1)若是char buf[] = {‘a’,‘b’,‘c’};这种方式是错的没有字符串结束标志。
char buf[50] ={‘a’,‘b’,‘c’};这是是正确的,abc三个字符之后全是0;
(2) 字符’\0’ = 数字0 != 字符 ‘0’
(3)sizeof()与strlen()
sizeof:数组的个数
strlen:字符串的有效长度
(4)可以通过数组名和指针的方式访问字符串
指针可以修改但是数组名不可以,因为数组名是一个指针常量,指针是一个变量。
例子:如果在栈区上定义一个buf = “dasdasdasdad”;
buf相当于一个门牌号,如果变量名称改变的话,系统就找不名称去回收那一片内存空间。

二、字符串基本函数

(1).strcpy:

参数:目的字符串和源字符传的地址
返回值:char* 返回母的字符串的首地址方便操作。
代码如下(示例):

char* my_strcpy(char *dest,const char *src)
{
	if(dest == NULL || src == NULL)
	{ 
		return NULL;
	}
	char *temp = dest;
	while(*src)
	{
		*dest = *src;
		dest++;
		src++;
	}
	dest = 0;
	return temp;
}

(2)strcmp:

参数:目的字符串和源字符传的地址
返回值:0 代表两个字符串相等,1代表大于,-1代表小于。
代码如下(示例):

int my_strcmp(char* dest, const char *src)
{
	if(dest == NULL || src == NULL)
	{
		return -1;
	}
	while(*dest || *src)
	{
	
		if(*dest > *src)
		{
			return 1;
		}
		else if( *dest < *src)
		{
			return -1;
		}
		else
		{
			dest++;
			src++;
		}
	}
	return 0;
}

(3)strcat:

参数:目的字符串和源字符传的地址
返回值:0 代表两个字符串相等,1代表大于,-1代表小于。
代码如下(示例):

char* my_strcat(char *dest,const char*src)
{
	if(dest == NULL || src == NULL)
	{
		return NULL;
	}
	char *p = dest;
	while(*dest)
	{
		dest++;
	}
	while(*src)
	{
		*dest = *src;
		dest++;
		src++;
	}
	dest = 0;
	return p;
}

(4)strlen:

参数:目的字符串地址
返回值:整形记录了传入字符串的长度。
代码如下(示例):

int my_strlen(char* buf)
{
	if(buf == NULL)
	{
		return -1;
	}
	char * p = buf;
	int cnt = 0;
	while(*p)
	{
		cnt++;
		p++;
	}
	return cnt;
}

2.字符串解析

(1)strtok

用来切割字符串,根据固定的字符来进行分隔,
第一次分隔的时候,将字符串的首地址值传过去,之后strtok会将则会将该分隔字符改为\0 字符,之后分隔的时候传地址为NULL就行。
从终端接收到的字符串,看情况而定,一般需要用到字符串标志位时将字符串尾的’\n变’成’\0’。

int main(int argc, const char *argv[])
{
	char buf[256] = {0};
	char *arg[10] = {NULL};
	while(1)
	{
		fgets(buf,256,stdin);
		buf[strlen(buf)-1] = '\0';
		if(0 == strcmp(buf,"#quit"))
		{
			break;
		}
		arg[1] = strtok(buf," ");
		arg[2] = strtok(NULL," ");
	
		printf("arg[1]%s\n",arg[1]);	
		printf("arg[2]%s\n",arg[2]);	
	}
	return 0;
}

(2)strstr()

从一个字符串中找一个子串,并定位到子串的开始。

int main(int argc, const char *argv[])
{
	char buf[100] = "123abc345abc456abc";
	char *p = NULL;
	p = strstr(buf,"abc");
	printf("p:%s\n",p);
	return 0;
}

(3)index()

思想与strstr类似但是index是分隔不是子串而是字符。

int main(int argc, const char *argv[])
{
	char buf[100] = "asdasd = 123";
	char *p = NULL;
	p = index(buf,'=');
	// 输出=号之后的字符串内容
	printf("%s\n",p+1);
	return 0;
}

3.my_atoi

将字符串转换为数字

int my_atoi(char *src)
{
	char *temp = src;
	int num = 0;
	while(*temp)
	{
		num = num*10+(*temp-'0');
		temp++;
	}
	return num;
}

3.示例

1.统计字符串中出现的单词数

int cnt_str_word(char * src)
{
	int *temp = src;
	int cnt = 0;
	while(*temp)
	{
		while(*temp == ' ')
		{
			temp++;
		}
		while(*temp != ' ' && *temp != '\0')
		{
			temp++:
		}
		cnt++;
	}
	return cnt;
}

2.统计字符串中出现的数组

题目:将字符串中出现的连续数字,保存在数组中,并统计出现的数字
代码展示:

#include <stdio.h>

int my_atoi(char c)
{
	return c - '0';

}
int get_intnum(char *str,int *a,int len)
{
	int cnt = 0;
	char *begini = NULL;
	char *end = NULL;
	int num = 0;
	int new_num = 0;
	while(*str)
	{
		while(*str > 47 && *str <58)
		{
			num = my_atoi(*str);
			new_num = new_num*10+num;
			str++;
			printf("cnt = %d\n",cnt);
		}
		a[cnt] = new_num;
		if(new_num)
		{
			cnt++;
		}
		new_num = 0;
		str++;
	}
	return cnt;
}
void show_int(int *a, int len)
{
	int i =0;
	for(i=0;i<len;++i)
	{
		printf("%d\n",a[i]);
	}
	return ;
}
int main(int argc, const char *argv[])
{
	char str[256] = {"123 sfdf 123e 3333sdsddsf2334fds"};
	int cnt = 0;
	int a[20] = {0};
	cnt = get_intnum(str,a,20);
	printf("cnt = %d\n",cnt);
	show_int(a,cnt);
	return 0;
}

结果为:
在这里插入图片描述

3.计算两个字符串

计算这个两个字符串:“1234536898989”+“1111111111111”

#include <stdio.h>
#include <string.h>
/*字符串逆序*/
char *revse_str(char *p)
{
	char *begin = p;
	char *end = p+strlen(p)-1;
	while(begin < end)
	{
		char c = *begin;
		*begin =*end;
		*end = c;
		begin++;
		end--;
	}
	return p;
}
/**计算字符串/
char * add_str(char *pstr1,char *pstr2,char * psum)
{
	int len1 = strlen(pstr1);
	int len2 = strlen(pstr2);
	revse_str(pstr1);
	revse_str(pstr2);
	int flag =0;
	int i =0;
	for(i=0;i < (len1 > len2 ? len1 : len2);++i )
	{
		if(i < len1 && i < len2)
		{
			psum[i] = pstr1[i]+ pstr2[i] - '0' + flag;
		}
		else
		{
			psum[i] = pstr1[i]+ pstr2[i]+ flag;
		}
		if(psum[i] > '9')
		{
			psum[i] -= 10;
			flag = 1 ;
		}
		else
		{
			flag = 0;
		}
	}
	if(flag)
	{
		psum[i] = '1';
		i++;
	}
	psum[i] = '\0';
	revse_str(psum);
	return NULL;
}

int main(int argc, const char *argv[])
{
	char str1[100] = {"1234536898989"};
	char str2[100] = {"1111111111111"};
	char sum[100] = {0};
	char * pstr = NULL;
	pstr = add_str(str1,str2,sum);	
	printf("sum:%s\n",sum);
	return 0;
}

4.压缩解压字符串

题目
文本压缩有很多种方法,这里我们只考虑最简单的一种:把由相同字符组成的一个连续的片段用这个字符和片段中含有这个字符的个数来表示。例如 ccccc 就用 5c 来表示。如果字符没有重复,就原样输出。例如 aba 压缩后仍然是 aba。

解压方法就是反过来,把形如 5c 这样的表示恢复为 ccccc。

本题需要你根据压缩或解压的要求,对给定字符串进行处理。这里我们简单地假设原始字符串是完全由英文字母和空格组成的非空字符串。
压缩:输入样例
C
TTTTThhiiiis isssss a   tesssst CAaaa as
输出样例:
5T2h4is i5s a3 te4st CA3a as
解压输入样例
D
5T2h4is i5s a3 te4st CA3a as10Z`
输出样例:
TTTTThhiiiis isssss a   tesssst CAaaa asZZZZZZZZZZ``

```c
#include <stdio.h>
#include <string.h>
int compress(char* psrcstr,char* pdststr)
{
	char *ptemp = psrcstr;
	char key =0;
	char *pchar = NULL;
	int cnt =0;
	int len =0;
	while(* ptemp != '\0')
	{
		key = *ptemp;
		pchar = ptemp;
		while(*pchar != '\0' && *pchar == key)
		{
			cnt++;
			pchar++;
		}
		len=strlen(pdststr);
		if(cnt != 1)
		{
			sprintf(&pdststr[len],"%d%c",cnt,key);
		}
		else
		{
			sprintf(&pdststr[len],"%c",key);	
		}
		cnt =0;
		ptemp = pchar;
	}

	return 0;
}
int decompress(char * psrcstr,char *pdststr)
{
	int cnt = 0;
	char *ptemp =NULL;
	char *pnum = NULL;
	char tmpnum[32] = {0};
	int i =0;
	ptemp = psrcstr;

	while(*ptemp != '\0')
	{
		if(*ptemp >= '0' && *ptemp <= '9')
		{
			pnum = ptemp;
			while(*pnum != '\0' && *pnum >= '0' && *pnum<= '9')
			{
				pnum++;
			}
			memset(tmpnum,0,sizeof(tmpnum));
			strncpy(tmpnum,ptemp,pnum-ptemp);
			cnt = atoi(tmpnum);
			for(i=0;i < cnt; ++i)
			{
				*pdststr = *pnum;
				pdststr++;
			}
			ptemp = pnum+1;
		}
		else
		{
			*pdststr = *ptemp;
			pdststr++;
			ptemp++;
		}
	}
	return 0;
}
int main(int argc, const char *argv[])
{
	char ret_c = '0';
	char str1[1000] = {0};
	char str2[1000] = {0};

	scanf("%c",&ret_c);
	getchar();
	gets(str1);
	if('C' == ret_c)
	{
		compress(str1,str2);
	}
	else if ('D' == ret_c)
	{
		decompress(str1,str2);
	}
	printf("%s\n",str2);
	return 0;
}

5.字符串生日比较

某城镇进行人口普查,得到了全体居民的生日。现请你写个程序,找出镇上最年长和最年轻的人。

这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过 200 岁的老人,而今天是 2014 年 9 月 6 日,所以超过 200 岁的生日和未出生的生日都是不合理的,应该被过滤掉。
输入样例
5
John 2001/05/12
Tom 1814/09/06
Ann 2121/01/30
James 1814/09/05
Steve 1967/11/20
输出样例
3 Tom John

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//定义结构体保存姓名和生日信息
typedef struct person
{
	char name[10];
	char day[16];
}person;
//判断生日是否合理
int islegalbrithday(char *per1)
{
	if(-1 == strcmp(per1,"1814/09/06") || 1 == strcmp(per1,"2014/0906"))
	{
		return 0;
	}
	return 1;
}
int printf_brithday(void )
{
	person perlist[10];
	int n =0;
	int i =0;
	int cnt =0;
	int max = 0;
	int min = 0;
	int j =0;
	scanf("%d",&n);
	for(i=0;i<n;++i)
	{
		scanf("%s %s",perlist[i].name,perlist[i].day);
		if(islegalbrithday(perlist[i].day))
		{
			cnt++;
			//当第一次时,最大最小值为当前下标
			if(cnt == 1)
			{
				max = i;
				min = i;
			}
			else
			{
				//若当前下标大于max,更新max
				if(strcmp(perlist[max].day,perlist[i].day) == 1)
				{
					max = i;
				}
				//若当前下标小于min,更新min
				else if(-1 == strcmp(perlist[min].day,perlist[i].day))
				{
					min = i;
				}
			}
		}
	}
	//输出所要的信息
	printf("%d %s %s",cnt,perlist[max].name,perlist[min].name);
	
	
	return 0;
}
int main(int argc, const char *argv[])
{
	printf_brithday();
	
	return 0;
}

6.福尔摩斯密码

pat:1014

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int printf_mima(char (*pstr)[1024],int len)
{
	char *ptem1 = pstr[0];
	char *ptem2 = pstr[1];
	int key = 0;
	char *pweek[7]  ={
		"MON" ,"TUE","WED","THU","FRI","SAT","SUN"};
	while(1)
	{
		if( pstr == NULL || pstr == NULL)
		{
			break;
		}
		if((*ptem1 == *ptem2) && (*ptem1 >='A' && *ptem1<= 'G'))
		{
			key = *ptem1;

			break;
		}
		else
		{
			ptem1++;
			ptem2++;
		}
	}
	printf("%s",pweek[key-'A']);
	ptem1++;
	ptem2++;
	while(1)
	{
		
		if(*ptem1 =='\0' || *ptem2 == '\0')
		{
			break;
		}
		if( (*ptem1 == *ptem2) &&((*ptem1 >= '0' && *ptem1 <= '9') || (*ptem1 >='A' && *ptem1 <= 'N')))
		{
			key = *ptem1;
			break;
		}
		else
		{
			ptem1++;
			ptem2++;
		}
	}
	if(key >= '0' && key<=9 )
	{
		key -= '0';
	}
	else if( key >= 'A' && key <= 'N')
	{
		key = key - 'A' + 10; 
		
	}
	printf(" %2d",key);
	ptem1 = pstr[2];
	ptem2 = pstr[3];
	int i =0;
	while(1)
	{
		if(*ptem1 == '\0' ||*ptem2 == '\0')
		{
			break;
		}
		if((*ptem1 == *ptem2) && ( (*ptem1 >= 'a' && *ptem1 <= 'z') || (*ptem1 >= 'A' && *ptem1 <= 'Z')))
		{
			key = ptem1 - pstr[2];
			break;
		}
		else
		{
			ptem1++;
			ptem2++;
		}
	}
	printf(":%02d\n",key);
	return 0;
}
int main(int argc, const char *argv[])
{
	char str[4][1024] = {0};
	int i =0;
	for(i=0;i<4;++i)
	{
		gets(str[i]);
	}
	printf_mima(str,4);
	return 0;
}

总结

1.字符串的初始化要注意格式
2.字符串的最要的还是字符串解析。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值