第3天----在一行句子中寻找最长最短单词

news2024/9/22 5:32:23

今天我们将学习如何在一行句子中寻找(第一次出现的)最长最短单词。本节内容会或多或少地利用到第一讲/第二讲的知识点,需要的同学可以先去看看前面的内容。

在这里插入图片描述


一、小试牛刀:

题目描述
输入 1 行句子(不多于 200 个单词,每个单词长度不超过 100),只包含字母、空格、逗号和句号。单词由至少一个连续的字母构成,空格、逗号和句号都是单词间的间隔。
输出第 1 个最长的单词和第 1 个最短单词。

输入格式
输入数据:一行句子。

输出格式
输出数据:

  • 第 1 行,第一个最长的单词。
  • 第 2 行,第一个最短的单词。

输入输出样例
输入:
I am a student,i am studying Programming language C in Peking University.
输出:
Programming
I

  • 根据题目要求,我们只需要在所有合法的字符串中,输出第一个出现的最长单词和最短单词。

1. 方法一:

  • 我们可以对于每个读入的字符串利用C++string库里的find()函数查找目标字符','/'.'是否存在,并利用substr()函数来截取所需的字符串(goto可以解决连续逗号问题),最后将所有合法的字符串存储到vector容器中。具体代码如下:
#include<iostream>
#include<vector>
#include<string>
using namespace std;
vector<string>str;//存储字符串
vector<int>str_length;//存储字符串长度
string s, s1;
size_t found;//用于find函数

int main(void)
{	
	int cnt = 0;//字符串个数
	while (1)
	{
		cin >> s;
		loop:
		found = s.find(',');//在s中查找逗号是否存在
		if (found != string::npos)//如果找到了逗号
		{
			s1 = s.substr(0, found);//0~found截取字符串

			str.push_back(s1);//将截取的字符串存入str
			str_length.push_back(s1.length());//将截取的字符串长度存入str_length
			cnt++;

			s = s.substr(found + 1);//将s截取为逗号后面的字符串
			goto loop;//为了避免逗号连续出现,所以用goto返回到loop继续判断
		}
		if (s[s.length() - 1] == '.') {//如果该字符最后一个字符是句号
			s1=s.substr(0, s.length() - 1);//截取句号前面的字符串

			str.push_back(s1);
			str_length.push_back(s1.length());
			cnt++;

			break;
		}

		str.push_back(s);
		str_length.push_back(s.length());
		cnt++;
	}
	int max = 0;
	int min = 0;
	for (int i = 0; i < cnt; i++)
	{
		if(str_length[i]>str_length[max])  max = i;
		if(str_length[i]< str_length[min]) min = i;
		//cout << str[i] << " ";//print大法
	}
	cout << str[max] << endl;
	cout << str[min];

	return 0;
}
  • 此方法虽然容易想,但是本身的执行效率并不高,时间复杂度和空间复杂度占用较大。

2. 方法二:

相信大家拿到这题后很快就可以想出来,我们需要发现一个单词,在单词中间记录信息,再对比信息。

  • 那么怎样判断一个单词的开始与结束呢?

我们在阅读的时候,每个单词开始前都会有一个标点符号或空格提醒我们这是下一个单词,那么代码也一样,发现一个空格或标点符号,更新数据。

for(int i=0;i<a.length();i++){
	if(a[i] == ' ' || a[i] == ',' || a[i] == '.'){
		//更新数据;	
	}
   	//单词长度++;
}
  • 如何更新数据?

可以设置两个变量,一个记录最长单词的结束位置,一个记录最长单词的长度,这样输出时我们就可以用结束位置-长度找到开始位置,并且输出。最小值也一样。

  • 具体代码如下:
