Форум программистов, компьютерный форум, киберфорум
Наши страницы

C++

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

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

03.08.2011, 17:13. Просмотров 2113. Ответов 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() указывает на одни и теже строки и столбцы, проверка элементов матрицы показала отсутсвие ошибок. А и В созданы и инициализированы правильно!
Суть задачи - где в моём коде просчёт?Готов к другим вариантам удаления строк и столбцов, жду...
0
Изображения
 
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.08.2011, 17:13
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Устал искать баг (C++):

Баг asio? или баг TCP стека? - C++
всем привет. повстречался с очень странным багом. и не могу определить кто бажит, asio, или TCP-стек. на стороне клиента,...

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

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

Непонятный баг - C++
Пишу программу на Си++ с использованием Qt и FMOD. Вот место, где глючит (тут только куски кода, не весь): void...

очень интересный баг - C++
Если кто-нибудь догадается в чем ошибка, то скажите. Ошибку я уже исправил, но не знаю, почему не работает этот код: #include...

Баг в MinGW при использовании fread - C++
Ну собственно вот простой тестовый код который выполняется некорректно: #include &lt;cstdio&gt; using namespace std; const int N =...

23
voral
488 / 468 / 79
Регистрация: 16.03.2008
Сообщений: 2,215
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;
т.к. еперь на этом месте еще не проверенный элеент
0
xAtom
915 / 740 / 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;
}
1
-=ЮрА=-
Заблокирован
Автор FAQ
03.08.2011, 20:17  [ТС] #4
Ты хочешь сказать что memcpy (move, не важно какая из них) работала не со строкой, а со всем оставшимся массивом???
0
voral
488 / 468 / 79
Регистрация: 16.03.2008
Сообщений: 2,215
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) смещались причем с заходом на другую строку.....
1
-=ЮрА=-
Заблокирован
Автор FAQ
04.08.2011, 09:16  [ТС] #6
Матрица размером 4000х4000, поэтому и не могу дебагом нормально что-то выловить...
0
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;
        }
    }
Т.е. мы просто не выводим пустые строчки....
Вроде неплохая идея(это намного производительней, чем сдвигать строчки\столбцы), а вот реализация хромает.. падает прога
0
voral
488 / 468 / 79
Регистрация: 16.03.2008
Сообщений: 2,215
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) может оказаться все, что угодно.....
0
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;
}
0
voral
488 / 468 / 79
Регистрация: 16.03.2008
Сообщений: 2,215
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 который занимает несколько байт в памяти, а на его месте
//переменный типа чар в один байт... :)
0
Stas0n
3 / 4 / 0
Регистрация: 13.07.2011
Сообщений: 313
04.08.2011, 14:26 #11
Ну так ведь я не прошу вывести то очищенную строчку.. я просто проверяю - если пустая, то не печатаю...
Разве это неправильно?
0
voral
488 / 468 / 79
Регистрация: 16.03.2008
Сообщений: 2,215
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 Посмотреть сообщение
Ну так ведь я не прошу вывести то очищенную строчку.. я просто проверяю - если пустая, то не печатаю... Разве это неправильно?
В какой строке проверка?
0
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;
        }
    }
Может подскажешь, как столбец удалить?
0
voral
488 / 468 / 79
Регистрация: 16.03.2008
Сообщений: 2,215
04.08.2011, 15:16 #14
1 Если "доковыривать" твой код. То удалять строку нет необходимости. Достаточно в первом элементе текущей строки поставить 0. И потом при записи в файл проверять это условие. Это будет пошустрее
2. Как удалять столбик, что то не придумывается в таком варианте. только по штучно

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

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

Добавлено через 1 минуту
Это условие
C++
1
matrix[i][i]!=NULL
не будет работать
0
Stas0n
3 / 4 / 0
Регистрация: 13.07.2011
Сообщений: 313
04.08.2011, 16:33 #15
Нельзя ставить ноль... Ноль в матрице так же может быть элементом.
0
04.08.2011, 16:33
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.08.2011, 16:33
Привет! Вот еще темы с ответами:

Помогите выловить баг, сил моих больше нету((( - C++
Программа глючит при добавлении больших структурированных каталогов, раньше думал, что ошибка выделения памяти, оказалось нет...Очень надо...

Баг или так задумано? Фишка с кодировкой файлов компиляции - C++
Visual C++ 2013 Express. От изменения кодировки созданных .cpp файлов будет зависеть то как выводятся русские буквы. Никогда раньше не...

Ошибка в коде (очень устал искать) - Pascal ABC
Уже несколько раз проходил отладкой, не пойму, в чём ошибка. Часа 2-3 бьюсь. Задание: Выделить цветом и подсчитать число слов,...

MS Access - УСТАЛ УЖЕ ИСКАТЬ ПРИЧИНУ СВОЕЙ ОШИБКИ - MS Access
как сделать поля с выбором варианта?.. например пол- выбрать &quot;м&quot; или &quot;ж&quot; тип данных ставлю логический формат поля -истина/лож ...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

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