Задача: Кодирование текстовых данных (файлов), побитовое кодирование

  • Автор темы Again
  • Дата начала
Статус
Закрыто для дальнейших ответов.
A

Again

#1
Постановка задачи
В этой задаче предполагается использование побитовых операций. Данные вводятся из файла на диске и выводятся в файл и на экран. Имена входного и выходного файлов задаются в командной строке.

При выполнении этой задачи необходимо:
1. При открытии или создании любых файлов необходимо проверять наличие ошибок ввода-вывода.
2. Результат выполнения задания должен быть представлен в наглядной форме, например:

Результат объединения значений
65535 = 11111111 11111111
1 = 00000000 00000001 операцией поразрядное И (&) равна
1 = 00000000 00000001

Условие задачи:
Составить программу, кодирующую текстовый файл, путем перестановки первого и последнего битов в байте, 2-го и предпоследнего и т.д. Предусмотреть возможность декодирования. Для кодирования символа составить функцию.
 

DarkKnight

Well-known member
01.08.2010
653
0
#2
Хочется увидишь ваши начинания (код, теорию по теме)...
Примерно по факту именно в вашу тему смогу ответить не ранее (понедельник, вторник)...
 
A

Again

#3
C++:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void kod( char *d, char *s )
{
int	i;
for ( i = 0; i < strlen( s ); i++ ) {
d[i] = s[i] ^ 0x19;
}
}

void main()
{
int i;
char *d;
char *s = "one two three four five six seven";

d = (char *)malloc( strlen( s ) );
kod( d, s );

printf( "%s\n", s );
for ( i = 0; i < strlen( s ); i++ ) {
printf( "%c", d[i] );
}
printf( "\n" );
}
Это выполняеться в памяти, а мне нужно в файле...
 

DarkKnight

Well-known member
01.08.2010
653
0
#4

DarkKnight

Well-known member
01.08.2010
653
0
#5
2Again : Кстати, Эгейн, а в задачи можно пользоваться и бинарными операциями и обычными??? Или только бинарными...
Я что то прям задумался... Просто первое что на ум пришло это сравнение
например наш символ char a;
тогда
итерация 1:
множитель b = 2^7 = 128
множитель c = 2^0 = 1;
C++:
if (a&b == a&c ){;} //Если нули ничего не меняем
else if (a&b > 0 && a&c>0) {;} //Если единицы опять же ничего не меняем
else //Различны то тут же
{
a = a^b; //Ивертируем
a = a^c;
}
так можно???? Или все же чисто-чисто бинарными операциями???
 

lazybiz

Well-known member
03.11.2010
1 339
0
#7
DarkKnight125
Будь проще:facepalm:
C++:
	c ^= 0x81, c ^= 0x42, c ^= 0x24, c ^= 0x18;
Собственно, реверс битов в байте.
 

DarkKnight

Well-known member
01.08.2010
653
0
#8
C++:
#include <stdio.h>
#include <conio.h>
#include <locale.h>

//Функция кодирования (ну и декодирования само собой), т.к. она обратимая
unsigned char CodeAndDecode(unsigned char b)
{
//Т.к. в байте (8бит), то для замены нам нужно 4 итерации
for (int i = 0; i<4; i++)
{
/* ЭТО Я ДЛЯ НАГЛЯДНОСТИ ОСТАВИЛ, ЧТО БЫ ПОНЯЛ КАК ИМЕННО ФОРМИРУЕТСЯ ИТОГОВОЕ УСЛОВИЕ
//Если байты равны нулю
if ( (b&(1<<(7-i))) == (b&(1<<i)) )
{
printf("Биты равны (0), итерация %i, биты %i и %i\n",i+1,i+1,8-i);
}
//Если байты равны единицы
else if ( (b&(1<<(7-i))) > 0 && (b&(1<<i)) > 0)
{
printf("Биты равны (1), итерация %i, биты %i и %i\n",i+1,i+1,8-i);
}
//Иначе нужно менять местами (биты разные)
else 
{
//Если не то не другое инвертируем байты
b = b^(1<<(7-i));
b = b^(1<<i);

}
*/
//Тоже самое но короче
if (!((b&(1<<(7-i))) == (b&(1<<i))) && !((b&(1<<(7-i))) > 0 && (b&(1<<i))>0))
{
b = b^(1<<(7-i));
b = b^(1<<i);
}
}
return b;
}

