深圳幻海软件技术有限公司 欢迎您!

【算法入门】字符串基础

2023-04-12

目录一.字符串引言1.字符串基础二.洛谷P5734详解1.字符串相关库函数💫(1)strcpy函数💫💫(2)strcat函数💫💫(3)strstr函数💫2.题目讲解一.字符串引言1.字符串基础字符串通常以\0作为结束标志,\0的ASCll码值为0,计算字符串长度时会忽略斜杠零。二.洛谷P

目录

  • 一.字符串引言
  • 1.字符串基础
    • 二.洛谷P5734详解
      • 1.字符串相关库函数
          • 💫(1) strcpy函数 💫
          • 💫(2) strcat函数 💫
          • 💫(3)strstr函数 💫
      • 2.题目讲解

一.字符串引言

1.字符串基础

字符串通常以\0作为结束标志,\0的ASCll码值为0,计算字符串长度时会忽略斜杠零。

二.洛谷P5734详解

1.字符串相关库函数

在讲解题目之前我们先介绍几个关于字符串操作常用的几个库函数

💫(1) strcpy函数 💫

strcpy也叫 拷贝函数 ,头文件为 string.h ,顾名思义它可以将一个字符串数组的内容拷贝到另一个数组中。
strcpy函数原型为:

char *strcat(char *dest, const char *src)
  • 1

下面通过一段代码演示它的效果:

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

int main()
{
char ch[20] = "helloworld";
char arr[10] = "xxxxxx";
printf("%s", strcpy(ch, arr));
return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

因为strcpy函数的返回值是拷贝后数组的地址,所以可以通过链式访问在屏幕上打印出xxxxxx,还需要注意的是拷贝函数目的数组要留够拷贝的空间不然程序会崩溃。

💫(2) strcat函数 💫

strcat函数称为追加拷贝函数 ,头文件为头文件为 string.h
strcat函数原型为:

char *strcat(char *dest, const char *src)
  • 1

strcat可以找到目标数组的结束标志\0,并用起始数组代替\0。
我们还是用代码来演示他的效果:

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

int main()
{
char ch[15] = "likou";
char arr[10] = "luogu";
printf("%s", strcat(ch, arr));
return 0;
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

结果:

这个函数同样需要在目标数组开辟足够的空间,才能 正常追加拷贝

💫(3)strstr函数 💫

strstr函数是字符串查找函数,文件为头文件为 string.h
函数原型为:

char *strstr( const char *arr1, const char *arr2 );
  • 1

strstr函数可以在arr1数组中查找是否存在arr2数组中的内容,如果存在返回首次出现的地址,不存在则返回空指针 NULL
下面用代码来演示下它的效果:

以上将几个要用得字符串函数讲解了,接下来我们看题目。

2.题目讲解

  • 我们先来看一下题目:

    分析: 题目考察了四个字符串的操作,只要我们掌握以上几个函数,还有熟练运用 数组下标 和字符串的 结束标志 即可。
    逻辑分析与代码编写:

我们先根据题目写出整体的逻辑:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <iostream>

using namespace std;

char ch[110];
char in[110];

int main()
{
int count;
cin >> count;
cin >> ch;
while (count--)
{
int input;
scanf("%d", &input);
if (input == 1)
{
}
else if (input == 2)
{
}
else if (input == 3)
{
}
else
{
}
}
return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

代码实现:

  1. 我们先实现第一个操作:在文档后插入字符串并输出,显然要用到追加拷贝函数strcat,如下:
if (input == 1)
{
cin >> in;
strcat(ch, in);
cout << ch << endl;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  1. 第二步,截取文档从第 a 个字符起 b 个字符输出,只需要在数组第a+b的位置赋为\0在运用拷贝函数操作即可,代码送上 体会一下:
else if (input == 2)
{
int start;
int end;
scanf("%d %d", &start, &end);
char in[110] = { 0 };

ch[start + end] = '\0';
strcat(in, &ch[start]);
strcpy(ch, in);

cout << ch << endl;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

因为在上一步操作中对in数组进行了输入,所以这里在使用in数组之前应该将in数组中的元素释放出来。

  1. 第三步,插入片段,在文档中第 a 个(有歧义,是数组下标)字符前面插入字符串,并输出文档的字符串。代码如下:
else if (input == 3)
{
int cur;
scanf("%d", &cur);
cin >> in;

strcat(in, &ch[cur]);
ch[cur] = '\0';
strcat(ch, in);
printf("%s\n", ch);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

上图代码逻辑雀氏妙,大家仔细体会。

  1. 最后一步:查找子串,查找字符串 str 在文档中最先的位置并输出;如果找不到输出 -1。通过观察示例所知,若存在返回的是下标而不是内存地址(返回下标我们可以使用指针减指针的方式实现),显然这里需要用来strstr函数
else
{
cin >> in;
char* ret=strstr(ch, in);
printf("%d\n", ret != NULL ? (int)(ret-ch) : -1);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这样用三目操作符 没想到吧?


下面完整代码奉上:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <iostream>

using namespace std;


char ch[110];
char in[110];


int main()
{
int count;
cin >> count;
cin >> ch;
while (count--)
{
int input;
scanf("%d", &input);
if (input == 1)
{
cin >> in;
strcat(ch, in);
cout << ch << endl;
}
else if (input == 2)
{
int start;
int end;
scanf("%d %d", &start, &end);
char in[110] = { 0 };

ch[start + end] = '\0';
strcat(in, &ch[start]);
strcpy(ch, in);

cout << ch << endl;
}
else if (input == 3)
{
int cur;
scanf("%d", &cur);
cin >> in;

strcat(in, &ch[cur]);
ch[cur] = '\0';
strcat(ch, in);
printf("%s\n", ch);

}
else
{
cin >> in;
char* ret = strstr(ch, in);
printf("%d\n", ret != NULL ? (int)(ret - ch) : -1);

/*if (NULL == ret)
cout << -1 << endl;
else
cout << ret - ch << endl;*/
}
}
return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

在源码中可以发现我注释了几处释放in数组的操作,其实我当时在疑惑多次对in数组输入,为什么不需要在下一次之前将in的元素释放掉。真相是 即使数组中保留着上一次输入的字符串 scanf再次输入时 会在字符串后自动补上\0保证上一次的元素无法影响输出(在不越界的情况下)

以上就是这次的全部内容。

感谢阅读,共同进步
文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览43883 人正在系统学习中