Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 17, средняя оценка - 4.65
-=ЮрА=-
Заблокирован
Автор FAQ
#1

Устал искать баг - C++

03.08.2011, 17:13. Просмотров 2061. Ответов 23
Метки нет (Все метки)

Проблемма проста - нужно удалить из вещественной матрицы строку и столбец, верней ряд строк и столбцов (условие - нулевой элемент на главной диагонале, даже привожу рисунок)

Пропускаю матрицу А и вектор свободных членов В через вот такой фильтр
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void compress(int m, double **a, double *b)
{
    for(int i = 0,j; i < m; i++)
    {
        if(a[i][i] == 0)
        {
            for(j = i; j < m - 1; j++)
                memcpy((void *)&a[j],(void *)&a[j + 1],m);
            for(j = 0; j < m; j++)
                a[j] = compress(m, i, a[j]);
            b = compress(m, i, b);
        }
    }
}
 
double * compress(int m, int i, double * vec)
{
    memcpy((void *)&vec[i],(void *)&vec[i + 1],m - (i + 1));
    return vec;
}
Всё время вылетает ошибка, try{}catch() указывает на одни и теже строки и столбцы, проверка элементов матрицы показала отсутсвие ошибок. А и В созданы и инициализированы правильно!
Суть задачи - где в моём коде просчёт?Готов к другим вариантам удаления строк и столбцов, жду...
Изображения
 
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.08.2011, 17:13     Устал искать баг
Посмотрите здесь:

Устал от утечек памяти - C++
С этими утечками памяти в C++ просто беда. Посоветуйте, что можно сделать? Может быть есть какие-то специальные утилиты?

Как искать ошибку? - C++
иногда в програмие вылетает ошибка Unhandled exception at at 0x75BAB727 in _2.0.exe: Microsoft C++ exception: std::out_of_range at...

Как искать ответы на вопросы? - C++
возможно глупый вопрос без конкретного ответа, но всетаки постараюсь сформулировать его как можно более понятно по сути. я учу с++. и...

Где искать DllMain в ATL 7.0? - C++
Может кто знает где искать DllMain в ATL 7.0 А то смотрю в глобальных функциях есть а когда пытаешься открыть программа выкидывает тебя...

Как правильно искать информацию по программированию на c++? - C++
Здравствуйте! Я думаю эта тема будет крайне полезна новичкам, коим являюсь и я. Вопрос собственно в том, где брать официальную...

Литература С++ для начинающих: Где искать? - C++
Ребята, подскажите литературу для изучения С++. Вообще я пишу всё на дельфине уже два года (т.е. есть опыт в программировании), а тут...

Как искать файлы которые создал пользователь? - C++
Каким методом можно искать файлы которые создал пользователь?

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
voral
411 / 391 / 51
Регистрация: 16.03.2008
Сообщений: 1,933
03.08.2011, 18:11     Устал искать баг #2
Как вариант:
1. Обходим матрицу. Двигаемся только по диагонали. Если встречаем 0. Уменьшаем счетчик столбцов/строк
2. Выделяем память под новую матрицу с размерами согласно текущему полученному счетчику строк/столбцов
3. Опять идем по матрице (по диагонали) и копируем во вторую только то, что нужно (т.е. если элемент в диагонали не равен 0)

Добавлено через 1 минуту
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
for(int i = 0,j; i < m; i++)
j -здесь зачем?

Добавлено через 6 минут
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
C++
1
2
for(j = i; j < m - 1; j++) 
memcpy((void *)&a[j],(void *)&a[j + 1],m);
Здесь, как я понял, вы сдивгаете строку. Т.е. согласно рисунку 5 ячеек начина с ячейки со значением "8".. Т.е. на последней строке вы вылетаете за пределы. К томуже еще перебиваете первые ячеки следующей строки (если текущая не последняя)

Добавлено через 4 минуты
К тому же у вас m не изменяется, а элементы сдвигаются

Добавлено через 8 минут
C++
1
for(j = 0; j < m; j++)
Тут тоже вроде нужно не до m, а до i

Добавлено через 10 минут
Стоп. у вас же double..... А последний параметр memcpy размер в байтах. нет?

