实验报告:统计字符串中子字符串出现的次数

实验报告

源程序:

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 int cntstring(char *source,char *substr);
 5 void main()
 6 {
 7     char str1[50],str2[20];       //str1 为主字符串,str2 为子字符串
 8     cout<<"input source string:";
 9     cin.getline(str1,50);
10     cout<<"input sub string:";
11     cin.getline(str2,20);
12     cout<<"Occurs:"<<cntstring(str1,str2)<<endl;
13 }
14 int cntstring(char *source,char *substr)
15 {
16     int sum=0;                   //统计子字符串数量初值为0
17     char *p1=source,*p2=substr;
18     while(*p1 !=‘\0‘)               //主字符串没有结束
19     {
20         if(*p1 == *p2)               //第一个字符相同
21         {
22             while(*p1 == *p2 && *p2 !=‘\0‘)   //循环比较后续字符
23             {
24                 p1++;p2++;            //子字符串没有结束,两字符串同事后移一个字符
25             }
26
27         }
28         else
29         {
30             p1++;                 //主字符串后移,重新比较
31         }
32
33         if(*p2 == ‘\0‘)
34             sum++;
35         p2=substr;                //字字符串出现一次,指针重新指向子字符串
36     }
37
38     return sum;                  //返回统计结果
39 }

提示:主函数使用cin.getline读入主字符串和子字符串。函数cntstring对于主字符串和子字符串从第一个字符开始逐一向后比较。第二个while循环表示当主字符串的当前字符与子字符串的第一个字符相同时,循环比较后续的字符是否相同,若循环完毕且指向子字符串的指针移到子字符串的末尾,则认为完成一次成功匹配,否则主字符串后移一个字符,再重新比较。

————————————————————————————

输入: input source string:This is a C++ program.

      input sub string:is

输出结果:Occurs:2

————————————————————————————

二、实验要求

对该题目进行下述修改,并对修改后的程序运行结果进行分析

错误分析:

重新运行程序,输入如下数据:

input source string:aaabc

input sub string:aabc

则输出结果为:Occurs:0

(1)对于错误分析中提出的问题,采用单步调试技术分析出错的原因。修改程序使其正确。

(2)修改程序,使其能够同时输出子字符串在主字符串中出现的每一个位置(该位置默认为子字符串中第一个字符在主字符串中出现的位置)。

