字符串总结加leetcode题解

在这里插入图片描述

今天学习的内容是字符串

什么是字符串

字符串就是一串字符,放在字符数组里面,或者字符指针,最后以’\0’结尾(ASCII码值为0)

char arr[] = "hello kiss";
char* pa = "hello kiss";//这里的字符串,是常量字符串,放在内存中的只读数据区中,所以是不可以修改的。

常量存储区也叫只读数据区,这是一块比较特殊的存储区,他们里面存放的是常量,是不允许修改的和静态区不同,静态区内的数据是可以修改的。

字符串遍历

首先要用strlen求出字符串长度(不包括\0)
然后循环遍历即可

int main()
{
    char arr[] = "hello world";
    int len = strlen(arr);
    for(int i = 0;i < len;i++)
    {
        .....
    }
    //其他写法
    for(int i = 0;arr[i]!='\0';i++)
    for(int i =0;arr[i];i++);//因为\0的ASCII码值为0;
}

大小写转换

for(int i =0;i<len;i++)
{
    if(arr[i]>='A'&&arr[i]<='Z')
    {
        arr[i] = arr[i]-'A'+'a'//这就完成了大写转小写,反之亦然
    }
}

字符串数组

可以理解为二维数组,每一行都是一个一维数组,用arr[i][j]就可以访问到每个字符。

字符串拷贝

char arr[] = "hello world";
char brr[] = "Hello Kissk";
strcpy(arr,brr);//将brr拷贝到arr

字符串比较

strcmp(arr,brr);//比较方式是按每个字符比较,直到不相等,或者某个字符串结束。

返回值>0 <0 0;

字符串分割

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

int main()
{
	char arr[] = "hello kiss kernel;666";
	//for (char* parr = strtok(arr, " ;"); parr; parr = strtok(NULL, " ;"))
	//{
	//	printf("%s\n",parr);
	//}
	char* parr = strtok(arr, " ;");
	while (parr != NULL)
	{
		printf("%s\n", parr);
		parr = strtok(NULL," ;");
	}

	return 0;
}
//最后输出结果为
hello
kiss
kernel
666

字符串翻转

就是用两个指针,从头到尾,从尾到头,遍历然后交换即可。

例题:给你一个字符串,仅反转元音字母,元音字母包括大小写。

#include<stdio.h>
#include<string.h>
char stc[] = "aeiouAEIOU";

int is_Achar(char s)
{
	int sz = strlen(stc);
	for (int i = 0; i < sz; i++)
	{
		if (s == stc[i])
			return 1;
	}
	return 0;
}

void Swap(char* str1, char* str2)
{
	char tmp = *str1;
	*str1 = *str2;
	*str2 = tmp;
}
int main()
{
	char arr[100] = { 0 };
	gets(arr);
	int len = strlen(arr);
	int left = 0;
	int right = len - 1;
	while (left < right)
	{
		while (arr[left] && !is_Achar(arr[left]))//找到元音字母才能停下
		{
			++left;
		}
		while (arr[right] && !is_Achar(arr[right]))//找到元音字母才能停下
		{
			--right;
		}
		if (left >= right)
		{
			break;
		}
		Swap(&arr[left], &arr[right]);//交换
		left++;//移动两个指针
		right--;
	}
	printf("%s\n", arr);
	return 0;
}

回文字符串

给定一个字符串判断其是不是回文串,字符串只考虑数字和字母字符,忽略大小写。

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

char* to_char_num(char* arr)
{
	int len = strlen(arr);
	char* ans = (char*)malloc(sizeof(char) * (len + 1));
	int returnsize = 0;
	for (int i = 0; i < len; i++)
	{
		if (arr[i] >= 'A' && arr[i] <= 'Z')
			ans[returnsize++] = arr[i];
		if (arr[i] >= 'a' && arr[i] <= 'z')
			ans[returnsize++] = arr[i];
		if (arr[i] >= '0' && arr[i] <= '9')
			ans[returnsize++] = arr[i];
	}
	ans[returnsize] = '\0';
	return ans;
}

int is_char_whi(char* ret)
{
	int len = strlen(ret);
	for (int i = 0; i < len / 2; i++)
	{
		if (ret[i] != ret[len - 1 - i])
			return 0;
	}
	return 1;
}

int main()
{
	char arr[101] = { 0 };
	gets(arr);
	//int len = strlen(arr);
	char* ret = to_char_num(arr);
	if (is_char_whi(ret))
	{
		printf("yes\n");
	}
	else
	{
		printf("no\n");
	}
	free(ret);
	return 0;
}

今天的题解

2278. 字母在字符串中的百分比

思路:直接遍历计数,然后返回百分比就好,要注意类型

