C语言中的压缩程序

C语言中的压缩程序,c,run-length-encoding,C,Run Length Encoding,我想压缩一系列字符。例如,如果我键入 输入:FFFFF BBBBB CCBBBAABBBGGGSSS(27 x 8位=216位) 输出:F5B7C2B3A2B2G5S3(14 x 8位=112位) 到目前为止,这就是我所拥有的,我可以计算数组中的字符数。但最重要的任务是按相同的顺序计算它们。我似乎无法理解:( 几周前我开始学习C语言,我对数组、指针和ASCII值都很了解 但无论如何,我似乎无法按顺序计算这些字符。我尝试了所有的方法。这种方法不好,但它是我最接近的方法 #include <s

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

输入:FFFFF BBBBB CCBBBAABBBGGGSSS(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);

 }
#包括
#包括
int main()
{
int charcnt=0,dotcnt=0,commacnt=0,blankcnt=0,i,countA,countB;
char-str[125];
printf(“******字符串操作******\n\n”);
printf(“输入字符串\n\n”);
scanf(“%[^'\n']s”,str);
printf(“\n\n输入的字符串是\%s\”\n,str);
对于(i=0;str[i]!='\0';i++)
{
//计数异常字符
如果(str[i]='')
blankcnt++;
如果(str[i]='.')
dotcnt++;
如果(str[i]==',')
commacnt++;
如果(str[i]=='A'| | str[i]=='A')
countA++;
如果(str[i]=='B'| | str[i]=='B')
countA++;
}
//打印计数结果
charcnt=i;
printf(“\n\n总字符数:%d”,字符数);
printf(“\n总空白:%d”,空白cnt);
printf(“\n总句号:%d”,dotcnt);
printf(“\n总逗号:%d\n\n”,逗号);
printf(“A%d\n”,countA);
}

设置一个计数器。在for循环中扫描数组。只要数组具有相同的字符序列,只要字符序列中断,就不断增加计数。将计数设置为上一个字符的压缩数,并将计数设置为0,以便为下一个序列再次添加。要检查序列,只需在能够保存最后一个数组项的值,并将其与下一个循环中的下一个数组项进行比较,以查看序列是否中断


这是一个O(n)算法,应该使用。

您尝试执行的操作称为

我认为,如果你的目标是简单地压缩字符串,那么计算整个字符,特别是任何特定字符(如点、逗号、空格)的数量是一种不必要的干扰。因此,现在让我们忽略这一点

