Поиск:

Ответ в темуСоздание новой темы Создание опроса
> VS2010 выдаёь ошибку "необработанное исключение" 
V
    Опции темы
Асоишница
Дата 14.3.2013, 00:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 45
Регистрация: 13.3.2012

Репутация: нет
Всего: нет



При компиляции выдаёт:
Необработанное исключение в "0x008c16dc" в "oit3архивация.exe": 0xC0000005: Нарушение прав доступа при чтении "0x008cf01c".

ссылается на строчку в процедуре CODER()
while (c != mass[i].simv) //находим символ в массиве mass

вот код:
Код

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <math.h>

/*объявляем структуру*/
typedef struct byte
{
        int simv;//номер символа из таблицы ASCII
        char code[30];//код символа, полученный в Лаб №2
} BYTE;

BYTE mass[256];//массив, элементы которого - структуры
int n; //количество байт в исходном файле
char filename[30], //имя исходного или разархивированного файла
     tablename[30],//имя файла с таблицей кодов
     arhname[30]; //имя архива
FILE *tablep, *filep, *arhp;//указатели на таблицу, файл, архив

void CODER();
int DECODER();
void READ();
void CLEAR();
void BIN(char buf[], int c);
void F(char code[], char a);

void main()
{
        int b = 0;
        while ( b != 1)
        {
                system("cls");
                /*вывод меню на экран*/
                printf("1. Coder\n2. Decoder\n3. Exit\n");
                int x = getch();
                switch (x)
                {
                        case '1': CODER(); break;
                        case '2': DECODER();break;
                        case '3': b = 1; break;
                        default: break;
                }
        }
}
/*процедура архивирует файл*/
void CODER()
{
  CLEAR();//очистка массивов
  /*ввод имён файлов и их открытие*/
  printf("Filename: ");
  scanf("%s", filename);
  filep = fopen(filename, "rb");
  printf("Arhive name: ");
  scanf("%s", arhname);
  arhp = fopen(arhname, "wb");
  READ(); //считываем таблицу кодов из файла
  int c; //считанный символ
  char byte[9];//один байт в двоичной с.с., его будем записываеть в архив
  memset(byte, '\0', 9);//заполняет первые 9 байт буфера byte символом '/0' 
  while ((c = fgetc(filep)) != EOF)//пока не обнаружится конец файла, считываем символ
  {
        n--;
        int i = 0;
        while (c != mass[i].simv) //находим символ в массиве mass
                i++;
        int j = 0;
        do //выполняем цикл
        {
                byte[strlen(byte)] = mass[i].code[j];//добавляем j-й бит кода символа в конец byte
                if((strlen(byte) == 8) || ((n == 0) && (mass[i].code[j+1] == '\0')))//если один байт собран
                {
                        /*переводим 8 бит в двоичную с.с.*/
                        int byte1 = 0;
                        for(int k=0; k<=7; k++)
                        {
                                if(byte[k] == '1')
                                        byte1 += pow(2.0,(7-k));
                        }
                        fputc(byte1, arhp);//записываем в архив
                        memset(byte, '\0', 8);//очищаем массив byte
                }
                j++;
        }
        while(mass[i].code[j] != '\0');//пока не переберём все биты кода
  }
  fclose(filep);
  fclose(arhp);
}
//процедура разархивации
int DECODER()
{
  CLEAR();//очистка массивов
  printf("Arhive name: ");
  scanf("%15s", arhname);
  arhp = fopen(arhname, "rb");
  printf("Filename: ");
  scanf("%15s", filename);
  filep = fopen(filename, "wb");
  READ(); //считываем таблицу кодов из файла
  char buf[30], buf1[30];
  memset(buf, '\0', 30);//заполняем первые 30 байт буфера buf символом '/0'
  int c = 0;//считанный байт
  int n1 = 0;//количество байт в разархивированном файле
  while ((c = fgetc(arhp)) != EOF) //пока не обнаружится конец архива
  {
        BIN(buf, c);//переводим символ в двоичную с.с. и записываем в byte
        unsigned int i = 1;
        while(i <= strlen(buf))//пока i не достигнет размера буфера
        {
                if(n1 >= n)/*если размер разархивированного файла равен размеру исходного файла*/
                        return 0;//завершаем работу
                memset(buf1, '\0', 30); //заполняем первые 30 байт буфера buf1 символом '/0'
                strncpy(buf1, buf, i);//копируем i элементов из buf в buf1
                /*перебираем массив с таблицей кодов*/
                for(int j=0;j<=255;j++)
                        if(strcmp(mass[j].code, buf1) == 0)//если код j-го символа из массива совпал с кодом buf1
                        {
                                fputc(mass[j].simv, filep);//записываем j-ый символ в файл
                                n1++;//размер файла увеличился на 1 байт
                                /*удаляем записаные биты из буфера*/
                                for(unsigned int k=i; k<=(strlen(buf)+2); k++)
                                        buf[k-i] = buf[k];
                                i = 0;
                                break;
                        }
                i++;
        }
  }
  fclose(filep);
  fclose(arhp);
  return 0;
}
/*процедура считывает таблицу кодов из файла*/
void READ()
{
        printf("Table-> ");
        scanf("%s", tablename);
        tablep = fopen(tablename, "rb");
        fscanf(tablep, "%s", mass[0].code);
        fscanf(tablep, "%d", &n);
        int i = 0;
        while(!feof(tablep)) //пока не обнаружится конец таблицы
        {
                /*считываем таблицу*/
                fscanf(tablep, "%d\n", &mass[i].simv);
                fscanf(tablep, "%s", mass[i].code);
                i++;
        }
        fclose(tablep);
}
//процедура очищает массивы
void CLEAR()
{
        memset(filename, '\0', 15);
        memset(tablename, '\0', 15);
        memset(arhname, '\0', 15);
        for(int i=0; i<=255; i++)
        {
                mass[i].simv = 0;
                memset(mass[i].code, '\0', 30);
        }
}
/*добавляет двоичное представление с в конец buf*/
void BIN(char buf[], int c)
{
        char code[30];
        memset(code, '\0', 30);
        int Q = c;
        int ost = 0;
        while((Q != 0))
        {
                ost = Q%2;
                Q /= 2;
                F(code, (ost + 48));
        }
        while(strlen(code) < 8) //пока размер массива code < 8
                F(code, 48); //48 - ASCII код "0"
        strcat(buf, code); //дописываем код в буфер 
}
/*добавляет 0 или 1 в начало массива code*/
void F(char code[], char a)
{
        char buf[30];
        buf[0] = '\0';
        strcpy(buf, code);//копирует код в буфер
        code[0] = a;
        code[1] = '\0';
        strcat(code, buf); //дописывает буфер в код
}
 


