C中的压缩程序

标签 c run-length-encoding

我想压缩一系列字符。例如,如果我输入

输入:FFFFBBBBBBBCCBBBAABBGGGGGSSS(27 x 8 位 = 216 位) 输出:F5B7C2B3A2B2G5S3(14 x 8 位 = 112 位)

到目前为止,这就是我所拥有的,我可以计算数组中的字符数。但最重要的任务是按相同的顺序对它们进行计数。我似乎无法弄清楚:( 几周前我开始做 C,我了解数组、指针、ASCII 值 但无论如何似乎无法按顺序计算这些字符。我什么都试了一点。这种方法并不好,但它是我最接近它的方法。

#include <stdio.h>
#include <conio.h>

int main()
{

 int charcnt=0,dotcnt=0,commacnt=0,blankcnt=0,i, countA, countB;
 char str[125];



 printf("*****String Manipulations*****\n\n");
 printf("Enter a string\n\n");

 scanf("%[^'\n']s",str);


 printf("\n\nEntered String is \" %s \" \n",str);


 for(i=0;str[i]!='\0';i++)
 {

 // COUNTING EXCEPTION CHARS                         
 if(str[i]==' ')
    blankcnt++;

 if(str[i]=='.')
    dotcnt++;

 if(str[i]==',')
    commacnt++;

 if (str[i]=='A' || str[i]=='a')

  countA++;

      if (str[i]=='B' || str[i]=='b')

  countA++;

 }

 //PRINT RESULT OF COUNT
 charcnt=i;
 printf("\n\nTotal Characters : %d",charcnt);
 printf("\nTotal Blanks     : %d",blankcnt);
 printf("\nTotal Full stops : %d",dotcnt);
 printf("\nTotal Commas     : %d\n\n",commacnt);
 printf("A%d\n", countA);

 }

最佳答案

您要执行的操作名为 Run-Length Encoding .

我认为,如果您的目标只是对字符串进行游程压缩,则对所有字符的计数,特别是对任何特定字符(例如点、逗号、空格)的计数是不必要的干扰。所以让我们暂时忽略它。

这里是您可以轻松就地对 ASCII 字符串进行游程编码的方法。即原始字符串将被压缩后的字符串覆盖。这可能是也可能不是您想要的,但它节省了另一个缓冲区的分配并且易于编码。

char *compress(char *str) {
    char *start = str;
    char *c_first = str;
    char *c_last = str;
    char *c_write = str;
    int run_len = 0;
    while (*str) {
        ++c_last;
        ++run_len;
        if (!(*c_last) || *c_last != *c_first || run_len == 9) { 
            // end of run
            *(c_write++) = *c_first;
            if (run_len > 1)
                *(c_write++) = '0' + run_len;
            // start next run
            run_len = 0; 
            c_first = c_last;
        }
        ++str;
    }
    *c_write = 0;
    return start;
}

如果需要计算或排除任何特殊字符,您可以在 while 循环中轻松完成。

添加它以允许从命令行进行测试。使用您的原始字符串作为单个参数运行。

int main(int argc, char **argv) {
    if (argc != 2)
        return 1;
    printf("%s\n", compress(argv[1]));
    return 0;
}

您对输出的要求没有完全指定,所以我的假设是:

  1. 优化假设:长度为 1 的游程未被压缩。这在解压缩时很容易检测到,并确保压缩后的字符串永远不会比原始字符串长。例如“ABBCDEF” 压缩为 “AB2CDEF”(而不是 “A1B2C1D1E1F1”)

  2. 简化假设:超过 9 个字符的运行将被压缩成几个部分。这确保游程长度始终可以用单个 ASCII 数字表示。即 "AAAAAAAAAAAABBBB" 压缩为 "A9A3B4" 如果您需要输出为 "A12B4",这并不困难。删除 run_len == 9 比较并展开 run_len > 1 下的代码以使用 iota 进行字符串渲染。

关于C中的压缩程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19748991/

相关文章:

c - 执行的线程多于创建的线程

java - 游程编码程序问题

c - 打印正确数量的相同字符时出现问题。C 中的 RLE

c++ - 基于DCT的视频编码过程

c - 在 C 中,如何使用 dup2 将 STDOUT_FILENO 重定向到/dev/null,然后再重定向回其原始值?

c - 如何在C程序中从外部文件加载mruby代码?

c - 用 C 为单链表 API 设计函数原型(prototype)

c - C 枚举的大型 c2hs 推断大小

r - 我可以在不使用 inverse 的情况下获得 rle 对象的总长度吗?

c - C中的RLE算法