You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言字符串压缩代码调试:重复字符转[字符$次数]格式

字符串连续重复字符替换问题调试

问题描述

需要实现字符串处理任务:将字符串中连续重复的字符替换为「字符+$+重复次数」格式。

  • 输入示例:"aaa bbuvvvvo"
  • 期望输出:"a$3 b$2uv$4o"
  • 当前错误输出:"a$3 b$2v$4vo"

原代码

#include <stdio.h>
#include <string.h>
#define CAPACITY 255
#define MAX_NUMBER 10

void Output(char readFile[], char outputFile[], char string[]);
void changeString(char string[], char newString[]);

int main() {

    char readFile[CAPACITY];
    char outputFile[CAPACITY];
    char string[CAPACITY];

    // Input file's name
    printf("Iveskite teksto failo varda: ");
    scanf("%s", &readFile);

    // Output file's name
    printf("Iveskite teksto faila i kuri bus isvedamas atsakymas: ");
    scanf("%s", &outputFile);


    Output(readFile, outputFile, string);
    return 0;
}

// Scanning file
void Output(char readFile[], char outputFile[], char string[])
{
    char newString[CAPACITY];
    FILE *input, *output;
    input = fopen(readFile, "r");

    while(fscanf(input, "%s", string) != EOF)
    {
        changeString(string, newString);
        printf("%s\n", newString);
    }
}

// Changing string to wanted string
void changeString(char string[], char newString[])
{
    char number[MAX_NUMBER];
    int symbols = 0;
    int j;

    for(int i = 0; string[i] != '\0'; ++i)
    {
        int temp = i;
        newString[i] = string[i];
        if(newString[i] == string[i + 1])
        {
            j = i;
            while(string[j] == string[i])
            {
                ++symbols;
                ++j;
            }
            // Changing int to char
            sprintf(number, "%d", symbols);
            newString[i + 1] = '$';
            i += 2;
            newString[i] = number[0];
            symbols = 0;
        }
    }
}

错误原因分析

  1. 索引管理混乱:同时用原字符串的i索引操作新字符串,导致新字符串写入位置错位,处理完重复字符后残留原字符串的多余字符(比如示例中的最后一个v)。
  2. 重复次数计算错误:用symbols计数器初始值为0,循环自增后得到的次数比实际少1,且逻辑冗余。
  3. 未处理多位数次数:仅取数字字符串的第一位,若重复次数超过9会丢失后续数位。
  4. 新字符串未终止:未添加'\0'终止符,输出可能出现乱码或残留旧数据。
  5. 文件读取逻辑缺陷:fscanf("%s")会跳过空格,无法处理带空格的输入;未处理文件打开失败的情况;未将结果写入输出文件。
  6. scanf参数错误:数组名本身是地址,无需加&,原代码中scanf("%s", &readFile)属于错误用法。

修复后的代码

#include <stdio.h>
#include <string.h>
#define CAPACITY 255
#define MAX_NUMBER 10

void Output(char readFile[], char outputFile[], char string[]);
void changeString(char string[], char newString[]);

int main() {
    char readFile[CAPACITY];
    char outputFile[CAPACITY];
    char string[CAPACITY];

    // 输入文件名
    printf("Iveskite teksto failo varda: ");
    scanf("%s", readFile);

    // 输出文件名
    printf("Iveskite teksto faila i kuri bus isvedamas atsakymas: ");
    scanf("%s", outputFile);

    Output(readFile, outputFile, string);
    return 0;
}

// 读取文件并处理输出
void Output(char readFile[], char outputFile[], char string[]) {
    char newString[CAPACITY];
    FILE *input = fopen(readFile, "r");
    if (!input) {
        perror("Failed to open input file");
        return;
    }

    FILE *output = fopen(outputFile, "w");
    if (!output) {
        perror("Failed to open output file");
        fclose(input);
        return;
    }

    // 读取整行保留空格,处理换行符
    while (fgets(string, CAPACITY, input) != NULL) {
        size_t len = strlen(string);
        if (len > 0 && string[len-1] == '\n') {
            string[len-1] = '\0';
        }
        changeString(string, newString);
        printf("%s\n", newString);
        fprintf(output, "%s\n", newString);
    }

    fclose(input);
    fclose(output);
}

// 转换字符串格式
void changeString(char string[], char newString[]) {
    int i = 0; // 原字符串遍历索引
    int k = 0; // 新字符串写入索引
    int len = strlen(string);

    while (i < len) {
        char current = string[i];
        int count = 1;

        // 统计连续重复次数
        while (i + count < len && string[i + count] == current) {
            count++;
        }

        // 写入当前字符
        newString[k++] = current;

        // 重复次数大于1时,写入$和次数
        if (count > 1) {
            newString[k++] = '$';
            char num_str[MAX_NUMBER];
            sprintf(num_str, "%d", count);
            strcpy(&newString[k], num_str);
            k += strlen(num_str);
        }

        // 跳到下一个不同字符的位置
        i += count;
    }

    // 添加字符串终止符
    newString[k] = '\0';
}

修复点说明

  • 分离索引管理:用i遍历原字符串,k独立管理新字符串的写入位置,避免索引冲突。
  • 简化次数计算:通过i + count直接遍历统计重复次数,逻辑更简洁准确。
  • 支持多位数次数:用strcpy完整写入数字字符串,处理次数大于9的场景。
  • 添加终止符:确保新字符串符合C语言字符串规范。
  • 修复文件操作:用fgets读取整行保留空格;增加错误处理;实现结果写入输出文件。
  • 修正scanf参数:去掉数组名前的多余&。

内容的提问来源于stack exchange,提问作者Kurbamit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 23:15:53