Добавлено через 6 минут
Не проверял. Но вроде так. (Это как я понял ваш алгоритм только без memcpy). Но нужно еще освободить память. Или просто возвращать новый размер
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void compress(int m, double **a, double *b)
{
    for(int i = 0,j; i < m; i++)
    {
        if(a[i][i] == 0)
        {
            for(j = i; j < m - 1; ++j)
                for(k=0;k<m;++k)
                    a[j][k]=a[j+1][k];
            for(j = i; j < m - 1; ++j)
                for(k=0;k<m;++k)
                    a[j][k]=a[j][k+1];
            --m;
        }
    }
}
Добавлено через 1 минуту
Ах да. Наверно надо в 15 строку вставить
C++
1
--i;
т.к. еперь на этом месте еще не проверенный элеент
xAtom
914 / 739 / 60
Регистрация: 09.12.2010
Сообщений: 1,346
Записей в блоге: 1
03.08.2011, 20:14     Устал искать баг #3
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
memcpy((void *)&vec[i],(void *)&vec[i + 1],m - (i + 1));
Видишь как получается ты указываешь только количество элементов массива, но функции memcpy, memccpy, memcmp, memmove и так далее, работают не с массивом а буфером, то есть нужно указывать полный размер данных. Вот написал код по твоей задаче

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
using namespace std;
 
 
void cross_remove(double** mat, int& size) {
    int  r;
    for(int i = 0; i < size; i++) {
        if( mat[i][i] == 0.0 ) {
        
          for(r = i; r < size - 1; r++) 
              memcpy(*((mat) + r), *((mat) + r + 1), sizeof(double) * size);
 
          for(r = 0; r < size; r++) 
              memcpy( *((mat) + r) + i,  *((mat) + r) + i + 1, (size - (i + 1)) * sizeof(double));
 
          size -= 1;
          cross_remove(mat, size);
        } 
    }
}
 
 
int main(void) {
 
   const int N = 4;
   int r, c;
 
   double** arr = new double*[N];
   for(int n = 0; n < N; n++)
        *((arr) + n) = new double[N];
 
   // статическая матрица для примера будет служить
   double   mat[N][N] = {
        {  0.0,    3.5,        40.5 ,   5.8 },
        {  2.4,     5.5,       23.5,    7.8 },
        {   9.4,     4.5,      0.0,      1.8 },
        {   8.4,     8.5,      23.5,    3.3 }
   };
 
   // с копировать её в динамическую матрицу
   for(r = 0; r < N; r++)
        memcpy(arr[r],  mat[r], sizeof(double) * N);
 
 
   int size  = N;  // переменная нужна для возвращения размера матрицы
   cross_remove((double**)arr, size);
 
   for(r = 0; r < size; r++) {
     for(c = 0; c < size; c++)
        cout << arr[r][c] << '\t';
     cout.put('\n');
   }
 
   for(r = 0; r < N; r++) {
       delete[] *((arr) + r);
       *((arr) + r) = NULL;
   }
   delete[] arr;
   arr = NULL;
 
   cin.get();
   return 0;
}
-=ЮрА=-
Заблокирован
Автор FAQ
03.08.2011, 20:17  [ТС]     Устал искать баг #4
Ты хочешь сказать что memcpy (move, не важно какая из них) работала не со строкой, а со всем оставшимся массивом???
voral
411 / 391 / 51
Регистрация: 16.03.2008
Сообщений: 1,933
03.08.2011, 20:49     Устал искать баг #5
Не со всем. Зависит от размера матрицы и платформы. Если размер double - 8 байт. И матрица 8x8 то копировася один следующий элемент. Если размер матрицы 14 то на последнем цикле
a[j][k]=a[j][k+1];
a[j][k+1]= черте что т.к. копировались только 6 байт из 8ми

Добавлено через 3 минуты
Т.е. при размере матрицы меньше 8 копировался кореженный следующий элемент; больше восьми (m/8) смещались причем с заходом на другую строку.....
-=ЮрА=-
Заблокирован
Автор FAQ
04.08.2011, 09:16  [ТС]     Устал искать баг #6
Матрица размером 4000х4000, поэтому и не могу дебагом нормально что-то выловить...
Stas0n
3 / 4 / 0
Регистрация: 13.07.2011
Сообщений: 313
04.08.2011, 13:48     Устал искать баг #7
А что, если просто удалять из массива нужную строчку\ столбец?

Добавлено через 1 час 18 минут
Можно например просто удалить вот так delete[] matrix[i]. Это строку/столбец не удалит - только освободит память, где она лежала. Но все указатели (и место в массиве под нее) останется.
а при выводе можно делать так:
C++
1
2
3
4
5
6
7
8
9
10
    for (int i = 0; i < range-k; i ++)
    {
        if ( matrix[i][i]!=NULL)
        {
            for (int j = 0; j < range-k; j++)
            {
                ofs << matrix[i][j] << " ";
            } ofs << endl;
        }
    }
