今天学习的内容是字符串
什么是字符串
字符串就是一串字符,放在字符数组里面,或者字符指针,最后以’\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;
}
今天的题解
思路:直接遍历计数,然后返回百分比就好,要注意类型
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);
}
思路:用一个计数器记录缺勤的次数,用一个标志位标记连续三天迟到,一个计数器记录迟到次数,连续三天迟到,标记为为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;
}
思路是:遍历字符串,一个标志位,标志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;
}
思路:先求出两个字符串长度,最大的长度定义为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;
}