三、实验结果以及分析(红色并下划线的是增加的代码

(1)将上述源程序代码更改为如下所示代码:

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 int cntstring(char *source, char *substr);
 5 void main()
 6 {
 7     char str1[50], str2[20];
 8     cout << "input source string:";
 9     cin.getline(str1, 50);
10     cout << "input sub string:";
11     cin.getline(str2, 20);
12     cout << "Occurs:" << cntstring(str1, str2) << endl;
13 }
14 int cntstring(char *source, char *substr)
15 {
16     int sum = 0;
17     char *p1 = source, *p2 = substr;
18     while (*p1 != ‘\0‘)
19     {
20         if (*p1 == *p2)
21         {
22             while (*p1 == *p2 && *p2 != ‘\0‘)
23             {
24                 p1++; p2++;
25             }
26
27         }
28         else
29         {
30             p1++;
31         }
32
33         if (*p2 == ‘\0‘)
34         {
35             sum++;
36         37         }
38
39         p2 = substr;
40         p1 = ++source;//←为添加的代码;
41     }
42
43     return sum;
44 }

分析

采用单步调试技术进行分析,拿错误分析中输入的数据 aaabc 和 aabc 来举例子

首先看实验流程,main函数将输入的两个字符串str1,str2作为实参,传递给*source,*substr的指针变量。

在用户函数cntstring中,声明字符型指针变量p1,p2,并将source(即str1的首地址)赋给p1,将substr(即str2的首地址)赋给p2。

看函数执行部分,当*p1(str1的首地址)不等于结束符‘\0‘时,进入while循环,如果*p1与*p2(str2的首地址)相等,则进入if语句,当指针p2还未指向结束符‘\0‘时,指针p1与p2同时向后移动一个字符,指向下一个字符。如str1为"aaabc",str2为"aabc",开始时,p1指向str1中的a,p2指向str2中的a,字符相同,两个指针同时向后移动。当指向的字符不相同时,指针p1指向下一个字符,当p2还未指向结束符‘\0‘时,将p2指针初始化,指向str2的第一个字符,同时也将p1指针初始化,指向str1的第二个字符(注意++source为指针运算,指针可以自增)。若p2指向了结束符,意味着已经找到了子字符串,故sum++(若没有找到子字符串p2是不可能指向结束符的)。当p1还未指向str1的结束符时,再次循环,从头上判断 字符是否相等开始(注意此时p1已经指向str1的第二个字符)。相同步骤以此类推

对于aaabc和aabc,前两个字符是相同的,当同时指向各自的第三个字符时,字符不相同,执行else语句中的p1++,p1指向了字符b,但后面有p1指针的初始化(p1=++source),故该轮循环结束后,p1指向str1的第二个字符a,p2也初始化,指向str2的第一个字符a,又开始一轮循环,则后面字符都相同,直到p2指向结束符,p1也指向结束符,执行了sum++语句,即sum=0+1,sum=1;返回值给主函数输出 Occurs:1;

(建议自己拿一只笔,用箭头模仿指针走向,按照程序运行的步骤来分析)

(2)将第一题中的代码改为如下代码:

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 int cntstring(char *source, char *substr);
 5 void main()
 6 {
 7     char str1[50], str2[20];
 8     cout << "input source string:";
 9     cin.getline(str1, 50);
10     cout << "input sub string:";
11     cin.getline(str2, 20);
12     cout << "Occurs:" << cntstring(str1, str2) << endl;
13 }
14 int cntstring(char *source, char *substr)
15 {
16     int sum = 0;
17     char *p1 = source, *p2 = substr,*p0 = source;
18     while (*p1 != ‘\0‘)
19     {
20         if (*p1 == *p2)
21         {
22             while (*p1 == *p2 && *p2 != ‘\0‘)
23             {
24                 p1++; p2++;
25             }
26
27         }
28         else
29         {
30             p1++;
31         }
32
33         if (*p2 == ‘\0‘)
34         {
35             sum++;
36             cout << "postion=" << source-p0+1<< endl;
37         }
38
39         p2 = substr;
40         p1 = ++source;
41     }
42
43     return sum;
44 }

分析

将str1的首地址赋给一个不变化的指针*p0(因为在后面运行中source会自增,设一个指针变量将其首地址保存下来)。

对于位置:由指针的运算可知,指针相减得出来的是整数且整数的值为两个指针指向的地址之间的数据单元的数量,举个栗子:

当p1指向aaabc中的b的时候,则p1-source(首地址,为第一个a)=3;(3个数据单元)

由于当str1,str2中的字符开始相等时,会进入while循环,就不会每指向下一个字符的时候进行初始化(p2 = substr;p1 = ++source;)

此时source保存着子字符串第一个字符在主字符串中的位置,比如主字符串为aaabc,子字符串aabc;source的值为主字符串中第二个a的地址

故source-p0等于1,再加1就是第二个a的位置,即子字符串在主字符串的中的位置。(仔细理解一下,我写的可能不够形象)

算法思想:指针的运算以及指针的移动指向。(具体看题(1)中的解释)

以上就是一道例题以及扩展题目的展示。若有更好的方法希望指出,谢谢!

时间: 2024-10-10 20:31:56

实验报告:统计字符串中子字符串出现的次数的相关文章

实现字符串中子字符串的替换2&mdash;&mdash;待替换字符串和替换字符串的长度可以不相等

//使用C语言实现字符串中子字符串的替换 //描述:编写一个字符串替换函数,如函数名为 StrReplace(char* strSrc, char* strFind, char* strReplace), //strSrc为原字符串,strFind是待替换的字符串,strReplace为替换字符串. //举个直观的例子吧,如:"ABCDEFGHIJKLMNOPQRSTUVWXYZ"这个字符串,把其中的"RST"替换为"ggg"这个字符串, //结

实现字符串中子字符串的替换

//使用C语言实现字符串中子字符串的替换 //描述:编写一个字符串替换函数,如函数名为 StrReplace(char* strSrc, char* strFind, char* strReplace), //strSrc为原字符串,strFind是待替换的字符串,strReplace为替换字符串. //举个直观的例子吧,如:"ABCDEFGHIJKLMNOPQRSTUVWXYZ"这个字符串,把其中的"RST"替换为"ggg"这个字符串, //结

汇编 实验报告5 字符串输入输出

;实验报告内容,输入一个字符串,去掉数字,输出ASSUME DS:DATA,CS,CDOE,SS,STACK DATA SEGMENT MAXLEN DB 15 INPUTLEN DB 0 STR1 DB 15 DUP(0) STR2 DB 15 DUP(0) DATA ENDS STACK1 SEGMENT STACK DW 40H DUP(0) STACK1 ENDS CODE SEGMENT START: MOV AX,DATA ;INITIAL THE DS,SS MOV DS,AX M

第五周总结&amp;实验报告三

第五周总结&实验报告三 实验报告 1.已知字符串:"this is a test of java".按要求执行以下操作:(要求源代码.结果截图.) ① 统计该字符串中字母s出现的次数. ② 统计该字符串中子串"is"出现的次数. ③ 统计该字符串中单词"is"出现的次数. ④ 实现该字符串的倒序输出. ① 统计该字符串中字母s出现的次数. package test3; public class Zifu { public static v

20135239 第一次实验报告

实验报告 一.实验内容 1. 使用JDK编译.运行简单的Java程序 2. 使用Eclipse 编辑.编译.运行.调试Java程序 要求: 完成实验.撰写实验报告 统计PSP时间 二.实验过程 使用JDK编译.运行简单的Java程序 1.进入实验环境后,打开Xfce终端.其作用类似于cmd命令行,用于打开和执行某些程序. 2.输入cd java0217->mkdir 20135239->cd 20135239->mkdir expel1->cd expel1->gedit H

技巧之C#统计字符串中字符出现的次数(转)

方法1.自定义类 class CharNum { private char c; private int num; public char C { get { return c; } } public int Num { get { return num; } set { num = value; } } public CharNum(char ch) { this.c = ch; this.num = 1; } } static void Main(string[] args) { /* */

【华为OJ平台练习题】统计一段字符串中含有空格、英文、数字的个数

//统计一段字符串中含有空格.英文.数字的个数 #include <iostream> using namespace std; void processString(char* s) { int n = strlen(s); int kg=0; int shuzi=0; int yingwen=0; if(n>0) { for(int a=0;a<n;a++) { if(s[a]==' ') kg++; if(s[a]<='9'&&s[a]>='0')

java怎么实现统计一个字符串中字符出现的次数

问题:假设字符串仅仅保护a-z 的字母,java怎么实现统计一个字符串中字符出现的次数?而且,如果压缩后的字符数不小于原始字符数,则返回. 处理逻辑:首先拆分字符串,以拆分出的字符为key,以字符出现次数为value,存入Map中. 源码如下: 1 import java.util.HashMap; 2 import java.util.Iterator; 3 import java.util.Map; 4 5 public class TestCompress { 6 7 public sta

Python(30)_统计输入的字符串有多少数字

#-*-coding:utf-8-*- ''' 统计用户输入的字符串中有几个数字 ''' # numList = ['0','1','2','3','4','5','6','7','8','9'] s = input('请输入字符串:') count = 0 for i in s: if i in numList: count +=1 print(count) Python(30)_统计输入的字符串有多少数字 原文地址:https://www.cnblogs.com/sunnybowen/p/1