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

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

Войти
Регистрация
Восстановить пароль
 
 
Ваю
17 / 17 / 1
Регистрация: 21.04.2015
Сообщений: 524
#1

Передача массива в функцию используя указатель на функцию - C++

01.08.2015, 13:35. Просмотров 537. Ответов 15
Метки нет (Все метки)

У меня имеется готовая программа без передачи функции в функцию указателем, мне нужно передать функцию ввода масива в функцию его обработки с помощью указателя. Имеется 3 функции ввода и 1 обработки, при вводе не из файла в качестве отсутствующих параметров можно добавить (..., NULL, "") дабы был один формат

Без указателей объявления такие:

C++
1
2
3
4
5
int InpKbdArr(__int16 * & Arr, unsigned int & SizeW, unsigned int & SizeH); //клава
int GenRndArr(__int16 * & Arr, unsigned int & SizeW, unsigned int & SizeH); //рандом
int FReadArr (__int16 * & Arr, unsigned int & SizeW, unsigned int & SizeH, FILE* & fArr, char * & Arr_txt); //файл
 
int MaxInStr (__int16 * & Arr, unsigned int & SizeW, unsigned int & SizeH, __int16 * & ArrX);
У меня имеются примеры работы с указателями, более-менее понятно что там происходит, но как сделать для моего задания я не знаю.

Вся программа целиком:
Кликните здесь для просмотра всего текста
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
#include <cstdlib>
#include <iostream>
#include <stdio.h>
#include <time.h>
#include <conio.h>
#include <sys\stat.h>
#include <sys\types.h>
using namespace std;
 
void InputData (__int16* & Array, unsigned int & SizeWidth, unsigned int & SizeHeight, 
    FILE* & fArr, char* & Arr_txt, unsigned int & ReadFileArr);
int  InpKbdArr (__int16* & Array, unsigned int & SizeWidth, unsigned int & SizeHeight);
int  GenRndArr (__int16* & Array, unsigned int & SizeWidth, unsigned int & SizeHeight);
void PrintArr  (__int16* & Array, unsigned int & SizeWidth, unsigned int & SizeHeight);
int  FWriteArr (__int16* & Array, unsigned int & SizeWidth, unsigned int & SizeHeight, 
    FILE* & fArr, char* & Arr_txt);
int  FReadArr  (__int16* & Array, unsigned int & SizeWidth, unsigned int & SizeHeight, 
    FILE* & fArr, char* & Arr_txt);
int  MaxInStr  (__int16* & Array, unsigned int & SizeWidth, unsigned int & SizeHeight, __int16* & ArrX);
void PrintArrX (__int16* & ArrX,                                                        unsigned int & SizeHeight);
int  FWrtArrX  (__int16* & ArrX,  unsigned int & SizeHeight,                             FILE* & fArrX, char* & ArrX_bin);
int  FReadArrX (__int16* & ArrX,  unsigned int & SizeHeight,                             FILE* & fArrX, char* & ArrX_bin);
void SearchMin (__int16* & ArrX,                                                        unsigned int & SizeHeight, __int16  & Min);
 
void main() {
    setlocale(0, "ru-ru"); srand((unsigned int)time(0));
     
    FILE *fArr = NULL, *fArrX = NULL; char *Arr_txt = "Arr.txt", *ArrX_bin = "ArrX.bin"; 
    __int16 *Arr = NULL, *ArrX = NULL, Min = numeric_limits<__int16>::max(); 
    unsigned int SizeW = 0, SizeH = 0, ReadFileArr = 0; 
 
    InputData(Arr, SizeW, SizeH, fArr, Arr_txt, ReadFileArr); //Ввод размера массива с клавиатуры или рандом
    if (!Arr) { //Если массив не был получен
        if (InpKbdArr(Arr, SizeW, SizeH)) //Ввод значений массива с клавиатуры или рандом
            GenRndArr(Arr, SizeW, SizeH); //Генерация случайого массива
    }
    if (Arr) { //Если массив был получен
        if (!ReadFileArr) { //не из файла
            PrintArr(Arr, SizeW, SizeH); //Вывести массив Arr на экран
            FWriteArr(Arr, SizeW, SizeH, fArr, Arr_txt); //Сохранение в текстовый файл массива Arr
        }
        //Поиск максимума в каждой строке массива Arr и сохранение в отдельный массив ArrX
        if (!MaxInStr(Arr, SizeW, SizeH, ArrX)) { //Если удалось выделить память для ArrX
            
            if (FWrtArrX(ArrX, SizeH, fArrX, ArrX_bin) < 2) //Сохранение в бинарный файл
                FReadArrX(ArrX, SizeH, fArrX, ArrX_bin); //Чтеие из бинарного файла
 
            PrintArrX(ArrX, SizeH); //Вывести массив ArrX на экран
 
            SearchMin(ArrX, SizeH, Min); //Поиск в масиве X минимального Y > 0 с помощью рекурсии
            free(ArrX); ArrX = NULL;
 
        } free(Arr); Arr = NULL;
    } 
    else puts("Не удалось считать исходный массив...");
 
    puts(""); system("pause");
}
 