#include <iostream>
#include <string>
using namespace std;
string a;
int sum = 0, maxx = -100, maxb, minb, minn = 1000000;
int main() {
	getline(cin, a);//带空格输入
	for (int i = 0; i < a.length(); i++) {
		if (a[i] == ' ' || a[i] == ',' || a[i] == '.') {//如果发现标点符号和空格,代表单词结束
			if (maxx < sum) {//如果单词长度突破目前发现的最长长度
				maxb = i;//把最长单词的结束点更新,i就是结束点
				maxx = sum;//把最长单词的长度更新
			}
			if (minn > sum) {//如果单词长度低于目前发现的最短长度
				minb = i;//更新最短单词结束点
				minn = sum;//更新最短长度
			}
			sum = 0;//sum清空,以便下次操作
		}
		else {
			sum++;//如果是字母,长度加一
		}
	}
	for (int i = maxb - maxx/*从开始位置开始输出*/; i < maxb/*到结束位置结束*/; i++) {
		cout << a[i];
	}
	cout << endl;
	for (int i = minb - minn; i < minb; i++) {//最短单词同理
		cout << a[i];
	}
	return 0;
}
  • 这样做可谓是非常妙,时间复杂度和空间复杂度大大降低,极大地提高了代码的运行效率,并且撇弃了复杂的操作,不仅更易书写,也使读者更易理解。

3. 方法三:

  • 每个字符逐个读入,读取到换行或文件结束时退出。先判断是不是分隔符,如果是,就更新最长单词和最短单词,并清空当前单词,否则添加当前字符到当前单词里。最后输出结果就可以了。代码如下:
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
int main()
{
	string a,b,t;
	int la=0,lb=1000;
	char ch;
	while(ch=getchar())
	{
		if(ch=='\n'||ch==EOF)	break;
		if(ch==' '||ch==','||ch=='.')
		{
			if(t.length()>la)
				a=t,la=t.length();
			if(t.length()<lb)
				b=t,lb=t.length();
			t="";
			continue;
		}
		t.push_back(ch);
	}
	cout<<a<<endl<<b;
	return 0;
}
  • 其实方法3本身和方法2并没有太大的区别,但相较于方法2来说则更为简便,对于结果的输出不再是利用做差得到,而是直接输出,使得代码进一步优化。

4. 方法四:

  • 在这题中,我们需要得出句中最长的单词与最短的单词。因此,我们可以采用 string 字符串 的方式进行扫描。首先是整体的字符串 s ,要使用 getline 进行输入,因为 字符串中有空格。然后是单词的字符串 s0 ,同时需要计数(单词长度),再与 ans1 , ans2 打擂台得到最大值与最小值。
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
int ans1=0,ans2=0x3f3f3f,cnt;
string s,s1,s2,s0;
int main()
{
	getline(cin,s);//一整行输入
	for(int i=0;i<s.length();i++)
	{
		if(s[i]==' '||s[i]==','||s[i]=='.')//判定单词末尾(注意中英符号区分)
		{
			if(cnt>ans1)//最大值打擂台
			{
				s1=s0;
				ans1=cnt;
			}
			if(cnt<ans2)//最小值打擂台
			{
				s2=s0;
				ans2=cnt;
			}
			cnt=0;
			s0.clear();//清除当前单词
		}
		else
                {
                    s0+=s[i]; //一般情况(记录单词字母以及其个数)
                    cnt+=1;
                }
     	
	}
	cout<<s1<<endl<<s2<<endl;//一般输出
    return 0;
}

  • 此方法和方法2,3类似,不做过多解释。

二、拓展讲解:

1.substr()函数:

  • C++substr()函数是用于提取字符串的子串的函数。它接受两个参数,第一个参数是起始位置,第二个参数是要提取的子串的长度。函数返回一个新的字符串,包含从起始位置开始的指定长度的字符。

下面是substr()函数的语法:

string substr (size_t pos, size_t len) const;
  • pos:起始位置,表示要提取子串的起始字符的索引。索引从0开始计数
  • len:子串的长度,表示要提取的字符数量。

下面是一个示例代码,演示如何使用substr()函数:

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello,World!";
    
    // 提取从索引6开始的子串,长度为5
    std::string sub = str.substr(6, 5);
    
    std::cout << sub << std::endl; // 输出 "World"
    
    return 0;
}

在上面的示例中,我们首先定义了一个字符串str,然后使用substr()函数提取了从索引6开始的子串,长度为5。提取的子串存储在变量sub中,并打印输出。

  • 需要注意的是,substr()函数返回的是一个新的字符串,不会修改原始字符串

当然,在C++中,substr()函数也可以只传递一个参数,表示从指定位置开始提取到字符串的末尾的子串。

  • 下面是一个示例代码,演示如何使用只有一个参数的substr()函数:
#include <iostream>
#include <string>

int main() {
    std::string str = "Hello,World!";
    
    // 提取从索引7开始到字符串末尾的子串
    std::string sub = str.substr(6);
    
    std::cout << sub << std::endl; // 输出 "World!"
    
    return 0;
}
  • 在上面的示例中,我们使用substr()函数只传递了一个参数,即起始位置。这将提取从索引6开始到字符串末尾的子串,并将其存储在变量sub中,然后打印输出。

2. goto语句:

  • C语言中的goto语句是一种无条件跳转语句,它可以将程序的执行直接转移到指定的标签位置。goto语句可以用于跳转到程序中的任意位置,包括循环、条件语句、函数等。

下面是goto语句的基本语法:

goto label;
...
label: statement;
  • goto后面是标志符label,它是用户定义的标签(标签名称必须是唯一);
  • 将标签放在需要跳转执行的地方前面且以冒号:结尾。
  • label后面是一个语句,该语句是在goto语句被执行时要跳转到的位置。

下面是一个使用goto语句的示例代码:

#include <stdio.h>

int main() {
    int i = 1;
    
    loop:
    printf("i = %d\n", i);
    i++;
    
    if (i <= 5) {
        goto loop; // 跳转到标签loop处
    }
    
    return 0;
}
  • 在上面的示例中,我们使用goto语句在循环中实现了一个简单的计数器。首先定义了变量i并初始化为1,然后使用loop作为标签。在循环中,我们打印输出i的值,然后将i递增。如果i小于等于5,就跳转到标签loop处继续执行循环。这样,我们就实现了一个简单的计数器。

但需要注意的是,goto语句容易导致程序结构混乱,使代码难以理解和维护。因此,在实际编程中,应尽量避免使用goto语句,而是使用更结构化的控制流语句(如循环和条件语句)来组织代码。


3. string::clear()函数:

  • 在C++的string库中,clear()函数用于清空字符串的内容,即将字符串中的所有字符都删除,使字符串变为空字符串。

下面是clear()函数的语法:

void clear();
  • clear()函数没有参数。
  • 调用clear()函数将清空字符串的内容。

下面是一个使用clear()函数的示例代码:

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello, World!";
    
    std::cout << "Before clear: " << str << std::endl; // 输出 "Before clear: Hello, World!"
    
    str.clear();
    
    std::cout << "After clear: " << str << std::endl; // 输出 "After clear: "
    
    return 0;
}
  • 在上面的示例中,我们首先定义了一个字符串str,并将其初始化为"Hello, World!"。然后,我们使用clear()函数清空了字符串的内容。在调用clear()函数后,字符串变为空字符串。最后,我们通过打印输出来验证字符串是否已经清空。

但需要注意的是,clear()函数只清空字符串的内容,而不会释放字符串所占用的内存。字符串对象的容量(即分配的内存大小)不会改变。如果需要释放字符串所占用的内存,可以使用shrink_to_fit()函数。


4. shrink_to_fit()函数:

  • 在C++的string库中,shrink_to_fit()函数用于将字符串的容量调整为适合其当前大小的最小值。这意味着它可能会释放字符串中未使用的内存空间,从而减少内存的占用

下面是shrink_to_fit()函数的语法:

void shrink_to_fit();
  • shrink_to_fit()函数没有参数。
  • 调用shrink_to_fit()函数将使字符串的容量调整为适合其当前大小的最小值。