//Главная функция
int main(int argc, char *argv[])
{
setlocale(LC_ALL,".1251");
int i; //Для цикла... Я просто хз понимает ли C++ определение в цикле тип for (int i = 0....
FILE *FileIn, *FileOut; //Файловые дескриптов

//Я буду работать со статическими именами файлов, ты потом уже сам вытащишь из командой строки нужные имена и вставишь в код

FileIn = fopen("InCode.txt","r+"); //Файл из которого получаем данные (обычные текстовые данные)
if (!FileIn)
{
printf("Ошибка открытия файла для чтения данных");
return 10;
}

FileOut = fopen("OutCode.txt","w+"); //Файл в который пишим кодированные данные
if (!FileOut)
{
printf("Ошибка открытия файла для записи данных");
return 11;
}


unsigned char buffer; //Буфер для 1 байта (я там ниже массив еще ввел, что бы вывод красивее был)
printf("Кодирование текста : \n");
//Пока не достигнут конец файла, читаем побайтно
while (!feof(FileIn))
{
fread((void*)&buffer,sizeof(unsigned char),1,FileIn); //Читаем
fprintf(FileOut,"%c",CodeAndDecode(buffer)); //Пишим в файл сразу (выходной файл)
printf("%c - %c\n",buffer,CodeAndDecode(buffer)); //Выводим на экран ОРИГИНАЛ - КОДИРОВАНИЕ
}
fclose(FileIn); //Закроем текущие дескриптеры
fclose(FileOut); 
//Откроем только что записанный файл...
//для наглядности вывода создадим массив на 10000 (без динамики)
unsigned char Arr[10000] = {0}; //Вот он, как раз все прочитаем в него и выведим строка к строке
FileIn = fopen("OutCode.txt","r+"); //Откроем для чтения тот файл, в который только что записали кодир. текст
if (!FileIn)
{
printf("Ошибка открытия файла для чтения данных");
return 11;
}
int kol =0; //Кол-во прочитанных данных из файла
while (!feof(FileIn))
{
kol = fread((void*)Arr,sizeof(unsigned char),10000,FileIn); //Прочитаем все в массив
}
printf("\nКодированный текст: \n");
for (int i = 0; i<kol; i++)
printf("%c",Arr[i]);
printf("\nДекодированный текст: \n");
for (int i = 0; i<kol; i++)
printf("%c",CodeAndDecode(Arr[i]));
return 0;
}
 

Вложения

DarkKnight

Well-known member
01.08.2010
653
0
#9
DarkKnight125
Будь проще:facepalm:
C++:
	c ^= 0x81, c ^= 0x42, c ^= 0x24, c ^= 0x18;
Собственно, реверс битов в байте.
Не, насчет реверса не согласен, простая инверсия... (было 255 стало 0)
Проверка все равно нужна.. Мы же инвертировать будем только то, где различия есть 0-1 или 1-0....
но выглядит красивее чем мои 1<<7; ;-)
 

lazybiz

Well-known member
03.11.2010
1 339
0
#10
DarkKnight125
Погоди.. Я по-моему там что-то упустил... Мне необходимо подумать.

Добавлено: Но ты, по-моему, все-равно немного усложнил... Сейчас подумаю.
 

lazybiz

Well-known member
03.11.2010
1 339
0
#11
DarkKnight125
А так не проще:welcome:
C++:
char reverse( char c )
{
int	i;
char	v = 0;
for ( i = 0; i < 8; i++ ) {
v |= ((c >> i) & 1) << (7 - i);
}
return v;
}
 

lazybiz

Well-known member
03.11.2010
1 339
0
#12
Проще некуда.
reverse - операция обратимая, т.ч. она и кодирует, и раскодирует.
C++:
#include <stdio.h>

char reverse( char c )
{
int		i;
char	v = 0;
for ( i = 0; i < 8; i++ ) {
v |= ((c >> i) & 1) << (7 - i);
}
return v;
}

void main( int narg, char **arg )
{
int		i, n;
FILE *	fp_in;
FILE *	fp_out;

if ( narg != 3 ) {
printf( "main.exe in_file out_file\n" );
return;
}

fp_in = fopen( arg[1], "rb" );
fp_out = fopen( arg[2], "wb+" );

fseek( fp_in, 0, SEEK_END );
n = ftell( fp_in );
fseek( fp_in, 0, SEEK_SET );

for ( i = 0; i < n; i++ ) {
fputc( reverse( fgetc( fp_in ) ), fp_out );
}

fclose( fp_out );
fclose( fp_in );
}
 

lazybiz

Well-known member
03.11.2010
1 339
0
#13
Чуть попроще:
C++:
#include <stdio.h>

char reverse( char c )
{
int		i;
char	v = 0;
for ( i = 0; i < 8; i++ ) {
v |= ((c >> i) & 1) << (7 - i);
}
return v;
}

void main( int narg, char **arg )
{
int		c;
FILE *	fp_in;
FILE *	fp_out;

if ( narg != 3 ) {
printf( "main.exe in_file out_file\n" );
return;
}

fp_in = fopen( arg[1], "rb" );
fp_out = fopen( arg[2], "wb+" );

while ( (c = fgetc( fp_in )) != EOF ) {
fputc( reverse( c ), fp_out );
}

fclose( fp_out );
fclose( fp_in );
}
 
Статус
Закрыто для дальнейших ответов.