void InputData(__int16 * & Arr,  unsigned int & SizeW, unsigned int & SizeH, FILE* & fArr, 
    char* & Arr_txt, unsigned int & Flag)
{
    char *Err1, *Err2, Tmp1[23], Tmp2[23]; SizeW = 0, SizeH = 0;
 
    do { do { Flag = 0; 
            printf("Ширина и высота массива [5..65535 или * или f f]: "); 
            scanf_s("%22s %22s", Tmp1, 23, Tmp2, 23);
            if (strlen(Tmp1) > 5 || strlen(Tmp2) > 5) {
                Flag = 1; puts("Корявый ввод");
            }
        } while (Flag);
 
        _strlwr(Tmp1); _strlwr(Tmp2);
        if (*Tmp1 == 'f' && *Tmp2 == 'f' && strlen(Tmp1) == 1 && strlen(Tmp2) == 1) {
            FReadArr(Arr, SizeW, SizeH, fArr, Arr_txt); Flag = 2; break; //Чтение из текстового файла массива Arr
        }
        
        SizeW = strtol(Tmp1, &Err1, 10);
        if ((SizeW < 5) || (Err1 == Tmp1 && *Tmp1 == '*' && strlen(Tmp1) == 1)) {
            SizeW = 6 + rand() % 6;
        }
        else { if (Err1 == Tmp1) Flag = 1; }
 
        SizeH = strtol(Tmp2, &Err2, 10);
        if ((SizeH < 5) || (Err2 == Tmp2 && *Tmp2 == '*' && strlen(Tmp2) == 1)) {
            SizeH = 10 + rand() % 11;
        }
        else { if (Err2 == Tmp2) Flag = 1; }
 
        if (Flag) { puts("Корявый ввод"); }
        else {
            if (SizeW > 65535) SizeW = 65535;
            if (SizeH > 65535) SizeH = 65535;
        }
 
    } while (Flag);
 
    printf("Ширина: %d ; Высота: %d\n\n", SizeW, SizeH); fflush(stdin);
}
 
int  InpKbdArr(__int16 * & Arr,  unsigned int & SizeW, unsigned int & SizeH)
{
    __int16 *ArrTmp = NULL, *ArrNew = NULL; unsigned int i, j, Flag; 
    char *Err1, Tmp1[23]; int Tmp2 = 0;
 
    ArrNew = (__int16*)realloc(ArrTmp, SizeW * SizeH * sizeof(*ArrTmp));
    if (ArrNew == NULL) { 
        free(ArrTmp); ArrTmp = NULL; puts("Ошибка памяти"); system("pause"); /*exit(1);*/ }
    else { Arr = ArrNew; j = 0; puts("Введите элементы масива [-32768..32767 или * или **]:");
 
    while (j < SizeH) { i = 0;
        while (i < SizeW)   {   
    
    do { do {   Flag = 0; printf("[%d; %d].. : ", j, i); scanf_s("%22s", Tmp1, 23);
        if (strlen(Tmp1) > 6) { Flag = 1; puts("Корявый ввод"); }
        } while (Flag);
 
        Tmp2 = strtol(Tmp1, &Err1, 10);
        if (Err1 == Tmp1 && *Tmp1 == '*' && strlen(Tmp1) == 1) {
            Tmp2 = 32767 - rand() % 65535;
        }
        else { if (Err1 == Tmp1) Flag = 1; }
 
        if (Flag == 1 && Tmp1[0] == '*' && Tmp1[0] == '*' && strlen(Tmp1) == 2) {
            puts("Будет сгенерирован случайный массив заданного размера."); 
            free(Arr); Arr = NULL; system("pause"); goto ExitFoo_InpKbdArr;
        }
        
        if (Flag) { puts("Корявый ввод"); }
        else {
            if (Tmp2 > +32767) { Tmp2 = +32767; printf("Коррекция вода: %d \n", Tmp2); }
            if (Tmp2 < -32768) { Tmp2 = -32768; printf("Коррекция вода: %d \n", Tmp2); }
        }
 
    } while (Flag);
 
    Arr[j * SizeW + i] = Tmp2; i++; } j++; } }
 
ExitFoo_InpKbdArr:
    puts("");
    if (Arr) { return 0; } else { return 1; }
}
 
int  GenRndArr(__int16 * & Arr,  unsigned int & SizeW, unsigned int & SizeH)
{
    __int16 *ArrTmp = NULL, *ArrNew = NULL; unsigned int i, j = 0; 
 
    ArrNew = (__int16*)realloc(ArrTmp, SizeW * SizeH * sizeof(*ArrTmp));
    if (ArrNew == NULL) { 
        free(ArrTmp); ArrTmp = NULL; perror("Ошибка памяти"); system("pause"); /*exit(1);*/ }
    else { Arr = ArrNew;
 
        while (j < SizeH) { i = 0;
            while (i < SizeW)   { Arr[j * SizeW + i] = 127 - rand() % 256; i++; } j++;
        } 
    }
 
    if (Arr) { return 0; } else { return 1; }
}
 
