HJ31 单词倒排 题解

news2024/11/24 17:45:37

题目描述:单词倒排_牛客题霸_牛客网 (nowcoder.com)

对字符串中的所有单词进行倒排。

1、构成单词的字符只有26个大写或小写英文字母;

2、非构成单词的字符均视为单词间隔符;

3、要求倒排后的单词间隔符以一个空格表示;如果原字符串中相邻单词间有多个间隔符时,倒排转换后也只允许出现一个空格间隔符;

4、每个单词最长20个字母;

 方法一:

定义一个字符指针数组,用于保存每个单词的起始字符地址,接下来将非字母字符全部替换成为字符串结尾标志'\0',则单词字符字母遇到结尾就结束了,相当于把一个字符串以非字母字符进行切割成为了多个字符串,最终对字符指针数组进行逆序打印每个单词即可。
 

  1. 创建一个字符数组来存储输入字符串,并用一个指针指向字符串的开头;创建一个字符指针数组,用于保存每个单词的起始字符地址;
  2. 创建一个循环,遍历输入字符串中的每个字符;
  3. 在循环中,检查当前字符是否为字母(大小写字母),你可以使用C标准库中的isalpha()函数来进行检查:
    1. 如果是字母,标记单词的起始位置,然后移动指针知道跳过这个单词(但指针指向的不是字母字符时,就跳过了一个单词);
    2. 如果遇到非字母字符(即不构成单词的字符),将该字符替换成为字符串结尾标志'\0',向后移动指针;
  4. 下标由大到小地打印字符指针数组的内容。

代码:

#include <stdio.h>
#include <ctype.h>
int main() {
    char arr[10001] = {0};
    char* dst[10001] = {NULL};
    gets(arr);
    char* move = arr;
    int count = 0;
    while(*move != '\0')
    {
        // 当遇到字母字符时
        if(isalpha(*move))
        {
            //记录单词的起始地址
            dst[count++] = move;
            // 跳过这个单词,找到非字母字符
            while(*move != '\0' && isalpha(*move))
            {
                move++;
            }
            continue;
        }
        // 当遇到非字母字符时
        *move = '\0';
        move++;
    }
    // 逆序打印
    for(int i = count-1;i>=0;i--)
    {
        printf("%s ", dst[i]);
    }
    return 0;
}

注:

在跳过一个单词的循环时,如果只是下面这种形式,可能会造成越界访问。例如:字符串为 “I am a student\0”。

while(isalpha(*move))
    move++;

在跳过最后一个单词 student 时,指针会指向 ’\0‘,跳出循环进行下一步:*move = ’\0‘ ;move++,即 ’\0‘ = ’\0‘ ;move++。这时move会指向字符串 ’\0‘ 后面一个位置,然后再一次进行外循环判断条件 *move != '\0',对move进行解引用,此时就发生了越界访问。

所以,正确的写法如下:

if(isalpha(*move))
{
    //记录单词的起始地址
    dst[count++] = move;
    // 跳过这个单词,找到非字母字符
    while(*move != '\0' && isalpha(*move))
    {
        move++;
    }
    continue;
}

这样,在跳过最后一个单词 student 时,指针指向 ’\0‘,跳出循环,执行continue使下一步:*move = ’\0‘ ;move++,不被执行,然后再一次进行循环判断 *move != '\0','\0' != '\0',条件为假,结束循环。

而且添加 continue 不会影响普通情况,例如:当跳过单词 am 时,move指向空格,执行continue,进行外循环判断条件  *move != '\0' , ’ ‘ != '\0',条件为真,进入循环:判断空格是否为字母字符--不是字母字符执行 *move = '\0'; move++; 

方法二:

因为,之前做过 单词逆置 这个题目(整体逆置,再逆置每一个单词),所以我用了这种思路,不过这种方法比较暴力。如果你想要了解 单词逆置 的话,可以看一下http://t.csdn.cn/pwNTt这篇博客。

步骤:

  1. 整体逆置,再逆置每一个单词,此时的字符串只需要再将单词之间的非字母字符(一个或多个)变成空格即可;
  2. 创建一个新的字符数组,用一个指针指向逆置后字符串的开头,进行判断:
    1. 如果指针指向的是字母字符,就将指针指向的内容添加到新的字符数组中;
    2. 如果指针指向的不是字母字符,就将空格添加到新的字符数组中;
  3. 最后打印新的字符数组。

因为单词之间只有一个空格,所以并不能 “ 遇到一个非字母字符时,就将空格添加到新的字符数组中” ;我们发现指针指向的非字母字符是字母字符后面一个非字母字符时,才添加空格,所以这里可以用一个变量来作为添加空格的条件:

当指针指向的是字母字符时,flag = 1;

当指针指向的是非字母字符时,判断条件:如果flag等于1时,添加空格,并将flag=0;如果flag不等于1,就不添加。

