Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 21.12.2012, 18:34   #1
Joose
Пользователь
 
Регистрация: 16.10.2011
Сообщений: 67
По умолчанию Массив из сторон треугольников

Всем привет. Есть простенькая программа, которая случайным образом создает двумерный массив, в котором каждая строка состоит из сторон треугольника. Программа находит площадь из этих сторон (при условии что из этих сторон можно составить треугольник) и печатает ее для каждого треугольника. Однако программа работает некорректно при значении количества треугольников свыше 15.

Код:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <limits.h>
#include <math.h>
#include "locale.h"
#define N 3

float* Function(float**, int);

int main()
{
    setlocale(LC_CTYPE, "RUSSIAN");
    int i, j, k, num;
    srand(time(NULL));                                                      //Рандомизация
    float **ms1, *sq;
    printf("Введите колличество треугольников:\n");
    scanf("%d", &num);
    printf("\nИсходная матрица сторон треугольника:\n\n");
    for(i = 0; i < num; i++)
    {
        printf("%d.", i+1);
        ms1[i] = (int*)malloc(N * sizeof(int));
        for(j = 0; j < N; j++)
        {
            printf("%15f", ms1[i][j] = 50*(float)(rand()) / RAND_MAX );       //Заполняем массив случайными значениями и печатаем очередное значение элемента
        }
        printf("\n");                                                         //Переходим на новую строку
    }
    printf("\nПлощади треугольников:\n\n");
    for(k = 0; k < num; k++)
    {
        sq = Function(ms1, num);
        if (sq[k] == -1)
            printf("Из данных сторон невозможно составить треугольник\n");
        else
        printf("Площадь %d-го треугольника равна: %f\n", k+1, sq[k]);
    }
    return 0;
}

float* Function(float** ms1, int m)
{
    int i;
    float *arr, p;
    for(i = 0; i < m; i++)
    {
            if (ms1[i][0] + ms1[i][1] > ms1[i][2] &&                                   //Проверяем, могут ли числа быть сторонами треугольника
                ms1[i][0] + ms1[i][2] > ms1[i][1] &&
                ms1[i][1] + ms1[i][2] > ms1[i][0])
                {
                    p = (ms1[i][0] + ms1[i][1] + ms1[i][2]) / 2;                       //Вычисляем полупериметр
                    arr[i] = sqrt(p * (ms1[i][0]) * (ms1[i][1]) * (ms1[i][2]));        //Находим площадь по формуле Герона и присваиваем

                }                                                                      // очередному элементу нового массива
                else
                arr[i] = -1;
    }
    return arr;
}
Плюс ко всему присутствуют некоторые не фатальные ошибки, думаю дело в них. Программа довольно проста, но разобраться что-то не получается. Может быть свежий взгляд более опытных программистов засечет ошибку. Заранее спасибо.

Последний раз редактировалось Joose; 21.12.2012 в 19:04.
Joose вне форума Ответить с цитированием
Старый 21.12.2012, 19:09   #2
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Код:
float **ms1
float *arr
Не выделена память.
Надо бы типа так:
Код:
ms1 = new float*[num];
arr = new float[m];
И здесь
Код:
 ms1[i] = (int*)malloc(N * sizeof(int));
Надо : ms1[i] = (float*)malloc(N * sizeof(float));
EUGY вне форума Ответить с цитированием
Старый 21.12.2012, 19:44   #3
Joose
Пользователь
 
Регистрация: 16.10.2011
Сообщений: 67
По умолчанию

Память выделяется функцией malloc циклически для каждой строки. Если бы она не выделялась, то программа вообще не работала, разве не так? Если честно впервые вижу выделение памяти через new. За тип перед malloc спасибо большое, совсем забыл что я делю на RAND_MAX! Но все же не совсем понял что Вы имели ввиду когда говорили о выделении памяти.
Joose вне форума Ответить с цитированием
Старый 21.12.2012, 19:44   #4
Smogg
Участник клуба
 
Регистрация: 14.06.2011
Сообщений: 1,138
По умолчанию

Ошибки синтаксиса - это понятно, но самое интересное происходит в "function".
При каждом ее вызове происходит выделение памяти. Все хорошо, если заранее точно известно, что функция вызовется наверняка один лишь раз.

Но она вызывается в цикле.

"Кто выделил память, тот ее и освобождает"
Smogg вне форума Ответить с цитированием
Старый 21.12.2012, 19:53   #5
Smogg
Участник клуба
 
Регистрация: 14.06.2011
Сообщений: 1,138
По умолчанию

Цитата:
Сообщение от Joose Посмотреть сообщение
Но все же не совсем понял что Вы имели ввиду когда говорили о выделении памяти.
Прочитайте про способ реализации многомерных массивов.
Кратко, двумерный массив - это совокуность отдельных одномерных массивов, на которые содержатся ссылки в "главном массиве". Т.е. вы выделяете память под отдельные массивы, а "главного" массива у вас нет.
Smogg вне форума Ответить с цитированием
Старый 21.12.2012, 20:00   #6
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Цитата:
Память выделяется функцией malloc циклически для каждой строки.
Это так. Но потом указатели на выделенную память для трех сторон треугольника копируются в массив память для которого не выделена.
С new это конечно для с++. А для си так:
ms1 = (float**) malloc( num * sizeof(float*));
Вот массив для приема num указателей готов.
А в цикле, как у Вас и написано, выделяется память под каждый элемент массива.
И я присоединяюсь к
Цитата:
самое интересное происходит в "function".
EUGY вне форума Ответить с цитированием
Старый 21.12.2012, 20:27   #7
Joose
Пользователь
 