void PrintArr (__int16 * & Arr,  unsigned int & SizeW, unsigned int & SizeH)
{
    unsigned int i, j = 0;
 
    while (j < SizeH) { i = 0;
        while (i < SizeW) { printf("%6d ", Arr[j * SizeW + i]); 
            if ((i+1) % 11 == 0) puts(""); i++;
        } if (i % 11 != 0) puts(""); if (i > 11) puts(""); j++;
    } puts("");
}
 
int  FWriteArr(__int16 * & Arr,  unsigned int & SizeW, unsigned int & SizeH, FILE* & fArr, char * & Arr_txt)
{
    FILE * pArr = NULL; unsigned int i, j = 0;
 
    fopen_s(&pArr, Arr_txt, "wt+");
    if (pArr == NULL) { perror("Ошибка файла"); system("pause"); /*exit(1);*/ }
    else { fArr = pArr;
    
        while (j < SizeH) { i = 0;
            while (i < SizeW) { fprintf(fArr, "%6d ", Arr[j * SizeW + i]); i++; } 
            fprintf(fArr, "\n"); j++;
        }
    }
    fclose(pArr);
 
    if (pArr) { return 0; } else { return 1; }
}
 
int  FReadArr (__int16 * & Arr,  unsigned int & SizeW, unsigned int & SizeH, FILE* & fArr, char * & Arr_txt)
{
    FILE *pArr = NULL; struct _stat64 fArrBuf; __int16 *ArrTmp = NULL, *ArrNew = NULL;
    char *Err1, Str1[23] = "\0", k = 0, Flag = -1; SizeW = 0; SizeH = 0;
    unsigned int i = 0, j = 0, CurChar = 0, OldW = 0;
 
    fopen_s(&fArr, Arr_txt, "ab+");
    if (fArr == NULL) { perror("Ошибка файла: #0"); system("pause"); }
    else { _fstat64(_fileno(fArr), &fArrBuf); 
        if (fArrBuf.st_size == 0) { perror("Ошибка файла: #1"); system("pause"); }
        else { 
            SizeW = 1; SizeH = 1; _fseeki64(fArr, 0, 0);
            while (CurChar < 33) CurChar = getc(fArr); 
 
            puts("Чтение из файла: \n");
            do { if (Flag < 0) { ArrTmp = Arr;
                ArrNew = (__int16*)realloc(ArrTmp, SizeW * SizeH * sizeof(*ArrTmp)); 
                if (Flag == -2 && OldW && j) {
                    j = SizeH - 1; while (j > 0) {
                        memmove_s((__int16*)Arr[j * SizeW], OldW * sizeof(*Arr),  //куда и предел свободного места байт
                            /*      */(__int16*)Arr[j *  OldW], OldW * sizeof(*Arr)); //откуда и сколько байт
                        } 
                    }
                } j = SizeH - 1;
                if (ArrNew == NULL) {
                    free(ArrTmp); ArrTmp = NULL; perror("Ошибка памяти"); system("pause"); }
                else { Arr = ArrNew; 
 
                    while (CurChar > 32 && CurChar != EOF) { //анализ последовательности символов
                        Flag = 0; k = 0; memset(Str1, 0, 7);
                        do {
                            Str1[k] = CurChar;
                            CurChar = getc(fArr);
                        } while (++k < 23 && CurChar > 32 && CurChar != EOF); Str1[k] = 0;
 
                        Arr[j * SizeW + i] = (short)strtol(Str1, &Err1, 10);
                        if (Str1 == Err1) {
                            Arr[j * SizeW + i] = 127 - rand() % 256;
                            printf("%6d~", Arr[j * SizeW + i]);
                        }
                        else printf("%6d ", Arr[j * SizeW + i]);
                    } //end while (CurChar > 32 && CurChar != EOF)
 
                    while (CurChar < 33 && CurChar != EOF) { //анализ изменения размеров массива Arr
 
                        if (CurChar != 13 && CurChar != 10 && CurChar < 33 && CurChar != EOF) {
                            if (Flag == 0) Flag = 1;
                            while (CurChar != 13 && CurChar != 10 && CurChar < 33 && CurChar != EOF)
                                CurChar = getc(fArr);
                        }
                        if ((CurChar == 13 || CurChar == 10) && (CurChar < 33 && CurChar != EOF)) {
                            Flag = 2; i = 0; while (CurChar == 13 || CurChar == 10) CurChar = getc(fArr);
                        }
                        if (Flag == 1 && CurChar > 32 && CurChar != EOF) { ++i; Flag = 0;
                            if (i % 11 == 0 && i > 0) puts(""); } //форматирование
                        else if (Flag == 2 && CurChar > 32 && CurChar != EOF) { ++SizeH; ++j; Flag = -1;
                            if (SizeW > 11) puts(""); } //дополнительный отступ
                        if (i >= SizeW) { OldW = SizeW; SizeW = i; ++SizeW; Flag = -2; }
                        if (Flag == 2 && i == 0) puts(""); //конец строки
 
                    } //end while (CurChar < 33 && CurChar != EOF)
                } //end else for if (ArrNew == NULL)
            } while (CurChar != EOF); puts(""); fclose(fArr); 
        } //end else for if (fArrBuf.st_size)
    } //end else for if (fArr == NULL)
 
    if (pArr && fArrBuf.st_size) { return 0; } else { return 1; }
}
 