Код делает следующее:
Есть текстовый файл. есть таблица кодов его символов, получена методом хафмена. Нужна заархивировать, а потом разархивировать файл.

Сжатие:  читаем текстовый файл.считали букву а. смотрим её код в файле кодов хафмена. пусть будет 00101
записали в массив из 8 чисел. осталось 3 позиции, считываем след. букву б: 0110. записываем получили:
00101011 0
т.е. один бит в следующую 8-ку переходит(байт).
дешифровка аналогично: считали бит: 0- ищем код, если нет, считываем следудющий бит байта......прошли все 8 бит, считываем след. байт и к оставшимся с прошлого байта битам дописываем по одному биту пока не наберётся код, который есть в таблице кодов, чтобы заменить его на букву.

например, наш файл кодов хафмена содержит коды:
а - 11001
б - 11011
1) рассматриваем, например, первых два байта из архивированного файла. допустим первые два байта нашего заархивированного файла такие:
11001110|1111001|
2) сравниваем каждый код из файла кодов файла побитово(смотрим, есть ли такой код в таблице)- сравниваем c 1-битом 1-го байта из файла. совпадает. 2-ой-совпадает. 3-ий совпадает. 4-ый. ..упс. облом. - не совпадает! тогда переходим к след. коду и начинаем заново сравнивать с 1-ым битом 1-го байта: 1-ый-совпадает. 2-ой-совпадает... как видно все совпали- смотрим, что это буква б. т.е. расшифровали:
б110|11110010|
далее начиая с 6-го бита дальше в таком же духе продолжаем, сравнивая 3 бита из первого байта и если совпало, переходим далее к сравнению битов второго байта.

При запуске вводить следующее:
1(CODER):
имя файла, который надо закодировать(text32.txt)-прилагается в архиве
файл, в который записываются коды(допустим hhh.arh)
имя файла с таблицей кодов хафмена(txt32.haf)-прилагается в архиве
2(DECODER):
имя закодированного файла(hhh.arh)
имя файла, в который запишем "раскодирование "(пусть будет text!!!.txt)
имя файла с таблицей кодов хафмена(txt32.haf)-прилагается в архиве


Присоединённый файл ( Кол-во скачиваний: 0 )
Присоединённый файл  Archive.rar 7,59 Kb
PM MAIL   Вверх
Earnest
Дата 14.3.2013, 08:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Это исключение означает ровно то, что написано: обращение к невыделенной памяти. Скорее всего, у тебя проблемы с адресацией массива, т.е. индекс неправильный. 


--------------------
...
PM   Вверх
feodorv
Дата 14.3.2013, 11:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 1
Всего: 45



Цитата(Earnest @  14.3.2013,  09:28 Найти цитируемый пост)
Скорее всего, у тебя проблемы с адресацией массива, т.е. индекс неправильный. 

Однозначно. Смотрим:
Цитата(Асоишница @  14.3.2013,  01:20 Найти цитируемый пост)
BYTE mass[256];//массив, элементы которого - структуры

Цитата(Асоишница @  14.3.2013,  01:20 Найти цитируемый пост)
        while (c != mass[i].simv) //находим символ в массиве mass
                i++;

В цикле нет проверки на i < 256, и если c не найдено, то i может стать большим или равным 256, что как раз и означает выход за пределы массива.
Что будет, если символ не найден в таблице? Или предполагается, что такого быть не может?
Почему c не найден - другой вопрос. Может, его в таблице нет, может, таблица неправильно считывается. Смотрим:
Цитата(Асоишница @  14.3.2013,  01:20 Найти цитируемый пост)
        int i = 0;
        while(!feof(tablep)) //пока не обнаружится конец таблицы
        {
                /*считываем таблицу*/
                fscanf(tablep, "%d\n", &mass[i].simv);
                fscanf(tablep, "%s", mass[i].code);
                i++;
        }

Та же ситуация: нет проверки индекса i на значение 256. Нет и гарантии, что охвачены все 256 ASCII и расширенных символов. Считанную таблицу нужно распечатать и проверить...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Dem_max
Дата 14.3.2013, 12:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1780
Регистрация: 12.4.2007

Репутация: 1
Всего: 39



Выход за пределы массива


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
Асоишница
  Дата 14.3.2013, 16:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 45
Регистрация: 13.3.2012

Репутация: нет
Всего: нет



Всем спасибо. Действительно прошляпила проверку на выход за пределы массива. Правда некорректно работает
в полученном разархивированном файле в .txt начало каждой строки не то(( а .bmp вообще не открывается- ошибка
Зато с .doc , .docx , .jpg и даже с .rar всё отлично. В чём тут дело.....

Это сообщение отредактировал(а) Асоишница - 14.3.2013, 17:20
PM MAIL   Вверх
feodorv
Дата 14.3.2013, 18:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 1
Всего: 45



Ну, не знаю. Все вычисления - целочисленные, зачем такое писать:
Цитата(Асоишница @  14.3.2013,  01:20 Найти цитируемый пост)
                        for(int k=0; k<=7; k++)
                        {
                                if(byte[k] == '1')
                                        byte1 += pow(2.0,(7-k));
                        }

Вот зачем здесь арифметика с плавающей точкой??? 2 в степени k есть (1 << k), то есть побитовый сдвиг единички на k позиций влево.

К сожалению, очень трудно разбирать Ваш код. И очень не нравится строковое побитовое представление, чем unsigned int не угодил?


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Асоишница
Дата 14.3.2013, 19:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 45
Регистрация: 13.3.2012

Репутация: нет
Всего: нет



feodorv, 2 с точкой- это чтоб компилятор не ругался на перегруженность функции. 
А как с побитовым сдвигом это сделать?

Добавлено через 5 минут и 9 секунд
ошибку нашла- она была в обрабатываемом файле с кодами. вернее она была в предыдущей лабе, а я её не сразу заметила- код исправила, а файлы не переделала.
PM MAIL   Вверх
feodorv
Дата 14.3.2013, 21:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 1
Всего: 45



Цитата(Асоишница @  14.3.2013,  20:08 Найти цитируемый пост)
2 с точкой- это чтоб компилятор не ругался на перегруженность функции. 

Ну так тут что 2 с точкой, что без точки. pow всё равно рассматривает аргумент как число с плавающей точкой. И всё равно возвращает double.

Цитата(Асоишница @  14.3.2013,  20:08 Найти цитируемый пост)
А как с побитовым сдвигом это сделать?
Код

byte1 += 1 << (7 - k);


Цитата(Асоишница @  14.3.2013,  20:08 Найти цитируемый пост)
ошибку нашла

Мои поздравления  smile 


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Асоишница
Дата 14.3.2013, 22:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 45
Регистрация: 13.3.2012

Репутация: нет
Всего: нет



feodorv, спасибо)всё работает)
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




[ Время генерации скрипта: 0.1037 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.