Регистрация: 16.10.2011
Сообщений: 67
По умолчанию

Цитата:
Сообщение от Smogg Посмотреть сообщение
Ошибки синтаксиса - это понятно, но самое интересное происходит в "function".
При каждом ее вызове происходит выделение памяти. Все хорошо, если заранее точно известно, что функция вызовется наверняка один лишь раз.

Но она вызывается в цикле.

"Кто выделил память, тот ее и освобождает"
Согласен, функция вызывается в цикле, что делать совсем не нужно. С этим понятно. Но выделение памяти происходит лишь при заполнении массива. При вызове функции память не выделяется, верно? В любом случае я вынес вызов функции из цикла, но ничего не изменилось:
Код:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include "locale.h"
#define N 3

float* Function(float**, int);

int main()
{
    setlocale(LC_CTYPE, "RUSSIAN");
    int i, j, k, num;
    srand(time(NULL));                                                      //Рандомизация
    float **ms1, *sq;
    printf("Введите колличество треугольников:\n");
    scanf("%d", &num);
    printf("\nИсходная матрица сторон треугольника:\n\n");
    for(i = 0; i < num; i++)
    {
        printf("%d.", i+1);
        ms1[i] = (float*)malloc(N * sizeof(float));
        for(j = 0; j < N; j++)
        {
            printf("%15f", ms1[i][j] = 50*(float)(rand()) / RAND_MAX );       //Заполняем массив случайными значениями и печатаем очередное значение элемента
        }
        printf("\n");                                                         //Переходим на новую строку
    }
    printf("\nПлощади треугольников:\n\n");
    sq = Function(ms1, num);
    for(k = 0; k < num; k++)
    {
        if (sq[k] == -1)
            printf("Из данных сторон невозможно составить треугольник\n");
        else
        printf("Площадь %d-го треугольника равна: %f\n", k+1, sq[k]);
    }
    return 0;
}


float* Function(float** ms1, int m)
{
    int i;
    float *arr, p;
    for(i = 0; i < m; i++)
    {
            if (ms1[i][0] + ms1[i][1] > ms1[i][2] &&                                   //Проверяем, могут ли числа быть сторонами треугольника
                ms1[i][0] + ms1[i][2] > ms1[i][1] &&
                ms1[i][1] + ms1[i][2] > ms1[i][0])
                {
                    p = (ms1[i][0] + ms1[i][1] + ms1[i][2]) / 2;                       //Вычисляем полупериметр
                    arr[i] = sqrt(p * (ms1[i][0]) * (ms1[i][1]) * (ms1[i][2]));        //Находим площадь по формуле Герона и присваиваем
                }                                                                      // очередному элементу нового массива
                else
                arr[i] = -1;
    }
    return arr;
}
Joose вне форума Ответить с цитированием
Старый 21.12.2012, 20:34   #8
Joose
Пользователь
 
Регистрация: 16.10.2011
Сообщений: 67
По умолчанию

Цитата:
Сообщение от Smogg Посмотреть сообщение
Прочитайте про способ реализации многомерных массивов.
Кратко, двумерный массив - это совокуность отдельных одномерных массивов, на которые содержатся ссылки в "главном массиве". Т.е. вы выделяете память под отдельные массивы, а "главного" массива у вас нет.
Спасибо Вам, понял наконец что про основной массив, который содержит в себе массивы строк я совсем забыл.
Joose вне форума Ответить с цитированием
Старый 21.12.2012, 20:36   #9
Smogg
Участник клуба
 
Регистрация: 14.06.2011
Сообщений: 1,138
По умолчанию

Ну, а чтоб совсем все было красиво - пред окончание программы верните системе всю выделенную память. (Хотя система сама прибирается за любой программой, но все же в отдельных моментах она этого не делает.)

Последний раз редактировалось Smogg; 21.12.2012 в 20:43.
Smogg вне форума Ответить с цитированием
Старый 21.12.2012, 20:46   #10
Joose
Пользователь
 
Регистрация: 16.10.2011
Сообщений: 67
По умолчанию

Цитата:
Сообщение от Smogg Посмотреть сообщение
Ок. Давайте от начала. Есть две строчки:

float **arr;
arr[0] = (float*)malloc(sizeof(float));

Объясните, что здесь произойдет.
Для нулевой строки массива строк происходит выделение памяти, достаточной для размещения в ней 3 элементов типа int.
Joose вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
процедуры и функции - возможно ли построение треугольника по длинам сторон, вычисление площади треугольника по длинам сторон kazbek1 Паскаль, Turbo Pascal, PascalABC.NET 2 18.05.2012 10:38
Фон с двух сторон AlexSilver HTML и CSS 0 21.03.2012 11:19
Реализовать программу сбора елки из треугольников. Используя объектные структуры, создать 6 треугольников разного размера dyozik Общие вопросы Delphi 4 05.12.2011 11:52
Си/Си++ Существование сторон треугольника. Маришка_Курносова Помощь студентам 2 01.07.2010 21:54
Диаграммы, легенда с 2 сторон. WIC Microsoft Office Excel 8 02.10.2007 17:17