【解決方法】ファイルの圧縮と解凍と C


みなさん、こんにちは。独自のデータ コンプレッサーとデコンプレッサーを作成しようとしています。ここでいくつかの投稿を見て、それらを変更しようとしましたが、問題があります。

それを圧縮するファイルのtrial.txtプログラムを作成したとしましょうが、多くの00 00 00 00を追加すると、圧縮バージョンが元のものよりも大きくなります。
だから私が欲しいのは、プログラムが圧縮および解凍されたバージョンをtxtとして保存する優れた圧縮ロジックです。 ハフマンアルゴリズムを試してみましたが、うまくいきませんでした。

私のコードは以下の通りです。 「ncurses.h」ライブラリが機能しない場合、コンパイラでエラーが発生する場合があります。「conio.h」も削除して追加できます

+++update 以下のようにコードを修正しました。問題は 1 つだけです。たとえば、解凍関数がメッセージの最後の文字を取得しません。

メッセージ: Hello World
圧縮された A0 B3 DD …
解凍: Hello World

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


void Compression(unsigned char *sizeOut, const char *Message_size) {  
    
	unsigned long long Buffer = 0;  
	char Bits = 0;
	
	while (*Message_size != 0) {
		Buffer |= (unsigned long long)(*Message_size++) << Bits;
		Bits += 7;
		if (Bits == 7 * 8) { 
			while (Bits > 0) {
				*sizeOut++ = Buffer;
				Buffer >>= 8;
				Bits -= 8;
			}
			Bits = 0;
			Buffer = 0;
		}
	}
	while (Bits > 0) {
		*sizeOut++ = Buffer;
		Buffer >>= 8;
		Bits -= 8;
	}
}


void Decompression (char *Out_size, const unsigned char *Compressed_size, unsigned CompressedLength) {
    
	unsigned long long Buffer = 0;
	char Bits = 0;
	while (CompressedLength) {
		while (CompressedLength && Bits < 7 * 8) {
			Buffer |= (unsigned long long)*Compressed_size++ << Bits;
			Bits += 8;
			--CompressedLength;
		}
		while (Bits > 0) {
			*Out_size++ = Buffer & 0x7F;
			Buffer >>= 7;
			Bits -= 7;
		}
		
		Bits = 0;
		Buffer = 0;
	}
}


int main(void) {
    
    
    
    
    int letters;
    
    printf("Creator: Ceyhun Kivanc Demir, data compressor and decompressor\n\n");
    
    
    
    
    
    FILE *file;
    char filename[100]="";	
    printf("\n\nPlease Enter the name of file: ");
    scanf("%99s",filename);
    file=fopen(filename,"r");
    if(file==NULL){
		printf("\n%s File not found.\n\n",filename, strerror(errno));
		exit(1);
	}
	
	    
    
   
    fseek(file, 0, SEEK_END);
    long count = ftell(file);
    fseek(file, 0, SEEK_SET);
    
    
    
    char Message[count];
    
    
    fread(Message, strlen(Message)+1, count, file);  
    Message[count]='\0';
    
	
	unsigned CompressedSize = sizeof(Message)*7/8; 
	unsigned char CompressedBytes[CompressedSize]; 
	char DecompressedSize[sizeof(Message)];
	
	
	
	printf("\nMessage: %s\n", Message);
	Compression(CompressedBytes, Message);
	printf("char number of message: %d\n", strlen(Message));
	printf("\nCompressed version: ");
	for (int Byte = 0; Byte < CompressedSize; ++Byte) {
		printf("%02X ", CompressedBytes[Byte]);
	}
	printf("\n");
	
	
	Decompression(DecompressedSize, CompressedBytes, CompressedSize);
	DecompressedSize[sizeof(Message)] = 0; 
	
	printf("\nDecompressed version: %s\n", DecompressedSize);
	printf("char number of message: %d\n", strlen(DecompressedSize));
	
	if (strcmp(Message, DecompressedSize) == 0) {
		printf("\nCompression done.\n");
	} else {
		printf("\nCompression crushed!\n");
	}
	fclose(file);
	return 0;
}

私が試したこと:

hufman アルゴリズム、ファイル保存、圧縮、解凍

解決策 1

これを見てください:

int count;
/* assign a value to count */
char Message[count];  /* creates a buffer of  size count */

/* ... a bit later */
unsigned CompressedSize = sizeof(Message)*7/8;

実行時に決定されるサイズでスタック上に配列を作成することは、GNU 拡張機能です。 それが間違っていると言っているわけではありませんが、注意すべき点がいくつかあります。
1) もし count が最大スタック サイズより大きい場合、既にスタックにある他の変数が破損する可能性があります。 使ったほうがいいかも malloc/free Message 変数を作成します。
2) Message 変数のサイズは、入力ファイルのサイズに基づいて実行時に設定されます。 しかし sizeof 演算子はで計算されます コンパイル 時間。 コンパイル時には配列のサイズがわからないため、 sizeof(Message) に評価されます sizeof(char *). これは、CompressedSize の値が間違っていることを意味します。
3) ポータブルではありません。 おそらくclangはこれをサポートしていると思いますが、MSVCがサポートしていないことは確かです。 それは、今も後も、あなたにとって問題になるかもしれませんし、ならないかもしれません。

余談ですが、このコードは

while( (letters = fgetc(file)) != EOF) {
  count++;
} 
fseek(file, 0, SEEK_SET);

で置き換えることができます

fseek(file, 0, SEEK_END);
long count = ftell(file);
fseek(file, 0, SEEK_SET);

この方法では、ファイル内の各バイトの読み取りに時間を費やす必要がなく、変数「文字」が不要になるため、(少量の) スペースを節約できます。

解決策 2

あなたのコードは今動いていますか?

コメント

タイトルとURLをコピーしました