Т.е. мы просто не выводим пустые строчки....
Вроде неплохая идея(это намного производительней, чем сдвигать строчки\столбцы), а вот реализация хромает.. падает прога
voral
411 / 391 / 51
Регистрация: 16.03.2008
Сообщений: 1,933
04.08.2011, 14:02     Устал искать баг #8
Цитата Сообщение от hello19 Посмотреть сообщение
Можно например просто удалить вот так delete[] matrix[i]. Это строку/столбец не удалит - только освободит память, где она лежала. Но все указатели (и место в массиве под нее) останется.
каким образом это освободит память занимаемую столбцом?
Далее если предположить, что так можно освободить память, почему вы думаете, что там будет NULL?

Давайте рассмотрим пример. Для упрощения одномерный массив
C++
1
2
3
4
5
int *test = new test[6];
// разные действия над массивом
delete[]  test;
// некоторые действия
cout << test[4];
Давайте подумаем, что вернет cout и есть ли гарантия, что там NULL.
что значит test[4] ? Это значит, что у нас есть некая область памяти начинающаяся с адреса А и нам надо получить элемент соответствующего размера со смещением от этого адреса (в байтах) 4*sizeof(int). Но ты уже освободил эту память. И она может быть занята другими переменными. Соответственно по адресу (test+4) может оказаться все, что угодно.....
Stas0n
3 / 4 / 0
Регистрация: 13.07.2011
Сообщений: 313
04.08.2011, 14:09     Устал искать баг #9
Извините, просто не кинул часть кода..
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
int main()
{
    int range = 5;
 
    // Allocate  matrix
    double **matrix = new double*[range]();
    for (int i = 0; i < range; i++) 
    {
        matrix[i] = new double[range]();
    }
 
    // reading from file
    ifstream ifs("aa.txt");
    double q;
    int i = 0;
    int j = 0;
    while ( ifs >> q )
    {
        matrix[i][j] = q;
        j++;
        if ( j % range == 0 ) { i++; j = 0;}
    }
    ifs.close();
    // delete nessesary colums and rows
 
    // счетчит количества нулевых строк/столбцов
    int k = 0;
 
    
    for ( int i = 0; i < range; i++ )
    {
        if ( matrix[i][i] == 0 )
        {
            inf << i << endl;
            k++;
            delete matrix[i];
        }
    }
    inf.close();
    // output matrix 2
    ofstream ofs("bb.txt");
    for (int i = 0; i < range-k; i ++)
    {
        for (int j = 0; j < range-k; j++)
        {
            ofs << matrix[i][j] << " ";
        } ofs << endl;
    }
    for ( int i =0; i < range-k; i++)
    delete[] matrix[i];
    delete[] matrix;
}
voral
411 / 391 / 51
Регистрация: 16.03.2008
Сообщений: 1,933
04.08.2011, 14:24     Устал искать баг #10
Ну так сам то внимательно прочитай свой код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
range=3;
// заполняем
arr[0]={1,2,3};
arr[1]={1,2,3};
arr[2]={1,2,3};
// освобождаем
delete[] arr[1];
++k;
//обрати внимание arr[2] не сдвигается в памяти
// водим в цикл вывода марицы в файл
// i от 0 до range-k=3-1=2
ofs << arr[0];
ofs << arr[1]; // упс...... а у нас по этому адресу уже давным давно другая переменная, в то и
 //"несколько переменных типа char". 
// мы ведь хотим прочитать double который занимает несколько байт в памяти, а на его месте
//переменный типа чар в один байт... :)
Stas0n
3 / 4 / 0
Регистрация: 13.07.2011
Сообщений: 313
04.08.2011, 14:26     Устал искать баг #11
Ну так ведь я не прошу вывести то очищенную строчку.. я просто проверяю - если пустая, то не печатаю...
Разве это неправильно?
voral
411 / 391 / 51
Регистрация: 16.03.2008
Сообщений: 1,933
04.08.2011, 14:29     Устал искать баг #12
однако можно так:
C++
1
2
 k++;  delete matrix[i];
 matrix[i]=NULL;
а потом
C++
1
2
if (matrix[i]!=NULL)
   for (int j = 0; j < range; j++)         {             ofs << matrix[i][j] << " ";         }
Но остается не закрытым вопрос удаления столбика