下面是一个使用shrink_to_fit()函数的示例代码:

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello, World!";
    
    std::cout << "Before shrink_to_fit: capacity = " << str.capacity() << std::endl; // 输出 "Before shrink_to_fit: capacity = 14"maybe
    
    str.shrink_to_fit();
    
    std::cout << "After shrink_to_fit: capacity = " << str.capacity() << std::endl; // 输出 "After shrink_to_fit: capacity = 13"maybe
    
    return 0;
}
  • 在上面的示例中,我们首先定义了一个字符串str,并将其初始化为"Hello, World!"。然后,我们使用capacity()函数获取字符串的容量,并打印输出。在调用shrink_to_fit()函数后,我们再次使用capacity()函数获取字符串的容量,并打印输出。可以看到,调用shrink_to_fit()函数后,字符串的容量可能会从14减少到了13,即可能会释放1个字节的内存空间。
  • 但需要注意的是,根据C++标准,shrink_to_fit()函数是一个非强制性的操作,实现可能会忽略该请求。因此,调用shrink_to_fit()函数并不一定会导致字符串的容量减小。

  • 实际上,大多数实现中的string类会动态地管理内存,根据需要自动分配和释放内存。当我们从字符串中删除字符时,实现通常会自动释放相应的内存,而不需要显式调用shrink_to_fit()函>数。


  • 本节我们主要学习了如何在一个句子中找到并打印出第一个出现的最长单词,用了几种不同的方法去实现,但是殊途同归,基本的思路是一致的。除此之外,我们还学习了substr()函数,goto语句,clear()函数等等。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/902005.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

股票交易这个游戏玩法的本质

养家老师的“买在分歧&#xff0c;卖在一致”不用过度解读了&#xff0c;这句话也会是一个人入门标志&#xff0c;那就是这个市场是博弈的市场&#xff0c;预期打满没有任何分歧的话&#xff0c;那就没有继续博弈的价值了&#xff0c;也就只有最后一批接盘的人&#xff0c;而分…

Java程序设计——编写一个登录页面

