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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Deep_sea
0 / 0 / 0
Регистрация: 03.05.2012
Сообщений: 9
#1

Разобраться в функции - C++

15.08.2012, 16:23. Просмотров 1029. Ответов 20
Метки нет (Все метки)

Здравствуйте! Имеем функцию на C. Не могу разобраться в строках 17-19 и 30-32. Возможно ли в C++ реализовать их более понятно или хотя бы поясните, как эту функцию перенести в C++, компилятор ругается на строки 19 и 32?

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
//  Функция запрашивает необходимую информацию и строит рваный массив, возвращая
//   указатель   на   него.   Количество   строк   хранится   в   «минус   первом»   элементе   вектора
// указателей на строки, а  в «минус первом» элементе каждой строки – количество элементов 
// в строке
double ** ConstructArray()
{
double ** p=NULL;
int N, M; // количество строк, элементов в строке
// Ввести корректное количество строк
do
{
printf("\nProgram makes an array of N rows.\n");
printf("Please, enter N (1<=N<=10): ");
scanf("%d", &N);
}while(N<1 || N>10);
p=(double **)malloc( sizeof(double *)*N + sizeof(int));// выделить память
((int *)p)[0]=N; //записать количество строк
((int *)p)++; //сдвинуть указатель
// вводить построчно
for(int i=0; i<N; i++)
{
// ввести корректное количество элементов в строке
do
{
printf("Enter M - number of elements in %d-th row (1<=M<=10): ", i);
scanf("%d", &M);
}while(M<1 || M>10);
// выделить память
p[i]=(double *)malloc( M*sizeof(double) + sizeof(int));
((int *)(p[i]))[0]=M; // записать длину строки
((int *)(p[i]))++; // сдвинуть указатель
// поэлементно вводим и сохраняем в массив строки
for(int j=0; j<M; j++)
{
double m;
do
{
printf("\nEnter A[%d][%d] (1<=A[%d][%d]<=10): ", i, j, i, j);
scanf("%lf", &m);
}while(m<1 || m>10);
p[i][j]=m;
}
}
return p; // вернем сконструированный массив
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.08.2012, 16:23     Разобраться в функции
Посмотрите здесь:

Не могу разобраться с отработкой рекурсивной функции C++
Функции и файлы! Для продвинутых, я не могу разобраться. C++
Помогите разобраться(С)Cпособы передачи аргументов в вызываемые функции: по значению, указателю и ссылке C++
помогите разобраться с ошибкой в вызове функции C++
C++ не могу разобраться с функциями ( значение функции, заданной с помощью ряда)
C++ не могу разобраться в функции
Функции в c++. никак не разобраться с задачками C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alsav22
5411 / 4807 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
15.08.2012, 16:38     Разобраться в функции #2
Цитата Сообщение от Deep_sea Посмотреть сообщение
Возможно ли в C++ реализовать их более понятно
В С++, выделение памяти - через new.
Catstail
Модератор
 Аватар для Catstail
21788 / 10512 / 1706
Регистрация: 12.02.2012
Сообщений: 17,526
15.08.2012, 16:48     Разобраться в функции #3
Место, которое Вас напрягло - это создания динамического массива. В C++ это можно сделать так:

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
#include <iostream.h>
 
int main(int argc, char* argv[])
{
 
    int n,i;
    int **M;
 
    // Г‡Г*ïðîñ Г°Г*çìåðГ*
 
    cout << "Enter size ";
    cin >> n;
 
    // ÑîçäГ*Г*ГЁГҐ Г¬Г*Г±Г±ГЁГўГ* ГіГЄГ*Г§Г*òåëåé Г*Г* ñòðîêè
 
    M=new int*[n];
 
    // ÑîçäГ*Г*ГЁГҐ ñòðîê
 
    for (i=0; i<n; i++) M[i]=new int [n];
    
    // ÏðîâåðêГ* Г°Г*áîòîñïîñîáГ*îñòè
 
    M[5][6]=-777;
    cout << M[5][6] << endl;
    
    // Г“Г*è÷òîæåГ*ГЁГҐ Г¬Г*Г±Г±ГЁГўГ*
 
    for (i=0; i<n; i++) delete [] M[i];
    delete [] M;
    
    return 0;
}
Поскольку динамический двумерный массив есть "массив массивов", то строки его могут быть разной длины!
alsav22
5411 / 4807 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
15.08.2012, 16:51     Разобраться в функции #4
19 строку, наверное, нужно так:
C++
1
(*(int *)p)++;
32 - так:
C++
1
(*(int *)(p[i]))++;
zss
Модератор
Эксперт С++
 Аватар для zss
6124 / 5727 / 1852
Регистрация: 18.12.2011
Сообщений: 14,638
Завершенные тесты: 1
15.08.2012, 16:52     Разобраться в функции #5
Смысл там в том, что в выделенной памяти решили хранить и размеры массива.
Однако, размеры то целочисленные, а массив действительный.
Поэтому в 17 строке выделяется память под массив указателей на адреса строк
и плюс под 1 целое число для хранения количества строк.
В 18 строке вместо адреса в нулевую ячейку записывается это количество строк.
А в 19 строке передвигаем указатель на свободное место. Однако надо сдвинуться
не на 8 байт, а на 4(размер целого числа). Поэтому такое дурное приведение.
Поскольку компилатор приходит от него в ступор, то используйте просто прибавление 1:
C++
1
p=(int*(p))+1; //сдвинуть указатель
Аналогично сделано в строках 30-32 для выделения памяти для каждой строки.
Deep_sea
0 / 0 / 0
Регистрация: 03.05.2012
Сообщений: 9
15.08.2012, 17:59  [ТС]     Разобраться в функции #6
C++
1
p=(int*(p))+1; //сдвинуть указатель
Смысл понял, но ошибка осталась.

Добавлено через 18 минут
aslav22 ваш вариант компилируется, но функция, которая должна выводить на экран этот массив, выводит мусор и вылетает.

Добавлено через 4 минуты
C++
1
2
3
4
5
6
7
8
9
10
11
12
// Функция выводит на экран рваный массив
void PrintArray(double **p)
{
int N, M; // количество строк, столбцов
N=((int *)p)[-1];
for(int i=0; i<N; i++)
{
M=((int *)(p[i]))[-1];
for(int j=0; j<M; j++) printf("%-6.2lf", p[i][j]);
printf("\n");
}
}
alsav22
5411 / 4807 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
15.08.2012, 18:15     Разобраться в функции #7
У меня, как ни странно, но работает. Вылетов нет. Заход в функцию PrintArray() есть, но ничего не выводится. Как функции вызываете? Весь код можете показать? При заполнении, по моему, что-то лишнее делается.
Миниатюры
Разобраться в функции  
alsav22
5411 / 4807 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
15.08.2012, 18:30     Разобраться в функции #8
Вот это не работает:
C++
1
N = ((int *)p)[-1];
В N получается какое-то отрицательное число (мусор).
Deep_sea
0 / 0 / 0
Регистрация: 03.05.2012
Сообщений: 9
15.08.2012, 18:43  [ТС]     Разобраться в функции #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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <iostream>
 
using std::cin;
using std::cout;
using std::endl;
 
double** construct_array();
/*void destruct_array(double**);*/
void print_array(double**);
 
int main()
{
    double** array;
 
    array=construct_array();
    print_array(array);
 
    system("pause");
 
    return 0;
}
 
double** construct_array()
{
    double** array;
 
    int rows, columns;
 
    do
    {
        cout<<"Input the integer number of rows"<<endl;
        cin>>rows;
    }
 
    while(rows<1||rows>10);
 
    array=(double**)malloc(sizeof(double*)*rows+sizeof(int));
    ((int*)array)[0]=rows;
    (*(int*)(array))++;
 
    for (int i=0; i<rows; i++)
    {
        columns=rand()%10+1;
        array[i]=(double*)malloc(sizeof(double)*columns+sizeof(int));
        ((int*)(array[i]))[0]=columns;
        (*(int*)(array[i]))++;
 
        for (int j=0; j<columns; j++)
        {
            double array_sign;
            do
                {
                    cout<<"Input the double number element"<<" Array"<<"["<<i<<"]["<<j<<"]"<<endl;
                    cin>>array_sign;
                }
 
                while(array_sign<1||array_sign>10);
            array[i][j]=array_sign;
        }
    }
 
    return array;
}
 
 
void print_array(double **array)
{
   int rows, columns;
 
   rows=((int*)array)[-1];
 
 
   for(int i=0; i<rows; i++)
       {
       columns=((int*)(array[i]))[-1];
       for(int j=0; j<columns; j++)
          cout<<array[i][j];
       cout<<endl;
       }
}
Вот мой код, а тот предыдущий пример другого варианта.
Полный код примера, он на C:

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include<stdlib.h>
#include"stdio.h"
#include<conio.h>
// Прототипы своих функций
void PrintArray(double **p);
double ** ConstructArray();
void DestructArray(double **p);
//******************************************************************
void main(void)
{
// указатель на вектор указателей на строки
double **pA;
clrscr(); // очистка экрана
// построит массив и вернет указатель на него
pA=ConstructArray();
// выведет массив на экран
    PrintArray(pA);
// освободит память
DestructArray(pA);
// подождет нажатия клавиши
getch();}
//******************************************************************
// Функция запрашивает необходимую информацию и строит рваный массив.
//   Возвращает   указатель   на   него.   Количество   строк   хранится   в   «минус первом» 
// элементе вектора указателей на строки, а в «минус первом» элементе каждой 
// строки – количество. Элементов в строке
double ** ConstructArray()
{
double ** p=NULL;
int N, M; // количество строк, элементов в строке
// вводим корректное количество строк
do
{
printf("\nProgram makes an array of N rows.\n");
printf("Please, enter N (1<=N<=10): ");
scanf("%d", &N);
}while(N<1 || N>10);
// выделяем память
p=(double **)malloc( sizeof(double *)*N + sizeof(int));
// запоминаем в «минус первом» элемент вектора указателя на строки
((int *)p)[0]=N;
// сдвигаем указатель
((int *)p)++;
// Организуем построчный ввод
for(int i=0; i<N; i++)
{
// вводим корректное количество элементов в строке
do
{
printf("\nEnter M - number of elements in %d-th row (1<=M<=10): ", i);
scanf("%d", &M);
}while(M<1 || M>10);
// выделяем память
p[i]=(double *)malloc( M*sizeof(double) + sizeof(int));
// записываем в -1 элемент
((int *)(p[i]))[0]=M; 
// сдвигаем указатель
((int *)(p[i]))++;    
for(int j=0; j<M; j++) // вводим элементы
{
double m;
do
{
printf("\nEnter A[%d][%d] (1<=A[%d][%d]<=10): ", i, j, i, j);
scanf("%lf", &m);
}while(m<1 || m>10);
p[i][j]=m;
}
}
return p; // вернуть указатель на сконструированный массив
}
void DestructArray(double **p)
{
if(!p) return;// проверка корректности
int N; // количество строк
N=((int *)p)[-1];
for(int i=0; i<N; i++)
{
((int *)(p[i]))--;
free(p[i]); // удалить каждую ненулевую
}
((int *)p)--;  // смещаем указатель на место
free(p); // освобождаем память
}
//******************************************************************// Функция выводит на экран рваный массив
void PrintArray(double **p)
{
int N, M; // количество строк, столбцов
N=((int *)p)[-1];
for(int i=0; i<N; i++)
{
M=((int *)(p[i]))[-1];
for(int j=0; j<M; j++) printf("%-6.2lf", p[i][j]);
printf("\n");
}
}
alsav22
5411 / 4807 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
16.08.2012, 04:06     Разобраться в функции #10
Вариант без функции DestructArray(). В ней есть ошибки, ещё не разобрался. А так работает.
Код
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include<stdlib.h>
#include"stdio.h"
#include<conio.h>
 
// Прототипы своих функций
void PrintArray(double **p);
double ** ConstructArray();
void DestructArray(double **p);
 
//******************************************************************
 
void main(void)
{
 
// указатель на вектор указателей на строки
double **pA;
 
//clrscr(); // очистка экрана
 
// построит массив и вернет указатель на него
pA = ConstructArray();
 
// выведет массив на экран
PrintArray(pA);
 
// освободит память
//DestructArray(pA);
 
// подождет нажатия клавиши
getch();}
 
//******************************************************************
// Функция запрашивает необходимую информацию и строит рваный массив.
//   Возвращает   указатель   на   него.   Количество   строк   хранится   в   «минус первом» 
// элементе вектора указателей на строки, а в «минус первом» элементе каждой 
// строки – количество. Элементов в строке
 
double **ConstructArray()
{
    double **p = NULL;
    int N, M; // количество строк, элементов в строке
 
    // вводим корректное количество строк
    do
    {
        printf("\nProgram makes an array of N rows.\n");
        printf("Please, enter N (1<=N<=10): ");
        scanf("%d", &N);
    } while(N<1 || N>10);
 
    // выделяем память
    p = (double **)malloc( sizeof(double *) * N + sizeof(int));
    // запоминаем в «минус первом» элемент вектора указателя на строки
    ((int *)p)[-1] = N;
    // сдвигаем указатель
    //((int *)p)++;
    // Организуем построчный ввод
    for(int i = 0; i < N; i++)
    {
    // вводим корректное количество элементов в строке
        do
        {
            printf("\nEnter M - number of elements in %d-th row (1<=M<=10): ", i);
            scanf("%d", &M);
        } while(M < 1 || M > 10);
 
        // выделяем память
        p[i]=(double *)malloc( M * sizeof(double) + sizeof(int));
        // записываем в -1 элемент
        ((int *)(p[i]))[-1] = M; 
        // сдвигаем указатель
        //((int *)(p[i]))++;    
        for(int j = 0; j < M; j++) // вводим элементы
        {
            double m;
            do
            {
                printf("\nEnter A[%d][%d] (1<=A[%d][%d]<=10): ", i, j, i, j);
                scanf("%lf", &m);
            } while(m < 1 || m > 10);
            p[i][j] = m;
        }
    }
    return p; // вернуть указатель на сконструированный массив
}//
 
//void DestructArray(double **p)
//{
//  if(!p) return;// проверка корректности
//  int N; // количество строк
//  N = ((int *)p)[-1];
//  for(int i = 0; i < N; i++)
//  {
//      ((int *)(p[i]))--;
//      free(p[i]); // удалить каждую ненулевую
//  }
//  ((int *)p)--;  // смещаем указатель на место
//  free(p); // освобождаем память
//}
//******************************************************************// Функция выводит на экран рваный массив
void PrintArray(double **p)
{
    int N, M; // количество строк, столбцов
    N = ((int *)p)[-1];
    for(int i = 0; i < N; i++)
    {
        M = ((int *)(p[i]))[-1];
        for(int j = 0; j < M; j++) 
            printf("%-6.2lf", p[i][j]);
        printf("\n");
    }
}


Добавлено через 1 час 45 минут
Если с освобождением памяти, то вот так можно:
Код
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include<stdlib.h>
#include"stdio.h"
#include<conio.h>
 
// Прототипы своих функций
void PrintArray(double **p);
double ** ConstructArray();
void DestructArray(double **p);
 
//******************************************************************
 
void main(void)
{
 
// указатель на вектор указателей на строки
double **pA;
 
//clrscr(); // очистка экрана
 
// построит массив и вернет указатель на него
pA = ConstructArray();
 
// выведет массив на экран
PrintArray(pA);
 
// освободит память
DestructArray(pA);
 
// подождет нажатия клавиши
getch();}
 
//******************************************************************
// Функция запрашивает необходимую информацию и строит рваный массив.
//   Возвращает   указатель   на   него.   Количество   строк   хранится   в   нулевом  
// элементе вектора указателей на строки, а в нулевом элементе каждой 
// строки – количество элементов в строке
 
double **ConstructArray()
{
    double **p = NULL;
    int N, M; // количество строк, элементов в строке
 
    // вводим корректное количество строк
    do
    {
        printf("\nProgram makes an array of N rows.\n");
        printf("Please, enter N (1<=N<=10): ");
        scanf("%d", &N);
    } while(N < 1 || N > 10);
 
    // выделяем память
    p = (double **)malloc( sizeof(double *) * N + sizeof(int));
    // 
    ((int *)p)[0] = N; // количетсво строк будет находиться в p[0].
    
    // Организуем построчный ввод
    for(int i = 1; i < N + 1; i++)
    {
    // вводим корректное количество элементов в строке
        do
        {
            printf("\nEnter M - number of elements in %d-th row (1<=M<=10): ", i);
            scanf("%d", &M);
        } while(M < 1 || M > 10);
 
        // выделяем память
        p[i]=(double*)malloc( M  * sizeof(double) + sizeof(double));
        // записываем в 0 элемент количество элементов в строке
        ((int *)(p[i]))[0] = M; 
         for(int j = 1; j < M + 1; j++) // вводим элементы
        {
            double m;
            do
            {
                printf("\nEnter A[%d][%d] (1<=A[%d][%d]<=10): ", i, j, i, j);
                scanf("%lf", &m);
            } while(m < 1 || m > 10);
            p[i][j] = m;
        }
    }
    return p; // вернуть указатель на сконструированный массив
}//
 
void DestructArray(double **p)
{
    if(!p) return;// проверка корректности
    int N; // количество строк
    N = ((int *)p)[0];
    for(int i = 1; i < N + 1; i++) // освобождаем память под строками.
    {
        free(p[i]); 
    }
    
    free(p); // освобождаем память под указателями.
}
//******************************************************************// Функция выводит на экран рваный массив
void PrintArray(double **p)
{
    int N, M; // количество строк, столбцов
    N = ((int *)p)[0];
    
    for(int i = 1; i < N + 1; i++)
    {
        M = ((int *)(p[i]))[0];
        for(int j = 1; j < M + 1; j++) 
            printf("%-6.2lf", p[i][j]);
        printf("\n");
    }
}
Если с new, то так:
Код
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include<stdlib.h>
#include"stdio.h"
#include<conio.h>
 
// Прототипы своих функций
void PrintArray(double **p);
double ** ConstructArray();
void DestructArray(double **p);
 
//******************************************************************
 
int main()
{
 
// указатель на вектор указателей на массивы
double **pA;
 
//clrscr(); // очистка экрана
 
// построит массив и вернет указатель на него
pA = ConstructArray();
 
// выведет массив на экран
PrintArray(pA);
 
// освободит память
DestructArray(pA);
 
// подождет нажатия клавиши
getch();
return 0;
}
 
//******************************************************************
// Функция запрашивает необходимую информацию и строит двумерный динамический массив double.
//   Возвращает указатель на него. Количество одномерных массивов хранится в нулевом  
// элементе вектора указателей на массивы, а в нулевом элементе каждого 
// массива – количество элементов в массиве.
 
double **ConstructArray()
{
    double **p = NULL;
    int N, M; // количество одномерных массивов, элементов в массиве
 
    // вводим корректное количество одномереых массивов
    do
    {
        printf("\nProgram makes an array of N rows.\n");
        printf("Please, enter N (1<=N<=10): ");
        scanf("%d", &N);
    } while(N < 1 || N > 10);
 
    // выделяем память
    p = new double *[N + 1];
    // 
    ((int*)p)[0] = N; // количество массивов double будет находиться в p[0].
    
    // Организуем ввод элементов в массивы
    for(int i = 1; i < N + 1; i++)
    {
    // вводим корректное количество элементов в массиве
        do
        {
            printf("\nEnter M - number of elements in %d-th row (1<=M<=10): ", i);
            scanf("%d", &M);
        } while(M < 1 || M > 10);
 
        // выделяем память
        p[i] = new double[M + 1];
        // записываем в 0-элемент количество элементов в массиве
        p[i][0] = M; 
         for(int j = 1; j < M + 1; j++) // вводим элементы
        {
            double m;
            do
            {
                printf("\nEnter A[%d][%d] (1<=A[%d][%d]<=10): ", i, j, i, j);
                scanf("%lf", &m);
            } while(m < 1 || m > 10);
            p[i][j] = m;
        }
    }
    return p; // вернуть указатель на сконструированный массив 
}//
 
void DestructArray(double **p)
{
    if(!p) return;// проверка корректности
    int N; // количество массивов double
    N = ((int*)p)[0];
    for(int i = 1; i < N + 1; i++) // освобождаем память под массивами double.
    {
        delete [] p[i]; 
    }
    
    delete [] p; // освобождаем память под указателями на массивы double.
}
//******************************************************************// Функция выводит на экран двумерный динамический массив
void PrintArray(double **p)
{
    int N, M; 
    N = ((int *)p)[0]; // количество одномерных массивов.
    
    for(int i = 1; i < N + 1; i++)
    {
        M = p[i][0]; // количество элементов в одномерном массиве.
        for(int j = 1; j < M + 1; j++) 
            printf("%-6.2lf", p[i][j]);
        printf("\n");
    }
}
Deep_sea
0 / 0 / 0
Регистрация: 03.05.2012
Сообщений: 9
16.08.2012, 19:25  [ТС]     Разобраться в функции #11
Да, спасибо, так все работает. Но есть проблема - в задании написано хранить информацию о массиве именно в -1 элементе. Сдвинуть указатель у меня не получается.
alsav22
5411 / 4807 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
16.08.2012, 20:31     Разобраться в функции #12
Цитата Сообщение от Deep_sea Посмотреть сообщение
Да, спасибо, так все работает. Но есть проблема - в задании написано хранить информацию о массиве именно в -1 элементе. Сдвинуть указатель у меня не получается.
Задание мне не понятно. Если память выделять динамически, то, смотрите, что в этом случае получается. Выделяется память, указатель на неё сохраняется, допустим, в указателе p. Потом по адресу p - 1, то есть перед выделенной памятью, записывается какое-то значение. Последствия неопределённые. Даже если это проходит нормально, то при освобождении памяти будут проблемы. Для массива указателей, это срабатывает, потому что размер памяти под указатель, и размер памяти под int совпадают. Для массива под double - это уже не срабатывает. У меня, по крайней мере, это не получилось сделать. Если память не освобождать (как в моём первом коде), то будет работать и с -1 элементом, но тогда утечка памяти.
Deep_sea
0 / 0 / 0
Регистрация: 03.05.2012
Сообщений: 9
16.08.2012, 20:40  [ТС]     Разобраться в функции #13
Насколько я понимаю, записывается в 0 элементе, а потом сдвигается указатель, так что нумерация остальных элементов будет начинаться с 0, а тот который был нулевым становится -1. Посмотрите вот методичка 4 контрольная 1 задание.
Вложения
Тип файла: pdf UchPosZaoch.pdf (818.4 Кб, 7 просмотров)
alsav22
5411 / 4807 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
17.08.2012, 03:06     Разобраться в функции #14
Теперь понял. Первый указатель: (int *)p++; нормально сдвигается. Второй: ((int *)(p[i]))++;, почему-то, не получается сдвинуть.

Добавлено через 33 минуты
Просто p[i]++; нормально сдвигается, но если попытаться привести p[i] к указателю на int и попробовать сдвинуть, то ошибка. Почему это - не понимаю.

Добавлено через 4 часа 6 минут
Так работает:
Код
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include<stdlib.h>
#include"stdio.h"
#include<conio.h>
#include <iostream>
using namespace std;
// Прототипы своих функций
void PrintArray(double **p);
double ** ConstructArray();
void DestructArray(double **p);
//******************************************************************
int main()
{
// указатель на массив указателей на double
double **pA;
clrscr(); // очистка экрана
// построит массив и вернет указатель на него
pA=ConstructArray();
// выведет массив на экран
    PrintArray(pA);
// освободит память
DestructArray(pA);
// подождет нажатия клавиши
getch();
return 0;
}
//******************************************************************
// Функция запрашивает необходимую информацию и строит рваный массив.
//   Возвращает   указатель   на   него.   Количество   массивов double   хранится   в   «минус первом» 
// элементе массива указателей, а в «минус первом» элементе каждого 
// массива – количество элементов в массиве.
double ** ConstructArray()
{
double ** p=NULL;
int N, M; // количество массивов double, элементов в массиве.
// вводим корректное количество массивов
do
{
printf("\nProgram makes an array of N rows.\n");
printf("Please, enter N (1<=N<=10): ");
scanf("%d", &N);
}while(N<1 || N>10);
// выделяем память под массив указателей
p=(double **)malloc( sizeof(double *)*N + sizeof(int));
// запоминаем, в «минус первом» элементе массива указателей, количество массивов double
((int *)p)[0]=N;
// сдвигаем указатель на массив указателей
(int *)p++;
// Организуем ввод элементов массивов double
for(int i=0; i<N; i++)
{
// вводим корректное количество элементов в массиве
do
{
printf("\nEnter M - number of elements in %d-th row (1<=M<=10): ", i);
scanf("%d", &M);
}while(M<1 || M>10);
// выделяем память под массивы double
p[i]=(double *)malloc( M*sizeof(double) + sizeof(int));
// записываем, в -1 элемент массива, количество элементов в массиве.
((int*)(p[i]))[0]=M;
// сдвигаем указатель на массив double
p[i] = (double*)(((int *)*(p + i)) + 1);
for(int j=0; j<M; j++) // вводим элементы
{
double m;
do
{
printf("\nEnter A[%d][%d] (1<=A[%d][%d]<=10): ", i, j, i, j);
scanf("%lf", &m);
}while(m<1 || m>10);
p[i][j]=m;
}
}
return p; // вернуть указатель на сконструированный массив
}
void DestructArray(double **p)
{
if(!p) return;// проверка корректности
int N; // количество строк
N=((int *)p)[-1];
for(int i=0; i<N; i++)
{
    p[i] = (double*)(((int *)*(p + i)) - 1); // сдвигаем назад указатели на массивы double.
    free(p[i]); // освобождаем память под массивами double.
}
(int *)p--;  // сдвигаем назад указатель на массив указателей.
free(p); // освобождаем память под массивом указателей.
}
//******************************************************************// Функция выводит на экран рваный массив
void PrintArray(double **p)
{
int N, M; // количество массивов, элементов в массиве
N=((int *)p)[-1];
for(int i=0; i<N; i++)
{
M=((int *)p[i])[-1];
for(int j=0; j<M; j++) printf("%-6.2lf", p[i][j]);
printf("\n");
}
}

Сдвиг, указателей на double, только так получается сделать:
C++
1
p[i] = (double*)(((int *)*(p + i)) + 1);
Через инкремент это никак не сделать. Не понятно, как такие примеры решения заданий можно приводить?
Deep_sea
0 / 0 / 0
Регистрация: 03.05.2012
Сообщений: 9
17.08.2012, 09:02  [ТС]     Разобраться в функции #15
Цитата Сообщение от alsav22 Посмотреть сообщение
Не понятно, как такие примеры решения заданий можно приводить?
Ну так вопрос к преподавателю, как он решил, так и написал. В любом случае спасибо за помощь.
alsav22
5411 / 4807 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
17.08.2012, 16:37     Разобраться в функции #16
Цитата Сообщение от Deep_sea Посмотреть сообщение
Ну так вопрос к преподавателю, как он решил, так и написал.
Я про него и пишу. Такие конструкции:
C++
1
2
((int *)p)++; 
((int *)(p[i]))++;
в принципе не могут быть выполнены. В последних круглых скобках получается временное выражение (rvalue), к которому нельзя применить инкремент. Кстати, в такой строке: (int *)p++; (47 строка) приведение к int* не срабатывает. Нужный сдвиг там происходит из-за совпадение размера double** и int*. Если уж правильно писать, то так:
C++
1
p = (double**)((int*)p + 1);
Вебер
0 / 0 / 0
Регистрация: 05.01.2011
Сообщений: 25
26.03.2013, 01:21     Разобраться в функции #17
alsav22, А что делать если количество строк нужно хранить в "Терминальный символ в конце вектора указателей на строки" ?
Т.е. что вобще есть этот терминальный символ?
alsav22
5411 / 4807 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
26.03.2013, 02:45     Разобраться в функции #18
Цитата Сообщение от Вебер Посмотреть сообщение
Т.е. что вобще есть этот терминальный символ?
Насколько знаю, это: '\0'. Конец строки в стиле С.

Добавлено через 1 минуту
Цитата Сообщение от Вебер Посмотреть сообщение
А что делать если количество строк нужно хранить в "Терминальный символ в конце вектора указателей на строки" ?
Эту фразу не понимаю.
kamre
126 / 130 / 4
Регистрация: 25.12.2011
Сообщений: 443
26.03.2013, 04:06     Разобраться в функции #19
Цитата Сообщение от Deep_sea Посмотреть сообщение
Возможно ли в C++ реализовать их более понятно
Легко, нужно только использовать нормальные контейнеры вроде std::vector<std::vector<double> > и не заниматься ерундой с указателями.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.03.2013, 08:39     Разобраться в функции
Еще ссылки по теме:

Разобраться в функции перемножения двух векторов C++
C++ Разобраться в небольшой функции
C++ Stack. определение шаблона функции testStack. (хочу разобраться в коде)
C++ Не могу разобраться как сделать указатель функции с динамич. массивом
Не могу разобраться с функциями в коде. Что это за функции Intreader , Bitwriter C++

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

Или воспользуйтесь поиском по форуму:
Вебер
0 / 0 / 0
Регистрация: 05.01.2011
Сообщений: 25
26.03.2013, 08:39     Разобраться в функции #20
alsav22,
Насколько знаю, это: '\0'. Конец строки в стиле С.
да это так называемый нультерминант,для определения конца строки.

Если Deep_sea, требовалось хранить информацию о массиве в -1 эелементе,то мне требуеться хранить в "Терминальный символ в конце вектора указателей на строки",и как это вобще я не понимаю.
Yandex
Объявления
26.03.2013, 08:39     Разобраться в функции
Ответ Создать тему
Опции темы

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