所以步骤就变成这样:

  1. 整体逆置,再逆置每一个单词,此时的字符串只需要再将单词之间的非字母字符(一个或多个)变成空格即可;
  2. 创建一个新的字符数组,用一个指针指向逆置后字符串的开头,进行判断:
    1. 如果指针指向的是字母字符,就将指针指向的内容添加到新的字符数组中,flag赋值为1;
    2. 如果指针指向的不是字母字符,如果flag等于1时,就将空格添加到新的字符数组中,如果flag不等于1,就不添加;flag赋值为0;
  3. 最后打印新的字符数组。

代码:

#include <stdio.h>
#include <string.h>
#include <ctype.h>
void reverse(char* left, char* right)
{
    while (left < right)
    {
        char temp = *left;
        *left = *right;
        *right = temp;

        left++;
        right--;
    }
}
int main() {
    char arr[10000] = { 0 };
    gets(arr);
    int len = strlen(arr);
    reverse(arr, arr + (len - 1));//逆置整体
    char answer[30] = { 0 };
    int flag = 0;
    char* dst = answer, * move = arr;
    // 逆置单词
    char* start = arr;
    char* end = start;
    while (*start != '\0')//当*start等于\0时,停止逆序
    {
        while (isalpha(*end) && *end != '\0')//注意最后一个单词的后面不是空格
        {
            end++;
        }
        reverse(start, end - 1);
        if (*end != '\0')//如果最后一个单词在向后移动时,会导致start跳过\0从而导致死循环
            end++;
        start = end;
    }
    // 将字符添加到新的字符数组中
    while (*move != '\0')
    {
        if (isalpha(*move))
        {
            *dst = *move;
            dst++;
            flag = 0;
        }
        else
        {
            if (flag == 0)
            {
                *dst = ' ';
                dst++;
                flag = 1;
            }
        }
        move++;
    }
    *dst = '\0';
    puts(answer);
    return 0;
}

今天的分享就到这里了,如果,你感觉这篇博客对你有帮助的话,就点个赞吧!感谢感谢……

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

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

相关文章

如何拼接两个视频在一起?

如何拼接两个视频在一起&#xff1f;在度过一个美好周末的时候&#xff0c;我和朋友一起拍摄了两组视频&#xff0c;准备将两个视频合并成一个并发布到朋友圈。这个想法非常棒&#xff0c;但是我在第一步就遇到了麻烦&#xff1a;如何将这两个视频拼接在一起&#xff1f;这听起…

MyBatis分页思想和特殊字符

目录 一、MyBatis分页思想 1.1 使用场景 1.2 代码演示 二、MyBatis特殊字符 2.1代码演示 一、MyBatis分页思想 1.1 使用场景 Mybatis分页应用场景&#xff1a; MyBatis是一个Java持久层框架&#xff0c;它提供了一种将SQL查询和结果映射到Java对象的简单方式。分页是MyBa…

【LeetCode】面试题总结 消失的数字 最小k个数

1.消失的数字 两种思路 1.先升序排序&#xff0c;再遍历并且让后一项与前一项比较 2.转化为数学问题求等差数列前n项和 &#xff08;n的大小为数组的长度&#xff09;&#xff0c;将根据公式求得的应有的和数与数组中实际的和作差 import java.util.*; class Solution {public …

龙迅半导体,LT9611 MIPIDSI/CSI转HDMI,双端口MIPI接收,HDMI支持4K30HZ,免费提供完善的资料和选型推荐

龙迅LT9611 1.描述&#xff1a; LT9611 MIPIDSI/CSI到HDMI1.4桥具有双端口MIPID-PHY接收器前端配置&#xff0c;每个端口有4个数据通道&#xff0c;每个数据通道运行2Gbps&#xff0c;最大输入带宽为16Gbps。该桥提供了一个HDMI数据输出与可选的S/PDIF或8通道I2S串行音频输入…

Excel变天!微软把Python「塞」进去了,直接可搞机器学习

量子位 | 公众号 QbitAI 喜大普奔&#xff01; 微软把Python弄进Excel了&#xff01; 搭建一个机器学习天气预测模型&#xff0c;在Excel里即可实现。 而且无需任何设置&#xff0c;在单元格里输入“PY”&#xff0c;就能开搞。 数据清理、预测分析、可视化等等任务&#xf…

Harbor平台离线搭建

之前我有写过如何搭建harbor以及配置harbor&#xff0c;本文主要讲一下在不联网的情况下如何搭建Harbor平台。 环境&#xff1a;centos 7.9 docker版本&#xff1a;20.10.17 harbor版本&#xff1a;v1.10.10 一、离线安装docker 安装包官方地址&#xff1a;Index of linux/sta…

麒麟系统上安装 MySQL 8.0.24

我介绍一下在麒麟系统上安装 MySQL 8.0.24 的详细步骤&#xff0c;前提是您已经下载了 mysql-8.0.24-linux-glibc2.12-x86_64.tar.xz 安装包。其实安装很简单&#xff0c;但是有坑&#xff0c;而且问题非常严重&#xff01;由于麒麟系统相关文章博客较少&#xff0c;导致遇到了…