Добавлено через 40 секунд
Цитата Сообщение от hello19 Посмотреть сообщение
Ну так ведь я не прошу вывести то очищенную строчку.. я просто проверяю - если пустая, то не печатаю... Разве это неправильно?
В какой строке проверка?
Stas0n
3 / 4 / 0
Регистрация: 13.07.2011
Сообщений: 313
04.08.2011, 14:56     Устал искать баг #13
Проверка при выводе:
C++
1
2
3
4
5
6
7
8
9
10
    for (int i = 0; i < range-k; i ++)
    {
        if ( matrix[i][i]!=NULL)
        {
            for (int j = 0; j < range-k; j++)
            {
                ofs << matrix[i][j] << " ";
            } ofs << endl;
        }
    }
Может подскажешь, как столбец удалить?
voral
411 / 391 / 51
Регистрация: 16.03.2008
Сообщений: 1,933
04.08.2011, 15:16     Устал искать баг #14
1 Если "доковыривать" твой код. То удалять строку нет необходимости. Достаточно в первом элементе текущей строки поставить 0. И потом при записи в файл проверять это условие. Это будет пошустрее
2. Как удалять столбик, что то не придумывается в таком варианте. только по штучно

Вообще алгоритм ТС (естественно после доработок) мне кажется оптимальным.
Пробегать каждый элемент накладно (в твоем варианте это тоже есть и вмое предложенном во 2 посте)
В моем (заполнение 0-ями) есть подводный камень - может быть реальный 0 не на диагонали

Единственное, что можно опробовать запихнуть матрицу в граф. но пока что то кажется не слишщком получится красиво

Добавлено через 1 минуту
Это условие
C++
1
matrix[i][i]!=NULL
не будет работать
Stas0n
3 / 4 / 0
Регистрация: 13.07.2011
Сообщений: 313
04.08.2011, 16:33     Устал искать баг #15
Нельзя ставить ноль... Ноль в матрице так же может быть элементом.
voral
411 / 391 / 51
Регистрация: 16.03.2008
Сообщений: 1,933
04.08.2011, 16:39     Устал искать баг #16
да да. я и сказал об этом
Stas0n
3 / 4 / 0
Регистрация: 13.07.2011
Сообщений: 313
04.08.2011, 16:43     Устал искать баг #17
Вот так и получается, что код не ахти какой((
Deviaphan
Делаю внезапно и красиво
Эксперт C++
1286 / 1220 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
04.08.2011, 16:43     Устал искать баг #18
Можно вообще не удалять ни столбцы, ни строки. Сохранить список "нулевых" индексов и пропускать их при записи в файл. Если дополнительной никакой работы не будет над матрицей происходить после "удаления" строк/столбцов, то это самый эффективный вариант.
Stas0n
3 / 4 / 0
Регистрация: 13.07.2011
Сообщений: 313
04.08.2011, 16:54     Устал искать баг #19
?????
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.08.2011, 17:13     Устал искать баг
Еще ссылки по теме:

Как искать функции, работающие с определенным типом? - C++
Всем привет! Сейчас у меня типичная нудная задача: создать строку wchar_t, конвертировать цифру из int в wchar_t, затем склеить...

Написать программу, которая буде искать и открывать файл. - C++
Здравствуйте. Надо написать программу, которая буде искать и открывать файл. Пока что написано только что бы читать файл, уже по заданному...

Как искать в файле и записать его в новый файл? - C++
Здравствуйте вот не могу никак решить проблему и за ранее спс кто откликнется и поможет в это нелегкой задачке не понимаю как искать в...

C++ Builder XE3 компонент TChart не установился, где искать? - C++ Builder
При установке ХЕ3 я повыключал всю ненужную (как я думал) байду — FireMonkey, Cobra, Ribbon и т.д, теперь нет чарта. Что нужно...

Нужно просматривать папки и искать в них определенные файлы - C++
Подскажите, как решить задачку! Есть папочка, а в ней еще много папочек, так вот нужно открывать их по очереди, и смотреть, есть ли там...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
voral
411 / 391 / 51
Регистрация: 16.03.2008
Сообщений: 1,933
04.08.2011, 17:13     Устал искать баг #20
Создаешь еще одну матрицу такого же размера. Заполняешь, например, 1цами. Пройтись по диагонали основной матрицы. А в вспомогательной проставлять 0 в тех элементах, которые должны быть удалены). Потом формируешь результирующую матрицу на основании первых двух.

Добавлено через 11 минут
Как бы то ни было в итоге мы все равно получаем по элементное копирование одного массива в другой. ТС предложил неплохой вариант. Массив остается прежний, но копирование происходит только при наличии 0 в диагонали. При чем копирование производим кусками памяти.
Yandex
Объявления
04.08.2011, 17:13     Устал искать баг
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru