字符串摘要(C语言)

时间:2024-02-21 22:48:39

题目描述

给定一个字符串的摘要算法,请输出给定字符串的摘要值。

  1. 去除字符串中非字母的符号。
  2. 如果出现连续字符(不区分大小写),则输出:该字符(小写)+ 连续出现的次数。
  3. 如果是非连续的字符(不区分大小写),则输出:该字符(小写)+ 该字母之后字符串中出现的该字符的次数。
  4. 对按照以上方式表示后的字符串进行排序:字母和紧随的数字作为一组进行排序,数字大的在前,数字相同的,则按字母进行排序,字母小的在前。

输入

一行字符串,长度为[1,200]

输出

摘要字符串

示例一

输入
aabbcc

输出

a2b2c2

示例二

输入

bAaAcBb

输出

a3b2b2c0

说明

bAaAcBb:

第一个 b 非连续字母,该字母之后字符串中还出现了 2 次(最后的两个 Bb),所以输出 b2,

a 连续出现 3 次,输出 a3,

c 非连续,该字母之后字符串再没有出现过 c,输出 c0

Bb 连续 2 次,输出 b2

对 b2a3c0b2 进行排序,最终输出 a3b2b2c0

代码

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

// 定义一个结构体,用于存储字符及其出现的次数
struct Letter {
    char name;
    int count;
};

// 自定义比较函数,用于对字母及其数量进行排序
int compare(const void *a, const void *b) {
    struct Letter *letterA = (struct Letter *)a;
    struct Letter *letterB = (struct Letter *)b;

    // 如果字母出现次数相同,则按字母字典序降序排列
    if (letterA->count == letterB->count) {
        return letterA->name - letterB->name;
    }

    // 否则按字母出现次数降序排列
    return letterB->count - letterA->count;
}

int main() {
    char inputStr[1000];
    // 读取一行输入字符串
    fgets(inputStr, sizeof(inputStr), stdin);

    // 创建一个过滤后的字符串数组,只包含字母
    char filteredStr[1000];
    int filteredStrIdx = 0;
    for (int i = 0; inputStr[i] != '\0'; i++) {
        char ch = inputStr[i];
        if (isalpha(ch)) { // 检查字符是否为字母
            filteredStr[filteredStrIdx++] =
                tolower(ch); // 转换为小写并添加到过滤后的字符串中
        }
    }
    filteredStr[filteredStrIdx] = '\0'; // 结束过滤后字符串

    // 初始化计数器和当前字符变量
    int count = 1;
    char currentChar = filteredStr[strlen(filteredStr) - 1];

    // 创建一个存储字母及其数量的结构体数组
    struct Letter *charList =
        (struct Letter *)malloc(sizeof(struct Letter) * strlen(filteredStr));
    int charListIdx = 0;

    // 初始化一个大小为26的数组,记录每个字母在剩余字符串中的出现次数
    int charCountMap[26] = {0};

    // 遍历过滤后的字符串,计算连续或非连续字符的出现次数
    for (int i = strlen(filteredStr) - 2; i >= 0; i--) {
        char ch = filteredStr[i];
        if (currentChar == ch) {
            count++; // 相同字符,增加计数
        } else {
            // 计算非连续字符或结束遍历时该字符的总出现次数
            if (count == 1) {
                count += charCountMap[currentChar] - 1;
                charCountMap[currentChar] = count + 1;
            } else {
                charCountMap[currentChar] = count;
            }
            
            // 将当前字符及其出现次数存入结构体数组
            struct Letter letter;
            letter.name = currentChar;
            letter.count = count;
            charList[charListIdx++] = letter;
            currentChar = ch;
            count = 1;
        }
        // 处理最后一个字符(无需检查下一个字符)
        if (i == 0) {
            if (count == 1) {
                count += charCountMap[currentChar] - 1;
            }
            struct Letter letter;
            letter.name = currentChar;
            letter.count = count;
            charList[charListIdx++] = letter;
        }
    }

    // 对结构体数组按照自定义比较函数进行排序
    qsort(charList, charListIdx, sizeof(struct Letter), compare);

    // 创建结果字符串数组,并将排序后的字符及其出现次数转换为输出格式
    char result[1000];
    int resultIdx = 0;
    for (int i = 0; i < charListIdx; i++) {
        result[resultIdx++] = charList[i].name;
        result[resultIdx++] = '0' + charList[i].count; // 将数字转换为字符形式
    }
    result[resultIdx] = '\0'; // 结束结果字符串

    // 输出摘要字符串
    printf("%s\n", result);

    // 释放内存
    free(charList);

    return 0;
}