int  MaxInStr (__int16 * & Arr,  unsigned int & SizeW, unsigned int & SizeH, __int16 * & ArrX)
{
    __int16 *ArrTmp = NULL, *ArrNew = NULL; unsigned int i = 0, j = 0;
 
    ArrNew = (__int16*)realloc(ArrTmp, SizeH * sizeof(*ArrTmp));
    if (ArrNew == NULL) { 
        free(ArrTmp); ArrTmp = NULL; perror("Ошибка памяти"); system("pause"); /*exit(1);*/ }
    else { ArrX = ArrNew;
 
        while (j < SizeH) { i = 0; __int16 Max = numeric_limits<__int16>::min();
            while (i < SizeW) {
                if (Arr[j * SizeW + i] > Max) { ArrX[j] = Arr[j * SizeW + i]; Max = ArrX[j]; } i++;
            } j++;
        }
    }
 
    if (ArrX) { return 0; } else { return 1; }
}
 
int  FWrtArrX (__int16 * & ArrX, unsigned int & SizeH, FILE* & fArrX, char* & ArrX_bin)
{
    struct _stat64 fArrBuf; 
 
    fopen_s(&fArrX, ArrX_bin, "wb+"); 
    fwrite(ArrX, sizeof(*ArrX), SizeH, fArrX); 
    _fstat64(_fileno(fArrX), &fArrBuf); 
    fclose(fArrX); 
 
    return fArrBuf.st_size < sizeof(ArrX) ? 1 : 0;
}
 
int  FReadArrX(__int16 * & ArrX, unsigned int & SizeH, FILE* & fArrX, char* & ArrX_bin)
{
    struct _stat64 fArrBuf; char c = '-';
    
    fopen_s(&fArrX, ArrX_bin, "ab");
    _fseeki64(fArrX, 0, 0);
    _fstat64(_fileno(fArrX), &fArrBuf);
 
    if (fArrBuf.st_size == 0) {
        perror("Ошибка файла: #2"); puts("Чтение отменено."); system("pause"); 
    }
    else if (fArrBuf.st_size < sizeof(ArrX)) {
        perror("Ошибка файла: #3"); fclose(fArrX);
        puts("Считать файл? [ + / - ]"); c = _getch();
    }
    if (c == '+') { fopen_s(&fArrX, ArrX_bin, "rb");
        fread(ArrX, sizeof(*ArrX), SizeH, fArrX);
    } fclose(fArrX);
 
    return fArrBuf.st_size == 0 ? 2 : fArrBuf.st_size < sizeof(ArrX) ? 3 : 0;
}
 
void PrintArrX(__int16 * & ArrX, unsigned int & SizeH)
{
    unsigned int j = 0; puts("Максимальные значения в строках массива: ");
 
    while (j < SizeH) { 
        printf("%6d ", ArrX[j]); if ((j + 1) % 11 == 0) puts(""); j++; } 
    puts(""); if (j > 11) puts("");
}
 
void SearchMin(__int16 * & ArrX, unsigned int & SizeH, __int16 & Min)
{
    unsigned int i = 0, j = 0;
 
    while (j < SizeH) { if (ArrX[j] > 0 && ArrX[j] <= Min) { Min = ArrX[j]; i++; } j++; }
 
    printf("Минимальное положительное значение массива ArrX: "); 
    if (i) { printf("%d \n", Min); } else puts("NaN");
}


И ещё нужна помощь в переделывании последней функции void SearchMin(__int16 * & ArrX, unsigned int & SizeH, __int16 & Min) на рекурсию
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.08.2015, 13:35
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Передача массива в функцию используя указатель на функцию (C++):

Передача массива структур в функцию через указатель - C++
вот пример куска кода, не могу понять почему ругается на: void Add(student *ptr) { for(int i = 0; i&lt;lim; i++) { ...

Передача массива через указатель в шаблонную функцию - C++
Здравствуйте. В общем есть шаблонный класс List, который является двусвязным списком: template &lt;class Type&gt; class List { ...

Передача умного указателя в функцию принимающую указатель на указатель - C++
Итак имеется функция со следующим параметром: HRESULT __stdcall Function(SomeClass **param); В случае, когда создаём обычный...

Как сделать функцию, возвращающую указатель на функцию (которая в свою очередь возвращает указатель на массив) - C++
Изучаю c++ по одной книжке.Она говорить не умеет.. Так вот понадобилось написать функцию,которая как параметр получает указатель на...

Передача указателя на указатель в функцию - C++
Вопрос к знатокам: Есть абстрактный класс(Symbol) и его производный (Cross). Создаю указатель этого абстрактного класса(Symbol *first) ,...

Передача в функцию указателя на указатель - C++
Добавление нового элемента в начало списка: void Add_Beg(List **u, Data &amp;x) // Почему в 1 аргументе функции указатель на указатель? { ...

15
Ваю
17 / 17 / 1
Регистрация: 21.04.2015
Сообщений: 524
01.08.2015, 14:04  [ТС] #2
Думаю можно сделать если не передачу функций ввода массива, то передачу функции, описывающей массив, например, такой void Array(__int16 * & Arr, unsigned int & SizeW, unsigned int & SizeH), только я не соображу что должна делать такая функция или она просто должна быть типом данных, и класс для неё я не сделаю, только если просто структуру может быть.

Имеющиеся у меня примеры передачи ссылок на функции:
Кликните здесь для просмотра всего текста
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
#include <cstdlib>
#include <iostream>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
 
void Check          (char * Str1, char * Str2, int(*pFooName)(const char * Str1, const char * Str2));
int  CompValues (const char * Str1, const char * Str2);
 
int main(void)
{
    //если не обнулить Err1 - его адрес совпадёт с Str2 - ошибка множественного объявления
    setlocale(0, "ru-ru"); char Str1[80], Str2[80], *Err1 = NULL; 
 
    /* указатель на функцию и его инициализация именем стандартной функции */
    int(*pStrCmp)(const char *Str1, const char *Str2) = &strcmp; 
 
    printf("Введите две строки.\n"); gets_s(Str1, 79); gets_s(Str2, 79);
    strtol(Str1, &Err1, 10);
 
    /*  Передает адрес функции strcmp посредством указателя pStrCmp, 
    **  так же можно непосредственно подставить имя функции, 
    **  в этом случае объявлять указатель на функцию не нужно... 
 
    **  Здесь производится проверка на наличие ошибки преобразования 
    **  и если её нет, то - в качестве входящего значения передаётся 
    **  имя нашей функции, оно сразу подставляется как значение 
    **  переменной, подобно числу, т.е без передачи из некой 
    **  переменной, которая его хранит, иначе передаётся имя 
    **  стандартной функции strcmp посредствам указателя на неё...
 
    */  Str1 != Err1 ? Check(Str1, Str2, CompValues) : Check(Str1, Str2, pStrCmp); 
 
    system("pause");
}
 
void Check(char * Str1, char * Str2, int(*pFooName)(const char * Str1, const char * Str2))
{
    printf("Проверка на совпадение: ");
    pFooName(Str1, Str2) ? printf("Не равны") : printf("Равны"); puts(""); 
}
 
int CompValues(const char * Str1, const char * Str2)
{
    __int64 Val1 = 0, Val2 = 0; char *Err1, *Err2;
 
    Val1 = strtol(Str1, &Err1, 10); Val2 = strtol(Str2, &Err2, 10);
 
    return Val1 == Val2 && Str2 != Err2 ? 0 : 1;
}


Кликните здесь для просмотра всего текста
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
#include <cstdlib>
#include <iostream>
using namespace std;
 
struct user { char* name; char* id; int dept; };
typedef user* Puser;
typedef int(*CFT)(const void *, const void *);
 
void sort(void* base, unsigned n, unsigned int sz, CFT cmp);
void print_id(Puser v, int n);
int cmp1(const void * p, const void * q);
int cmp2(const void * p, const void * q);
 
user heads[] = {
  "Ritchie D.M.",    "dmr",   11271,
  "Sethi R.",        "ravi",  11272,
  "SZYmanski T.G.",  "tgs",   11273,
  "Schryer N.L.",    "nls",   11274,
  "Schryer N.L.",    "nls",   11275,
  "Kernighan B.W.",  "bwk",   11276
};
 
int main() 
{
  sort(heads, 6, sizeof(user), cmp1);
  print_id(heads, 6); // в алфавитном порядке
  cout << "\n";
  sort(heads, 6, sizeof(user), cmp2);
  print_id(heads, 6); // по номерам отделов
    cout << "\n";
    system("pause");
}
 
void sort(void* base, unsigned n, unsigned int sz, CFT cmp) {
    for (int i = 0; i < n - 1; i++)
    for (int j = n - 1; i < j; j--) {
        char* pj  = (char*)base + j * sz; // b[j]
        char* pj1 = pj - sz;              // b[j-1]
        if ((*cmp)(pj, pj1) < 0) { // поменять местами b[j] и b[j-1]
            for (int k = 0; k < sz; k++) {
                char temp = pj[k];
                pj[k] = pj1[k];
                pj1[k] = temp;
            }
        }   // Сортировка вектора "base" из n элементов в возрастающем порядке;
    }       // используется функция сравнения, на которую указывает cmp.
}           // Размер элементов равен "sz". Сортировка пузырьковым методом.
 
void print_id(Puser v, int n)
{
    for (int i = 0; i < n; i++)
        cout    << v[i].name    << '\t'
                    << v[i].id      << '\t'
                    << v[i].dept    << '\n';
}
 
// сравнение строк, содержащих имена
int cmp1(const void * p, const void * q)
{
    return strcmp(Puser(p)->name, Puser(q)->name);
}
 
// сравнение номеров разделов
int cmp2(const void * p, const void * q)
{
    return Puser(p)->dept - Puser(q)->dept;
}
0
Tulosba
:)
Эксперт С++
4396 / 3232 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
01.08.2015, 14:10 #3
Ваю, приведу для тебя простой пример работы с указателем на функцию:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
 
void f(int i) {
    std::cout << i << std::endl;
}
 
// Принимаем указатель на функцию fptr (которая принимает int и возвращает void)
// и целое число v 
void c( void(*fptr)(int), int v ) {
    fptr(v); // Вызываем функцию по указателю с передачей параметра
}
 
int main() {
   // Вызываем функцию "c", которая принимает аргументами функцию f и число 42
   c( f, 42 );
}
Я думаю, этого должно хватить для понимания.
0
Ваю
17 / 17 / 1
Регистрация: 21.04.2015
Сообщений: 524
01.08.2015, 14:24  [ТС] #4
Tulosba, да, такие примеры мне понятны, но что мне делать в моём случае - не до конца. Допусим я переделаю принимающую указатель функцию на такую - int MaxInStr (__int16 * & ArrX, void * Array), что мне потом нужно делать с этим, чтобы оно заработало? Нужно ли делать эту функцию типом данных? - из имеющихся у меня примеров вроде как и нет, но когда я стал пытаться делать - переменные оказались неинициализированными, поэтому пришлось объявить функцию ч.з typedef, но у меня не получилось доделать всё до конца

C++
1
void Array(__int16 * & Arr, unsigned int & SizeW, unsigned int & SizeH);
0
Tulosba
:)
Эксперт С++
4396 / 3232 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
01.08.2015, 14:30 #5
Цитата Сообщение от Ваю Посмотреть сообщение
что мне потом нужно делать с этим, чтобы оно заработало?
Если передаешь указатель на функцию внутрь другой функции, то, вероятно, в какой-то момент нужно ее вызвать через этот указатель.
Цитата Сообщение от Ваю Посмотреть сообщение
Нужно ли делать эту функцию типом данных?
Если под этим ты понимаешь создание typedef, то это не обязательно, но добавляет удобства при частом использовании указателя на функцию.
Цитата Сообщение от Ваю Посмотреть сообщение
но у меня не получилось доделать всё до конца
Опиши словами, что хочешь сделать. Не в терминах языка программирования, а в терминах задачи.
0
Ваю
17 / 17 / 1
Регистрация: 21.04.2015
Сообщений: 524
01.08.2015, 14:35  [ТС] #6
То, что мне осталось доделать выделено жирным.

Полный текст моего задания:

Условия выполнения:
Выбрать алгоритм, составить его блок-схему и программу для решения выбранного варианта задания. Программа должна по выбору пользователя осуществлять ввод исходной матрицы с клавиатуры или из файла. Для этого программа должна содержать две соответствующие функции, указатель на одну из которых необходимо передавать в функцию для вычисления элементов массива Х. Данная функция должна вызывать через указатель одну из функций ввода элементов матрицы, производить вычисление элементов массива X в соответствии с заданием и возвращать указатель на этот массив. Кроме того, программа должна содержать функцию для вывода на экран и в файл исходной матрицы и результирующего массива, а также рекурсивную функцию определения в соответствии с заданием величины Y. В программе не должно быть глобальных переменных.

Вариант задания:
Дана матрица А(5х5). Определить массив Х из 5 элементов, каждый из которых равен наибольшему элементу соответствующей строки матрицы. Определить величину Y, как наименьший из положительных элементов массива X.
0
Tulosba
:)
Эксперт С++
4396 / 3232 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
01.08.2015, 14:56 #7
1. Выделяем сигнатуру функции ввода из этих:
C++
1
2
int InpKbdArr(__int16 * & Arr, unsigned int & SizeW, unsigned int & SizeH);
int GenRndArr(__int16 * & Arr, unsigned int & SizeW, unsigned int & SizeH);
Получаем такой typedef (синоним типа):
C++
1
typedef int (*InputFun)(__int16 * & Arr, unsigned int & SizeW, unsigned int & SizeH);
Теперь InputFun - это у нас тип "указатель на функцию нужной нам сигнатуры"
2. Создаем прототип функции обработки (то, что ты выдел жирным).
C++
1
void Process( InputFun input, __int16 * & Arr, unsigned int & SizeW, unsigned int & SizeH )
В теле делаем вызов функции ввода:
C++
1
input( Arr, SizeW, SizeH );
и обработку массива (твой алгоритм).
3. В main() заводишь переменную (указатель на функцию ввода):
C++
1
InputFun input = InpKbdArr; // по умолчанию - "с клавиатуры"
запрашиваешь пользователя как он хочет сделать ввод и на основании его выбора задаешь значение переменной input.
Потом делаешь вызов ранее созданной функции:
C++
1
Process( input, Arr, SizeW, SizeH );
Вроде бы всё.
1
Kerry_Jr
Модератор
Эксперт PHP
2206 / 2002 / 701
Регистрация: 14.05.2014
Сообщений: 5,865
Записей в блоге: 1
Завершенные тесты: 5
01.08.2015, 15:12 #8
Цитата Сообщение от Tulosba Посмотреть сообщение
C++
1
void Process( InputFun input, __int16 * & Arr, unsigned int & SizeW, unsigned int & SizeH )
Цитата Сообщение от Ваю Посмотреть сообщение
в соответствии с заданием и возвращать указатель на этот массив
наверное лучше
C++
1
__int16 *Process( InputFun input, __int16 * & Arr, unsigned int & SizeW, unsigned int & SizeH )
0
Tulosba
:)
Эксперт С++
4396 / 3232 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
01.08.2015, 15:35 #9
Цитата Сообщение от Kerry_Jr Посмотреть сообщение
наверное лучше
Я сначала тоже так подумал, и даже написал, но перед отправкой на форум оставил void. Т.к. подумал, что возвращать можно и через ссылочные параметры. Как это делается в тех же функциях ввода. А через return было бы актуально для организации цепочек вызовов, но это не тот случай всё же.
В общем, если препод потребует, то ТС, я думаю, добавит
0
Ваю
17 / 17 / 1
Регистрация: 21.04.2015
Сообщений: 524
01.08.2015, 15:40  [ТС] #10
У меня возник вопрос по поводу пункта 2:

В последствии input становится переменной, имеющей 3 параметра для получения адреса массива, его ширины и высоты, далее в описании написано "В теле делаем вызов функции ввода", здесь input является именем той функции, с помощь которой пользователь захочет произвести ввод.

В моём случае это будет так?

C++
1
int MaxInStr (__int16 * & ArrX, int * input);
Вот это место я не очень и понимаю. Тело прототипа тоже представляю очень смутно :-(

Ниже Kerry_Jr предложил добавить указатель к функции, этого я тоже не знаю, имя функции = адрес функции, если к адресу добавить указатель - получается взятие значения функции, если я правильно понимаю, но функция в данном случае походу возвращает код отработки, а не значение переменной результата по средствам return, значит я понимаю это неправильно
0
Tulosba
:)
Эксперт С++
4396 / 3232 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
01.08.2015, 17:03 #11
Цитата Сообщение от Ваю Посмотреть сообщение
В последствии input становится переменной, имеющей 3 параметра
Переменная типа InputFun есть указатель на функцию соответствующей сигнатуры, то что было написано при создании синонима типа:
C++
1
typedef int (*InputFun)(__int16 * & Arr, unsigned int & SizeW, unsigned int & SizeH);
Нельзя говорить, что "переменная имеет параметры". Параметры есть у функции, на которую указывает переменная, но не у самой переменной.
Цитата Сообщение от Ваю Посмотреть сообщение
В моём случае это будет так?
Что "это"?
Цитата Сообщение от Ваю Посмотреть сообщение
если к адресу добавить указатель - получается взятие значения функции
Слишком витиевато рассуждаешь, трудно тебя понять. Ясно только, что ты "плаваешь" в терминологии. А использование "ссылок на указатели", типов из разряда __int16 (зачем именно такой тип для данной задачи?) и смеси сишного и плюсового кода только усугубляет ситуацию.

В общем, надо бы подтянуть уровень языка. Иначе просто не будет понимания, что из чего следует и зачем.
Если, конечно, оно действительно нужно, а не просто "сдать зачет" и забыть.
0
Ваю
17 / 17 / 1
Регистрация: 21.04.2015
Сообщений: 524
01.08.2015, 17:17  [ТС] #12
Цитата Сообщение от Tulosba Посмотреть сообщение
Нельзя говорить, что "переменная имеет параметры". Параметры есть у функции, на которую указывает переменная, но не у самой переменной.
я не умею правильно выражаться, но вы меня поняли, смесь си и си++ у меня по большей части только в вводе/выводе из-за макросов или как там они называются, я про %d и подобное, они в простом си удобнее и проще, выделение памяти использую от си, поскольку оно более гибкое, нежели просто new/delete, им покрайней мере мне пользоваться удобнее. Без использования ссылок на указатели будет невозможно сделать кое что в программе, без них получается некрасиво, а на счёт типов данных - так просто мне удобнее, сразу видно объём памяти занимаемой переменной, не нужно вспоминать что такое Short

Под "это" я понимал 2 пункт, с которым я не разобрался до конца и по которому задал вопрос.

2. Создаем прототип функции обработки (то, что ты выдел жирным).

C++
1
void Process( InputFun input, __int16 * & Arr, unsigned int & SizeW, unsigned int & SizeH )
В теле делаем вызов функции ввода:

C++
1
input( Arr, SizeW, SizeH );
и обработку массива (твой алгоритм).
0
Tulosba
:)
Эксперт С++
4396 / 3232 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
01.08.2015, 17:42 #13
Цитата Сообщение от Ваю Посмотреть сообщение
Данная функция должна вызывать через указатель одну из функций ввода элементов матрицы, производить вычисление элементов массива X в соответствии с заданием и возвращать указатель на этот массив.
Разбираем по частям:
Цитата Сообщение от Ваю Посмотреть сообщение
Данная функция
Речь о функции, которую я назвал Process
Цитата Сообщение от Ваю Посмотреть сообщение
должна вызывать через указатель
Сначала надо в Process передать указатель (input), а потом сделать вызов:
C++
1
input( Arr, SizeW, SizeH );
Цитата Сообщение от Ваю Посмотреть сообщение
одну из функций ввода элементов матрицы
Это выбирает пользователь, в результате чего переменная (input) внутри main
(тут стоит уточнить, что input внутри main, и input внутри Process - это разные переменные,
но значение из первой (что в main) при вызове Process копируется во вторую)
принимает значение либо InpKbdArr, либо GenRndArr.
Цитата Сообщение от Ваю Посмотреть сообщение
производить вычисление элементов массива X в соответствии с заданием
Обрабатываешь данные должным образом. Т.е. из матрицы получаешь массив.
Цитата Сообщение от Ваю Посмотреть сообщение
и возвращать указатель на этот массив.
Тут всё таки надо добавить в сигнатуру Process возврат указателя (Kerry_Jr оказался прав).
Т.о. будет выглядеть так:
C++
1
__int16 *Process( InputFun input, __int16 * & Arr, unsigned int & SizeW, unsigned int & SizeH )

Не по теме:

P.S. по поводу гибкости, макросов, new/delete и прочего ты заблуждаешься по большей части. Но для этого, имхо, надо отдельную тему создавать.

0
Ваю
17 / 17 / 1
Регистрация: 21.04.2015
Сообщений: 524
02.08.2015, 06:05  [ТС] #14
Вызов input( Arr, SizeW, SizeH ); похож на указатель во 2м примере в 39й строке, только я неочень понимаю его, почему так и зачем там 6я строка вообще, как там работает сортировка, вычисление размеров

Не по теме:

Без кода я не понимаю этого места и это не для того чтоб просто сдать и забыть, я 4й раз уже пытаюсь разобраться за последние 15 лет, но не получается, мне не у кого спрашивать как надо, у меня нет знакомомых, умеющих пользоваться компьютером, и у знакомых знакомых - тоже, я могу разбираться только на работающих аналогичных примерах, книги мне недостаточно, там нельзя найти ответы на всё, да и часто тучи опечаток из-за которых у меня ничего не получается

0
Tulosba
:)
Эксперт С++
4396 / 3232 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
02.08.2015, 09:15 #15
Цитата Сообщение от Ваю Посмотреть сообщение
указатель во 2м примере в 39й строке
C++
39
PrintArr(Arr, SizeW, SizeH); //Вывести массив Arr на экран
Тут обычный (прямой) вызов функции PrintArr.
По твоему же заданию надо сделать косвенный вызов InpKbdArr, либо GenRndArr.
И это делается через переменную input.
Цитата Сообщение от Ваю Посмотреть сообщение
зачем там 6я строка вообще
Это которая?
Цитата Сообщение от Ваю Посмотреть сообщение
как там работает сортировка, вычисление размеров
Эти вопросы уже выходят за границы текущей темы.
0
02.08.2015, 09:15
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.08.2015, 09:15
Привет! Вот еще темы с ответами:

Передача двухмерного массива из функцию в функцию - C++
Допустим у меня есть функция, в которой &quot;генерируется&quot; массив. Но нужно его передать в другую функцию, которая его выведет на экран. ...

Записать указатель на функцию, не используя typedef - C++
Имеется переменная - указатель на функцию fptr. Написать эту же переменную fptr, не используя typedef'ы /* Указатель на функцию void...

В функцию-метод передать указатель на другую функцию-метод и вызвать через переданный указатель - C++
Друзья! Всем привет. Вот код: class otets { public: void f (void (otets::*p)()); private: void echo_f (){}; ...

Зачем передавать в функцию X указатель на callback функцию, если последняя ВНЕШНЯЯ и вызовется БЕЗО ВСЯКОГО УКАЗАТЕЛЯ? - C++
Собсно. То есть ребята, вот пример отсюда: http://www.cplusplus.com/reference/algorithm/count_if/ // count_if example #include...


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

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

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