int percentageLetter(char * s, char letter){
    int len = strlen(s);
    double sum = 0.0;
    for(int i =0;i<len;i++)
    {
        if(s[i]==letter)
        sum++;
    }
    return (int)(sum/len*100);
}

551. 学生出勤记录 I

思路:用一个计数器记录缺勤的次数,用一个标志位标记连续三天迟到,一个计数器记录迟到次数,连续三天迟到,标记为为1,最后判断返回即可。

bool checkRecord(char * s){
    int len = strlen(s);
    int sumA = 0;
    int flag = 0;
    int sumL = 0;
    for(int i =0;i<len;i++)
    {
        if(s[i]=='A')
        {
            sumA++;
            sumL = 0;
        }
        else if(s[i]=='L')
        {
            sumL++;
        }
        else
        {
            sumL = 0;
        }
        if(sumL>=3)
        {
            flag = 1;
        }
    }
    if(sumA<2&&flag==0)
        return true;
    return false;
}

2255. 统计是给定字符串前缀的字符串数目

思路是:遍历字符串,一个标志位,标志words这个字符串是不是s的子字符串,先求两个字符串长度,若是words的串大于s的长度,直接标志位置为0;若是不大于,进行判断,遍历两个字符串,遇到不同的字符就将标志位置为0,直到某个字符串结束。最后根据标志位,自增计数器即可。

int countPrefixes(char ** words, int wordsSize, char * s){
    int sum = 0;
    int len = strlen(s);
    for(int i =0;i<wordsSize;i++)
    {
        int j = 0;
        int flag = 1;//假设是子字符串
        int wlen = strlen(words[i]);
        if(wlen>len)
            flag = 0;
        while(words[i][j])
        {
            
            if(j>=len)
                break;
            if(words[i][j]!=s[j])
            {
                flag = 0;
            }
            j++;
        }
        if(flag==1)
            sum++;
    }
    return sum;
}

1071. 字符串的最大公因子

思路:先求出两个字符串长度,最大的长度定义为len_all,然后求出这两个字符串长度的最大公约数,这个最大公约数就是答案字符串的长度。然后循环遍历这两个字符串,用i%len1和i%len2,防止越界,然后i< maxlen的时候且str1的字符等于str2的之后就放到ans里面,然后遍历完最长的字符串,如果发现有不等于的字符,就返回一个空字符串。

int  is_mulnum(int len1,int len2)
{
    int a = (len1>len2)?len1:len2;
    int b = (len1<len2)?len1:len2;
    int c = a%b;
    while(b)
    {
        c = a%b;
        a = b;
        b = c;
    }
    return a;
}
char * gcdOfStrings(char * str1, char * str2){
    int left = 0;
    int right = 0;
    int len1 = strlen(str1);
    int len2 = strlen(str2);
    int len_all = (len1>len2)?len1:len2;
    int maxlen = is_mulnum(len1,len2);//求两个长度的最大公约数
    char* ans = (char*)malloc(sizeof(char)*(maxlen+1));
    
    for(int i =0;i<len_all;i++)
    {
        if(str1[i%len1]!=str2[i%len2])
            return "";
        if(i<maxlen)
        {
            ans[i] = str1[i];
        }
    }
    ans[maxlen] = '\0';
    return ans;
}

借鉴题解

思路2:利用库函数,首先用strstr去长的字符串里面找短的,找不到返回空字符串。然后进入循环,先比较找到较长的字符串,然后让较长的字符串指针向后移动短字符串的长度再次用strstr去长字符串中找短的,如果找不到返回空字符串,找到了就继续循环,两种情况跳出循环,1,两个指针后面的字符串完全相同,退出循环返回该指针后的字符串,2,遇到不相等的情况,返回空字符串终止循环。

char *gcdOfStrings(char *str1, char *str2)
{
    //if (strstr(str1, str2) == NULL && strstr(str2, str1) == NULL) 原答案
    if (!(strstr(str1, str2) == str1 || strstr(str2, str1) == str2))
        return "";
    int p_a = 0, p_b = 0, cmp = 0;
    do
    {
        cmp = strcmp(str1 + p_a, str2 + p_b);
        cmp > 0 ? (p_a += strlen(str2 + p_b)) : (p_b += strlen(str1 + p_a));
        //if (strstr(str1 + p_a, str2 + p_b) == NULL && strstr(str2 + p_b, str1 + p_a) == NULL)
        if (!(strstr(str1 + p_a, str2 + p_b) == (str1 + p_a) || strstr(str2 + p_b, str1 + p_a) == (str2 + p_b)))
            return "";
    } while (cmp);
    return str1 + p_a;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KissKernel

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值