[MyBatis系列③]动态SQL

目录 1、简介 2、if标签 3、foreach标签 4、SQL抽取 ⭐MyBatis系列①&#xff1a;增删改查 ⭐MyBatis系列②&#xff1a;两种Dao开发方式 1、简介 开发中在MyBatis映射文件配置SQL语句&#xff0c;但是前面配置的都是比较简单的&#xff0c;不涉及稍复杂的业务场景。想要应…

守护进程(精灵进程)

目录 前言 1.如何理解前台进程和后台进程 2.守护进程的概念 3.为什么会存在守护进程 4.如何实现守护进程 5.测试 总结 前言 今天我们要介绍的是关于守护进程如何实现&#xff0c;可能有小伙伴第一次听到守护进程这个概念&#xff0c;感觉很懵&#xff0c;知道进程的概念&…

实验八 网卡驱动移植

【实验目的】 掌握 Linux 内核配置的基本方法&#xff0c;完成对网卡驱动、NFS 等相关功能的配置 【实验环境】 ubuntu 14.04 发行版FS4412 实验平台交叉编译工具&#xff1a;arm-none-linux-gnueabi- 【注意事项】 实验步骤中以“$”开头的命令表示在 ubuntu 环境下执行&…

基于labview设备状态监测和故障诊断(一)NI软硬件介绍

随着近代工业逐步向机电一体化方向发展。设备的自动化、智能化、大型化与复杂 化程度的不断提高&#xff0c;设备发生故障给企业所带来的经济损失越来越大&#xff0c;因此对设备的运 行状况进行实时监测和故障诊断势在必行。可以这样说&#xff0c;机械设备的工作状况监测和…

C++设计模式(工厂模式)

文章目录 前言一、什么是工厂模式二、简单工厂模式三、简单工厂模式优点和缺点四、简单工厂适用场景五、简单工厂类的使用总结 前言 本篇文章正式带大家来学习C中的设计模式&#xff0c;这篇文章主要带大家学习工厂模式。 一、什么是工厂模式 工厂模式&#xff08;Factory P…

洗涤护理门店小程序DIY制作教程

随着移动互联网的快速发展&#xff0c;小程序成为了各行各业推广和服务的新平台。对于干洗店来说&#xff0c;拥有一个专属的洗护小程序不仅可以提升用户体验&#xff0c;还能增加店铺的曝光度和销售额。那么&#xff0c;如何DIY制作一个干洗店洗护小程序呢&#xff1f; 首先&a…

在Ubuntu上安装和设置RabbitMQ服务器,轻松实现外部远程访问

文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 内网穿透3.1 安装cpolar内网穿透(支持一键自动安装脚本)3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 RabbitMQ是一个在 AMQP(高级消息队列协议)基…

【最全】MySQL知识点总结

先简单的大致了解一下&#xff0c;学习知识的目的是运用&#xff01;&#xff01;&#xff01; MySQL是什么&#xff1f; 一种关系型数据库管理系统&#xff0c;也就是说这是用来管理数据库的工具。 SQL相关命令 数据库相关 创建数据库&#xff1a;CREATE DATABASE 数据库名; …

12、Pinia 快速入门

1、什么是Pinia Pinia 是 Vue 的最新 状态管理工具 &#xff0c;是 Vuex 的 替代品 2、手动添加Pinia到Vue项目 在实际开发项目的时候,关于Pinia的配置,可以在项目创建时自动添加 现在我们初次学习&#xff0c;从零开始&#xff1a; 1.使用 Vite 创建一个空的 Vue3 项目 n…

【JUC系列-02】深入理解CAS底层原理和基本使用

JUC系列整体栏目 内容链接地址【一】深入理解JMM内存模型的底层实现原理https://zhenghuisheng.blog.csdn.net/article/details/132400429【二】深入理解CAS底层原理和基本使用https://blog.csdn.net/zhenghuishengq/article/details/132478786 深入理解cas的底层原理和基本使用…

Bootstrap的类container与类container-fluid有什么区别?

阅读本文前建议先阅读下面两篇博文&#xff1a; 怎么样通过Bootstrap已经编译好(压缩好)的源码去查看符合阅读习惯的源码【通过Source Map(源映射)文件实现】 在CSS中&#xff0c;盒模型中的padding、border、margin是什么意思&#xff1f; 以下是Bootstrap的类 container 的盒…

【Java 高阶】一文精通 Spring MVC - 标签库 (八)

&#x1f449;博主介绍&#xff1a; 博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家&#xff0c;WEB架构师&#xff0c;阿里云专家博主&#xff0c;华为云云享专家&#xff0c;51CTO 专家博主 ⛪️ 个人社区&#x…

Android——基本控件(下)(十八)

1. 时钟组件&#xff1a;AnalogClock与DigitalClock 1.1 知识点 &#xff08;1&#xff09;掌握AnalogClock与DigitalClock的使用&#xff1b; 1.2 具体内容 package com.example.clockproject;import android.os.Bundle; import android.app.Activity; import android.view…