需要编写两个类 LonginFrame、MainFrame LonginFrame类 import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class LoginFrame extends JFrame {JLabel lbluserLogIn;JL…

GitLab与GitLab Runner安装(RPM与Docker方式),CI/CD初体验

背景 GitLab 是一个强大的版本控制系统和协作平台&#xff0c;记录一下在实际工作中关于 GitLab 的安装使用记录。 一开始使用 GitLab 时&#xff0c;是在 CentOS7 上直接以 rpm 包的方式进行安装&#xff0c;仅作为代码托管工具来使用&#xff0c;版本&#xff1a; 14.10.4 …

OpenCV基础知识(6)— 滤波器

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。在尽量保留原图像信息的情况下&#xff0c;去除图像内噪声、降低细节层次信息等一系列过程&#xff0c;被叫做图像的平滑处理&#xff08;或者叫图像的模糊处理&#xff09;。实现平滑处理最常用的工具就是滤波器。通过调节…

对容器、虚拟机和 Docker 的初学者友好介绍

一、说明 如果你是一个程序员或技术人员&#xff0c;你可能至少听说过Docker&#xff1a;一个有用的工具&#xff0c;用于在“容器”中打包&#xff0c;运输和运行应用程序。很难不这样做&#xff0c;这些天它得到了所有的关注 - 来自开发人员和系统管理员。即使是像谷歌、VMwa…

idea gerrit 插件使用指引

IDEA安装gerrit插件 在线安装&#xff08;推荐&#xff09; 直接搜索gerrit&#xff0c;安装即可离线安装 可以到github下载离线包&#xff1a;https://github.com/uwolfer/gerrit-intellij-plugin/releases&#xff0c;不过可能会有版本不兼容问题&#xff0c;还是推荐在线安装…

完美版积分商城系统-奇偶商城系统源码+独立代理后台

奇偶商城系统源码 完美版独立代理后台 1.演示环境&#xff1a;Linux Centos7以上版本 宝塔 2.Nginx 1.18.0 PHP7.0 Mysql5.6 3.伪静态选择thinkphp 4./Application/Common/Conf 修改数据库信息 详细搭建教程附在压缩包内了,下载查看

信号量

信号量&#xff08;semaphore&#xff09;和信号只有一字之差&#xff0c;却是不同的概念&#xff0c;信号量与之前介绍的IPC不同&#xff0c;它是一个计数器&#xff0c;用于实现进程间的互斥于同步 本文参考&#xff1a; Linux 的信号量_linux 信号量_行孤、的博客-CSDN博客 …

常见的 Python 错误及其解决方案

此文整理了一些常见的 Python 错误及其解决方案。 1、SyntaxError: invalid syntax 说明&#xff1a;无效的语法是最常见的错误之一&#xff0c;通常是由于编写代码时违反了 Python 的语法规则。可能的原因&#xff1a; 忘记在 if、while、for 等语句后写冒号&#xff0c;或者…

perl下载与安装教程【工具使用】

Perl是一个高阶程式语言&#xff0c;由 Larry Wall和其他许多人所写&#xff0c;融合了许多语言的特性。它主要是由无所不在的 C语言&#xff0c;其次由 sed、awk&#xff0c;UNIX shell 和至少十数种其他的工具和语言所演化而来。Perl对 process、档案&#xff0c;和文字有很强…

GAN!生成对抗网络GAN全维度介绍与实战

目录 一、引言1.1 生成对抗网络简介1.2 应用领域概览1.3 GAN的重要性 二、理论基础2.1 生成对抗网络的工作原理2.1.1 生成器生成过程 2.1.2 判别器判别过程 2.1.3 训练过程训练代码示例 2.1.4 平衡与收敛 2.2 数学背景2.2.1 损失函数生成器损失判别器损失 2.2.2 优化方法优化代…

windows批处理set命令:设置变量,计算表达式

文章目录 基础模式表达式模式变量输入模式环境变量 基础模式 变量是一切编程的基础&#xff0c;在批处理语言中&#xff0c;通过set设置变量&#xff0c;而在调用变量时&#xff0c;需要在变量两端加上百分号&#xff0c;例如 set a1 echo %a%运行结果为 >set a1 >ech…

离市区太远的高铁站,导致旅客舍弃高铁而转用其他交通工具

随着高铁网络的完善&#xff0c;如今旅客出行越来越多选择快速、便捷的高铁作为出行交通工具&#xff0c;不过旅客显然也对一些城市的高铁站离市区太远有所抱怨&#xff0c;导致不少消费者选择舍弃高铁而转用其他交通工具。 网上有一份高铁站离市区距离的排名&#xff0c;据悉离…

Linux Xshell常用命令

一、查看服务器信息 1.1、查看CentOS服务器版本号 执行以下命令 cat /etc/redhat-release结果如下&#xff1a; 1.2、查看服务器根目录下空间占用情况 执行以下命令 cd / du -h --max-depth1 |grep G |sort参数说明&#xff1a; –max-depth1 最大深度为1 grep ‘G’ 文…

JavaScript中的this关键字的作用,以及它如何确定其值

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ this关键字的作用⭐ this的值取决于执行上下文⭐ 示例⭐ 总结⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这…

Linux常用命令——dig命令

在线Linux命令查询工具 dig 域名查询工具 补充说明 dig命令是常用的域名查询工具&#xff0c;可以用来测试域名系统工作是否正常。 语法 dig(选项)(参数)选项 <服务器地址>&#xff1a;指定进行域名解析的域名服务器&#xff1b; -b<ip地址>&#xff1a;当主…

探秘Maven神奇力量:使用systemPath加载外部JAR包

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; 探秘Maven神奇力量&#xff1a;使用systemPath加载外部JAR包 ⏱️ 创作…

攻防世界-ics-06

原题解题思路 看着页面多&#xff0c;其实只有报表中心能够跳转&#xff0c;但是选了确定后没反应&#xff0c;应该不是注入&#xff0c;只有id会变化。 在burp中设置好负载进行爆破 有一个长度与众不同的包 打开发现flag。

攻防世界-simple_php

原题 解题思路 flag被分成了两个部分&#xff1a;flag2&#xff0c;flag2。获得flag1需要满足变量a0且变量a≠0&#xff0c;这看起来不能实现&#xff0c;但实际上当变量a的值是字符时&#xff0c;与数字比较会发生强制类型转换&#xff0c;所以a为字符型数据即可&#xff0c;变…

STP生成树总结

一、什么是STP&#xff08;802.1D&#xff09; STP协议生来就是为了冗余而存在的&#xff0c;单纯树型的网络无法提供足够的可靠性&#xff0c;由此我们引入了额外的链路&#xff0c;这才出现了环路这样的问题。但单纯是标准的802.1D STP协议并不能实现真正的冗余与负载…