下面是如何方便地对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的运行不会被压缩。这在解压缩时很容易检测到,并确保压缩的字符串永远不会比原始字符串长。例如,
    “ABBCDEF”
    压缩为
    “AB2CDEF”
    (而不是
    “A1B2C1D1E1F1”

  • 简化假设:超过9个字符的运行将被压缩成若干段。这确保了运行长度始终可以用单个ASCII数字表示。例如,
    “aaaaaaaaaaaaaabbb”
    压缩为
    “A9A3B4”
    ,如果您需要输出为
    “A12B4”
    ,这并不困难。删除
    运行长度==9
    比较,并展开
    运行长度>1
    下的代码,以使用
    物联网
    进行字符串渲染


  • 我觉得你好像把两个问题混在一起了

    正如@Darren所指出的,第一个被称为:寻找一个相同字节的序列,用一个字节替换它们,然后重复计数。第二个,据我所知,是计算字符串中出现的一些“特殊”字符的数量

    运行长度编码

    我将给出一个不同于@Darren的RLE实现。就像他的解决方案一样,我的解决方案不处理作业的“特殊字符”部分。我将从

    void
    rll_encode(char *in, char *out)
    {
        while (*in != '\0') {
            int len = find_run(in);
            out = emit_run(out, *in, len);
            in = in + len;  // advance the input
        }
        *out = '\0';
    }
    
    这是运行长度编码的框架:通过输入查找运行,然后将这些运行发送到输出,并进行适当编码。此循环由三个步骤组成:

  • find_run
    函数将查找从输入中的当前位置开始的最长允许运行时间,该位置由中的
    指向。它返回该运行时间的长度,该长度将始终大于零
  • 类似地,
    emit\u run
    接受字符和重复计数,并在输出缓冲区中生成正确的编码。它返回要在输出缓冲区中使用的下一个位置
  • 发出run之后,我们将指针推进输入缓冲区
    len
    字节,并重复循环
  • 循环完成后,我们将NUL字节附加到输出缓冲区,以便它形成有效字符串。在任何类型的实际压缩器中,最后一步都不会完成,并且输入和输出缓冲区都有与其相关的大小

    剩下的只有实际实现
    find_-run
    emit_-run
    。让我们从
    emit_-run
    开始,因为它更简单:

    char *
    emit_run(char *out, char c, int len)
    {
        *out++ = c;
        *out++ = '0' + len;
        return out;
    }
    
    这将输出一个缓冲区
    out
    ,一个字符
    c
    ,并与重复计数
    len
    相关联。例如,给定
    c='a'
    len==5
    ,它将
    C5
    附加到输出缓冲区

    这个函数有一个相当严重的问题。考虑字符串<代码>“ABCDE”< /C>:每一个字母都有一个重复计数,因此字符串被编码为<代码>“A1B1C1D1E1”< /代码>,这几乎不被压缩。

    int
    find_run(char *in)
    {
        char run_char = *in;
        int run_len = 0;
        for (;;) {
            char c = *in;
            bool run_ended = 
                c != *run_char || // catches '\0', too
                run_len == MAX_RUN;
            if (run_ended)
                break;
            run_len++;
            in++;
        }
        return run_len;
    }
    
    #include <stdio.h>
    #include <stdbool.h>
    #define MAX_RUN 9
    
    /* insert emit_run from above */
    /* insert find_run from above */
    /* insert rll_encode from above */
    
    int main(int argc, char **argv)
    {
        char out[1024];
        rll_encode(argv[1], out);
        printf("%s\n", out);
    }
    
        #include <stdio.h>
    
    extern compression_function(char arr[1000])
    
    {
       char current_char;
       int count, i,j=0,t=0,G=0,H=0, char_size=0;
       int original_length=0,com_number_length=0,compressed_length=0;
       int index=0;
    
        FILE* outputfile;
        FILE* processing;
    
       outputfile= fopen("C:\\Users\\Desktop\\output.txt","w");
       processing= fopen("C:\\Users\\Desktop\\processing.txt","w");
    
       if(outputfile == '\0' )
    { 
                    printf("Cannot Write To File!\n");
    
                    }        
    
    
    current_char = arr[0]; 
    count = 1; 
    i = 0; 
    
    printf("\n\nOUTPUT: ");
    //USING A WHILE LOOP
    while (arr[i] != '\0') 
    { 
    //'i' WILL BE INCREMENTED TO CHECK ALL THE CHAR IN THE ARRAY      
    
    i++;
    
    // CHECK IF THE CURENT CHAR IS THE SAME AS THE LAST ONE        
    if( arr[i] == current_char )
    {
    count++; 
    }
    
    //ELSE IF NO MORE CHAR IS SIMILAR, IT WILL PRINT THE COUNT RESULT RIGHT AWAY    
    else
    {
    if(count==1)
    { 
    //sprintf(output_array,"%c", current_char);             
    printf("%c", current_char);
    fprintf(outputfile,"%c", current_char);
    fprintf(processing,"%c", current_char);
    
    G++;
    }
    
    if(count>=2)
    {        
           printf("%c%d", current_char, count);
           fprintf(outputfile,"%c%d", current_char,count);
           fprintf(processing,"%c", current_char );
           }
    
    if (count>9)
    {
               j++;
               }
               if (count>99)
    {
               t++;
               }
    
    //REST ALL COUNT FOR THE SECOND DIFFRENT CHAR IN ARRAY
    
       current_char = arr[i]; 
       count = 1;
       char_size++;
    
    
    //BREAK THE LOOP WHEN CHAR IN ARRAY IS NULL       
       if( current_char == '\0' )
       {
    
               break;
    
               }   
        } 
        }
    
     original_length = strlen(arr);
     com_number_length=(char_size+j+t-G);
     compressed_length=(char_size+char_size+j+t-G);
    
     fclose(outputfile);
     fclose(processing);
    
     //CALLING FUNCTION-SIZE-CALCULATOR
    size_calculator(original_length,char_size,com_number_length,compressed_length);
    
    
               }
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char* compress(char* str) {
        int i;
        int z = 0;
        int k = 1;
        int size_str = strlen(str);
        char *compress_str = malloc(size_str + 1);
        if (size_str < 2) {
            return str;
        }
    
        for (i = 0; i < size_str; i++) {
            if (i == 0) {
                compress_str[z] = str[i];
            } else {
                if (str[i] == str[i-1]) {
                   compress_str[z] = str[i];
                   if ( k >= 9 && k < 99) {
                   k++;
                   compress_str[z + 1] = (k / 10) + 48;
                   compress_str[z + 2] =  (k % 10) + 48;
                   } else if (k >= 99) {
                       k++;
                       compress_str[z + 1] = (k / 100) + 48;
                       compress_str[z + 2] =  ((k / 10) % 10) + 48;
                       compress_str[z + 3] =  (k % 10) + 48;
                   } else {
                       k++;
                       compress_str[z + 1] = k + 48;
                   }
                } else {
                    if (k >= 10 && k < 100) {
                        z = z + 3;
                        k = 1;
                        compress_str[z] = str[i];
                    } else if  (k >= 100) {
                       z = z + 4;
                       k = 1;
                       compress_str[z] = str[i];
                    } else if (k > 1 && k <= 9) {
                        z = z + 2;
                        k = 1;
                        compress_str[z] = str[i];
                    } else if (k == 1){
                        z++;
                        compress_str[z] = str[i];
                    }
                }
            }
       }
       return compress_str;
    }
    
    int main() {
        char* res;
        char* str;
        str = (char *)malloc(10240 * sizeof(char));
        scanf("\n%[^\n]", str);
    
        res = compress(str);
        printf("%s\n", res);
        return 0;
    }