Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Образовательный студенческий форум _ Информатика / Программирование _ С++ нахождения площади и периметра треугольника по координатам

Автор: InFuz 11.3.2010, 14:16

В общем закончили 1 семестр и во втором начался C++ (был и остался Pascal)
Посоветуйте какую нибудь книжку или самоучитель по C++.
Пока читаю Г. Шилд "Самоучитель С++"

И помогите разобраться с 1 лабой. Мало того, что в С++ пока не рублю так еще и задача... я ее даже на листке не решу не то что уж прогу по ней писать.

Известны координаты вершин треугольника ABC: A(x1,y1), B(x2,y2) и C(x3,y3). Найти
его площадь и периметр.

Нашел в инете пару формул, хотя точно не уверен что те.
Вот, что пока смог накорябать.

# include <iostream.h>
# include <stdio.h>
# include <math.h>

int main()

{
int x1,x2,x3,y1,y2,y3;
double s,p,a,b,c;
cout<<"\n Лабораторная работа №1";
cout<<"\n x1="; cin>>x1;
cout<<"\n x2="; cin>>x2;
cout<<"\n x3="; cin>>x3;
cout<<"\n y1="; cin>>y1;
cout<<"\n y2="; cin>>y2;
cout<<"\n y3="; cin>>y3;
a = sqrt((x1-x2)^2+(y1-y2)^2);
b = sqrt((x1-x3)^2+(y1-y3)^2);
c = sqrt((x2-x3)^2+(y2-y3)^2);
p = a+b+c;
cout<<"\n p=" <<p;
/* cout<<"p="<<p;
s=(x1-x3)*(y2-y3)*(x2-x3)*(y1-y3)/2;
cout<<"s="<<s; */
}

Автор: Евгений М. 11.3.2010, 15:09

Формула Герона.

pp=p*0.5;
s=sqrt(pp*(pp-a)*(pp- b )*(pp-c));

Не забудьте объявить pp как double.

Автор: InFuz 11.3.2010, 16:15

Пару вопросов.
Что такое pp (p я так понимаю пириметр).
И как избавиться от ошибки когда вычисляется a, b, c и значение под корнем становиться отрицательным, например для треугольника а(1,1) b(-1,1) c(0,-1).

Автор: Pavlov Andrey 11.3.2010, 16:25

да pp - у него это периметр, а в Героне надо полу-периметр(p)
когда находишь длины сторон, поставь mod или abs (не помню, ну общем можно и самому написать функцию, возвращающую |x|(модуль) )))))
А хотя, я что то не понимаю, где там может быть отрицательное значение????

Автор: InFuz 11.3.2010, 18:01

да фиг его знает, когда вводишь а(1,1) b(-1,1) c(0,-1) выдает ошибку что значение под корнем отрицательное, хотя по формуле ничего подобного нет.

Сделал вот так вроде работает, только фиг его знает правильно считает или нет biggrin.gif
Попробую такую сдать.

# include <iostream.h>
# include <stdio.h>
# include <math.h>

int main()

{
int x1,x2,x3,y1,y2,y3;
double s,p,pp,a,b,c;
cout<<"\n Лабораторная работа №1";
cout<<"\n ";
cout<<"\n Введите x1="; cin>>x1;
cout<<" Ввидите y1="; cin>>y1;
cout<<" Введите x2="; cin>>x2;
cout<<" Ввидите y2="; cin>>y2;
cout<<" Ввидите x3="; cin>>x3;
cout<<" Ввидите y3="; cin>>y3;
a = sqrt (abs (((x1-x2)^2+(y1-y2)^2)));
b = sqrt (abs (((x1-x3)^2+(y1-y3)^2)));
c = sqrt (abs (((x2-x3)^2+(y2-y3)^2)));
p = a+b+c;
cout<<"\n p=" <<p;
pp=p/2;
//Формула Герона
s=sqrt(pp*(pp-a)*(pp- b )*(pp-c));
cout<<"\n s=" <<s;
}

Автор: Dimka 11.3.2010, 18:20

выведите на экран промежуточные значения a,b,c,p
abs- зачем используете?

Автор: InFuz 11.3.2010, 18:37

без abs выдает ошибку что значение под корнем отрицательное хотя это не так.
p и так выводит это по условию надо найти. вот с a b c еще

# include <iostream.h>
# include <stdio.h>
# include <math.h>

int main()

{
int x1,x2,x3,y1,y2,y3;
double s,p,pp,a,b,c;
cout<<"\n Лабораторная работа № 1";
cout<<"\n Вариант № 21";
cout<<"\n ";
cout<<"\n Введите x1="; cin>>x1;
cout<<" Ввидите y1="; cin>>y1;
cout<<" Введите x2="; cin>>x2;
cout<<" Ввидите y2="; cin>>y2;
cout<<" Ввидите x3="; cin>>x3;
cout<<" Ввидите y3="; cin>>y3;
a = sqrt (abs (((x1-x2)^2+(y1-y2)^2))); cout<<" a=" <<a ;
b = sqrt (abs (((x1-x3)^2+(y1-y3)^2))); cout<<"\n b=" <<b ;
c = sqrt (abs (((x2-x3)^2+(y2-y3)^2))); cout<<"\n c=" <<c ;
p = a+b+c;
cout<<"\n p=" <<p;
pp=p/2;
//Формула Герона
s=sqrt(pp*(pp-a)*(pp- b )*(pp-c));
cout<<"\n s=" <<s;
}

Автор: Dimka 11.3.2010, 18:46

да Вы не для меня выводите эти значения, а для себя.
Если без abs выдает "под корнем отрицательное значение",
sqrt ( (((x1-x2)^2+(y1-y2)^2)) )

то нужно вывести значение выражения, под корнем и проверить его на отрицательность. Если оно действительно отрицательно, значит или Вы что-то не то делаете или система считает неправильно

Автор: InFuz 11.3.2010, 19:09

Да я знаю что не для вас, не надо так сурово (:

как исправить ошибку function "sqr" should have a prototype;
здесь.
aa= sqr (x2-x3);

Автор: Dimka 11.3.2010, 19:34

sqr что ознгачает?

Автор: InFuz 11.3.2010, 19:35

возведение в квадрат.

Автор: граф Монте-Кристо 11.3.2010, 19:42

Видимо, в math.h нету такой функции. Можно написать её самому, либо вместо sqr(x) писать x*x. Можно ещё поюзать pow, но она работать будет дольше,чем x*x.

Автор: InFuz 11.3.2010, 19:51

я в принципе и хотел написать в виде х*х, просо с sqr (х) короче и аккуратнее бы получилось ну ладно напишу х*х
вот конечный вариант, щас все вроде правильно, ошибка была в том что она не понимала ^2 (и sqr) пришлось писать х*х

# include <iostream.h>
# include <stdio.h>
# include <math.h>

int main()

{
int x1,x2,x3,y1,y2,y3;
double s,p,pp,a,b,c,aa;
cout<<"\n Лабораторная работа № 1";
cout<<"\n ";
cout<<"\n Введите x1="; cin>>x1;
cout<<" Ввидите y1="; cin>>y1;
cout<<" Введите x2="; cin>>x2;
cout<<" Ввидите y2="; cin>>y2;
cout<<" Ввидите x3="; cin>>x3;
cout<<" Ввидите y3="; cin>>y3;
a = sqrt (((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2))); cout<<" a=" <<a ;
b = sqrt (((x1-x3)*(x1-x3))+((y1-y3)*(y1-y3))); cout<<"\n b=" <<b ;
c = sqrt (((x2-x3)*(x2-x3))+((y2-y3)*(y2-y3))); cout<<"\n c=" <<c ;
p = a+b+c;
cout<<"\n p=" <<p;
pp=p/2;
//Формула Герона
s=sqrt(pp*(pp-a)*(pp- b )*(pp-c));
cout<<"\n s=" <<s;
}

Автор: Dimka 11.3.2010, 19:54

на счётах быстрее посчитаешь площадь. Уже 2 часа идет отладка программы

Автор: InFuz 11.3.2010, 19:59

biggrin.gif
если бы я лучше знал язык я бы может и после первой подсказки сделал все.
да и интернет форум куда медленнее для общения чем хотя бы icq

Автор: InFuz 12.3.2010, 17:36

Лаба №2

Определить, является ли последовательность из N произвольных чисел знакочереду-
ющейся.


Честно говоря, чот нет идей никаких. За окончание последовательности возьмем 0. А дальше чот даже не знаю с чего начать.

Шаблон:

# include <iostream.h>
# include <stdio.h>
# include <math.h>

int main()

{
int a;
cout<<"\n Лабораторная работа № 2";
cout<<"\n ";
cout<<"\n Введите элемент последовательности (конец последовательности - 0 -)";
cout<<"\n "; cin>>a;
cout<<"\n ";
while (a != 0);
{ ...
ыыы
...
cout <<"Последовательность знакочередующаяся";
cout <<"Последовательность не знакочередующаяся";
}
}

Автор: Vahappaday 12.3.2010, 19:54

Цитата(InFuz @ 12.3.2010, 17:36) *

Лаба №2

Определить, является ли последовательность из N произвольных чисел знакочередующейся.

Честно говоря, чот нет идей никаких. За окончание последовательности возьмем 0. А дальше чот даже не знаю с чего начать.


Код
# include <iostream>
# include <stdio.h>
# include <conio.h>

using namespace std;

int main()
{

    int a,b=0;
    bool alter=true;
    _wsetlocale(LC_ALL,L"Russian");
    cout<<"\n Лабораторная работа № 2";
    cout<<"\n ";
    cout<<"\n Введите элемент последовательности (конец последовательности - 0 -)";
    cout<<"\n "; cin>>a;
    while (a != 0)
    {
        if((a*b)>0)
        {
            alter=false;
        }
        b=a;
        cout<<"\n Введите элемент последовательности (конец последовательности - 0 -)";
        cout<<"\n "; cin>>a;
    }
    if(alter) cout <<"Последовательность знакочередующаяся";
    else cout <<"Последовательность не знакочередующаяся";
    getch();
    return 0;
}


Компилил в студии (Microsoft Visual Studio 2008), посему дам несколько комментариев:

1. # include <iostream> - <iostream.h> у меня студия просто не нашла, либо я что-то не так делаю, либо это и впрям устаревший заголовочный файл.

2. using namespace std; - обязательно, как без него работала прошлая лаба, удивляюсь.

3. _wsetlocale(LC_ALL,L"Russian"); - без этой строчки у меня, лично, бракозябри в консоли вместо русского языка.

4. getch() - ждёт ввода символа, добавил, чтобы можно было смотреть результат работы. Хотя, конечно, этого можно добиться и запуская по Ctrl+F5 в студии, наверное, и в вашей среде, если она отличается, есть что-то такое.

5. #include <conio.h> - нужно для работы getch();



Ещё какие-то комментарии нужны?
Кстати, на какой специальности учитесь? Что-то связанное с информатикой/программированием/ИТ или нет?

Автор: InFuz 12.3.2010, 21:06

я компилю в borland c++ 3.1 т.к. и сдавать лабы нужно в ней.
подредактировал под свой компилятор, вроде работает все норм, спасибо вам

# include <iostream.h>
# include <stdio.h>
# include <math.h>

int main()
{
int a,b=0,alter=1;
cout<<"\n Лабораторная работа № 2";
cout<<"\n ";
cout<<"\n Введите элемент последовательности (конец последовательности - 0 -)";
cout<<"\n"; cin>>a;
while (a != 0)
{
if((a*b )>0) //не понял как тут работает ведь b=0 и a*b всегда будет 0
{
alter=0;
}
b=a;
cin>>a;
}
if(alter) cout <<"Последовательность знакочередующаяся";
else cout <<"Последовательность не знакочередующаяся";
}

using namespace std; - обязательно, как без него работала прошлая лаба, удивляюсь.
это издержки моего компилятора.

Кстати, на какой специальности учитесь? Что-то связанное с информатикой/программированием/ИТ или нет?
да "Прикладная математика и информатика", в 1 семестре изучали Pascal (хотя и сейчас продолжаем), я его еще по школе более менее знал, так что с ним особых проблем небыло, а вот во 2 семестре еще C++ добавилось, вот учу потихоньку.

Автор: Vahappaday 12.3.2010, 21:32

Цитата(InFuz @ 12.3.2010, 21:06) *

да "Прикладная математика и информатика"

Тогда больше готового кода не будет, только подсказки))

Цитата(InFuz @ 12.3.2010, 21:06) *

if((a*b )>0) //не понял как тут работает ведь b=0 и a*b всегда будет 0


Чуть ниже есть строчка b=a;, она и меняет значение. Суть вот в чём. Мы каждую итерацию "запоминаем" значение предыдущего элемента в b.
В следующей итерации проверяем положительность произведения a*b - если произведение положительно, то предыдущий и текущий элемент одного знака - выставляем флаг и, фактически, дальше программу можно не выполнять.

Если же все произведения были неположительными (0 допустим для 1-й итерации, когда b=0), то флаг alter так и останется true, в конце выводится Последовательность знакочередующаяся. Если же хоть одно произведение было положительным, мы не можем считать такую последовательность положительной и выводим Последовательность не знакочередующаяся.

Кстати, зачем bool убрали? Судя по cin, cout используется STL. Раз используется STL - перед нами C++. Раз C++, то bool абсолютно корректен. Хотя... Вам виднее) Не видел я эту версию борланда и ничего утверждать не берусь)

Автор: InFuz 13.3.2010, 9:56

ясно, первая итерация как бы проходит в холостую (т.к. один элемент не является еще последовательностью).

да это С++, хотя # include <iostream.h> и отсутствие using namespace это как в С

в 3.1 нет типа bool как такового он появляется в версиях 5 и старше, так что приходится в место него использовать тип целых чисел где 0=false, а 1=true.

Автор: Vahappaday 13.3.2010, 11:00

Цитата(InFuz @ 13.3.2010, 9:56) *

ясно, первая итерация как бы проходит в холостую (т.к. один элемент не является еще последовательностью).

Именно так)

Автор: InFuz 30.3.2010, 12:28

Лаба №4

Дан массив целых простых чисел. Переписать все простые числа из заданного массива в другой массив. Первый массив упорядочить по возрастанию, второй по убыванию. Создать функции для для определения простого числа и для сортировки элементов массива.
P.S. "обязательное применение динамических массивов"


Начал по лекциям разбираться с динамическим массивом, пытался отладить пример который нам давали но он выдает ошибку, не смог понять че ему надо

# include <iostream.h>
# include <stdio.h>
# include <math.h>
# include <conio.h>
# include <alloc.h>

int main()
{ clrscr();
int i,n;
float * a;
float s;
cout<<"n="; cin>>n;
a=(float *) malloe (n * sizeof(float)); //<==тута "function 'malloe' should have a prototype"
a=new float[n];
cout<<"El-ma \n";
for (i=0; i<n; i++) cin>>* (a+i);
s+=*(a+i);
cout<<"s=" <<s<<"\n";
return 0;
getch();
}


написал еще на pascale пока функцию для определения простое число или нет

Writeln('Vvedite 4islo');
Readln( R );
if (R = 1) or (R = 2) then Writeln('Prostoe 4islo')
else if (R mod 2 = 0) then Writeln('Sostavnoe 4islo')
else begin
I := 3;
while R mod I <> 0 do
I:= I + 2;
if R <= I then Write('Prostoe 4islo')
else Write('Sostavnoe 4islo');
end;


Vahappaday надеюсь на ваши подсказки ))

Автор: граф Монте-Кристо 30.3.2010, 13:05

Цитата(InFuz @ 30.3.2010, 16:28) *

a=(float *) malloe (n * sizeof(float)); //<==тута "function 'malloe' should have a prototype"

Не malloe, a malloc.

Автор: InFuz 30.3.2010, 15:00

biggrin.gif

Автор: Vahappaday 31.3.2010, 4:07

ой... а зачем и new и malloc? и ни разу не освобождена память))) ай-яй-яй))

Рекомендую почитать про выделение памяти в некоторых старых версиях Builder'a. Мне один опытный человек говорил, что у Borland был косяк либо с new/delete, либо с malloc/free, скорее с первым. Хотя я могу и ошибаться.

getch() после return 0; не имеет смысла.

Насчёт нового массива. Есть два варианта.
1. Функция сама изнутри сначала делает проход и считает.
2. Мы должны передавать функции указатель на уже выделенную область памяти.

Первый вариант.... понадёжней, что ли. Исключает ошибки при вызове.
Если будете делать по второму, то я бы сделал что-то типа

int CopySimples(float *src, float *dst);

И если передать dst=NULL, то ничего не копировать, а просто считать и возвращать количество элементов.
Затем выделять память под такое количество элементов и уже передавать нормальный указатель.

Я думаю в этом случае проще реализовать 1-й вариант.
Главное, не забывать освобождать память, а то привыкнете.

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

Насчёт сортировки: каким методом сортировать будем? Пузырьком? Чем-то посложнее? Можно вообще воспользоваться встроенным qsort'ом

Добавлено:
Пришла ещё мысль сделать функцию добавления массива к числу. То есть, мы должны выделить память на 1 больше имеющегося, скопировать старый в новый, дописать новое число, освободить память из под старого, вернуть указатель на новый.
Вариантов куча на самом деле))
Определяйтесь, и пробуйте писать. Где будет тяжело - подмогу.

Автор: InFuz 31.3.2010, 10:54

Пока делаю без функций т.к. с ними еще не разобрался.
Вот так пока получается, вроде переделал функцию из паскалевской без изменений, там работала, а тут чот ни фига

Код
# include <iostream.h>
# include <stdio.h>
# include <math.h>
# include <conio.h>
# include <alloc.h>

int main()
{//----------------------------------------------------------------
    clrscr();
    int w,i,j,n,s,g;
    int * yk;
    cout<<"n="; cin>>n;
    yk=new int[n];
    cout<<"El-ma \n";
    for (i=0; i<n; i++)
    { cin>>* (yk);
      s=*(yk);
      cout<<"\n s="<<s;
//----------------------------------------------------------------
      if (s==1 || s==2) { cout<<"\n s - Prostoe 4islo"; g=*(yk);
      cout<<"\n g="<<g;}
      if (s%2==0) cout<<"\n s - Sostavnoe 4islo";
      else
      {
    w=3;
    while (s&w!=0)
    { w=w+2;
      if (s<=w) { cout<<"\n s - Prostoe 4islo"; g=*(yk);
      cout<<"\n g="<<g; }
      else cout<<"\n s - Sostavnoe 4islo";
    }
      }
    }
//-----------------------------------------------------------------
    delete yk;
    getch();
}

Автор: Vahappaday 31.3.2010, 14:52

ой... не нравится мне этот код. Опишу в таком порядке, как бросилось в глаза.

1. Для освобождения памяти из под массива использовать надо

Код
delete []yk;

Вы же удаляете бедную память как объект.
2. Память под массив выделяете и так её и не используете.
Код
cin>>* (yk);

- это конечно здорово, что умеете пользоваться разыменовыванием, но тут всё делается проще.
Код
cin >> yk[i];

Так куда проще, а главное, так правильно)) Можно, конечно, инкрементировать указатель, но так он "испортится" - не будет уже указывать на начало массива.
3. Посмотрел, как определяется простота числа. Это плохо, так никто не пишет. 4 лаба, пора бы уже разобраться с функциями.
Вообще, суть функции понятен или нет? Функция обязана что-то возвращать. Пусть возвращает bool (ну, или int) - 0, если число составное, 1 - если простое.
4. Кстати о функциях: int main ничего не возвращает, это ошибка синтаксическая.

Это всё "стопроцентные" ошибки, я уже молчу про то, что код трудночитаем, плохо структурирован. К хорошему стилю лучше привыкать сразу.

Советую написать-таки функцию типа bool, ну или в вашем случае int...
int IsSimple(int x), которая отвечала бы за определение простоты числа. Сложное - возвращаем 0. Дошла до конца проверки - значит, число простое, возвращаем 1. Это обязательно хотя бы потому, что определение простоты здесь не самоцель а лишь служебная функция, которая используется как один из кусочков выполнения итоговой задачи.

Когда напишете, будем разбираться с сортировкой и копированием.

Массив нужно не просто завести, но и скопировать в него все входные числа. Как это сделать, я описал чуть выше.

Автор: InFuz 31.3.2010, 16:18

Гляньте функцию, еще хотел спросить как х присвоить yk[i]? Короче давайте еще подсказок, суть то функций понятен я имел в виду еще не совсем разобрался/"набил руку" как это все оформляется/выгядит конкретно в программе. Последовательность расположения функций в программе их взаимодействие другу с другом. От паскаля еще отвыкнуть не могу ))

Код
# include <iostream.h>
# include <stdio.h>
# include <math.h>
# include <conio.h>
# include <alloc.h>

int main()
{
      clrscr();
//----------------------------------------------------------------
      int Chislo(int x);
      int i,n,j;
      {
    Chislo=0;
    for (i=0; i<n; i++)
    {
      if (x[i]%2==0) Chislo=0;
      else for (j=1; j>sqrt(x[i]); j+2)
        {
          if (x[i]%j!=0) Chislo=1;
          else
          {
        Chislo=0;
        break;
          }
        }
    }
      }
//-----------------------------------------------------------------
    int w,i,j,n,s,g;
    int yk[99];
    cout<<"n="; cin>>n;
    yk=new int[n];
    cout<<"El-ma \n";
    for (i=0; i<n; i++)
    {
      cin>>yk[i];
      s=yk[i];
      cout<<"\n s="<<s;
    }
//-----------------------------------------------------------------
    delete []yk;
    getch();
}

Автор: Vahappaday 31.3.2010, 16:43

На мой взгляд, вновь неверно... Теоретически функцию можно описывать внутри другой функции, но я не видел, чтоб к этому прибегали.

У Вас же Chislo описана внутри main.

Также советую разобраться в синтаксисе определения функции.

Код
[тип возвращаемого значения] [имя функции]([список параметров])
{
[код]
}


Никакой переменной с именем функции по умолчанию не создаётся. Все возвраты осуществляются оператором return.

Захотели вернуть 0, пишем return 0;
Захотели вернуть 1, пишем return 1;
Захотели вернуть x, пишем return x;

После выполнения оператора return выполнение функции прекращается и управление передаётся вызывающей функции.

Объявлять все локальные переменные нужно уже в теле функции, там, где у меня написано [код].

То есть, если вы всё вот этот осознаете, то поймёте, что функция описана неверно.

Остальные комментарии:
1. опять main ничего не возвращает - чего вы её так обижаете, такая же функция) Обещает отдавать int, значит, должна отдавать int))
2. Зачем int yk[99]? Зачем Вы выделили память в стеке? Вы же её не используете...
3.
Цитата
как х присвоить yk[i]?

А никак) Просто пишете
Код
Chislo(yk[i]);
и всё


Вот небольшой примерчик с оформлением функций. У меня массив статический, но Вам так нельзя, не подходит по условию статический.

Код

int IsSimple(int x)
{
    int i;
    if (x<2) return 0; //если меньше двух, дальше функция не будет выполняться
    for(i=2;i<x;i++)
    {
        if(!(x%i))
        {
            return 0; //есть делитель больший или равный двойке, но меньше числа, опять же прекращаем
        }
    }
    return 1; //делителей не нашлось, число простое
}

int main()
{
    int i;
    int x[50];
    for(i=0;i<50;i++)
    {
        cin >> x[i];
        if(IsSimple(x[i])) cout << "Prostoe\n";
        else cout << "Sostavnoe\n";
    }
    return 0; //заметьте, обещал вернуть int и вернул int
}


Автор: InFuz 1.4.2010, 10:33

(i=2;i<x;i++)?
Разве может быть делителем x число которое >1/2x (например числа >5 не могут быть делителями 10)
можно сократитть количество проверок в цикле почти в 2 раза.

С функциями вроде разобрались, терь надо с дин. массивом разобраться.

yk[99] - получается статический
*(yk) - тоже не верно а как тогда?

Код
# include <iostream.h>
# include <stdio.h>
# include <math.h>
# include <conio.h>
# include <alloc.h>

//----------------------------------------------------------------
    int Chislo(int x)
    {
      int j;
      if (x<4) return 1;
      else
       {
         for (j=2; j<floor(x/2)+1; j++)
         if (x%j==0) return 0;
       }
       return 1;
    }
//-----------------------------------------------------------------
    int mani()
    {
      clrscr();
      int w,i,j,n,s,g,yk;
      cout<<"n="; cin>>n;
      yk=new int[n];
      cout<<"El-ma \n";
      for (i=0; i<n; i++)
      {
         cin>>yk[i];
         s=yk[i];
         cout<<"\n s="<<s;
         if (Chislo(yk[i])) cout<<"Prostoe\n";
         else cout<<"Sostavnoe\n";
      }
      delete []yk;
      getch();
      return 0;
    }

Автор: Vahappaday 1.4.2010, 18:39

Цитата(InFuz @ 1.4.2010, 10:33) *

(i=2;i<x;i++)?
Разве может быть делителем x число которое >1/2x (например числа >5 не могут быть делителями 10)
можно сократитть количество проверок в цикле почти в 2 раза.


Тогда уж не до x/2 а до sqrt(x), обычно делается так, не стал писать, чтоб не усложнять.

Цитата(InFuz @ 1.4.2010, 10:33) *

yk[99] - получается статический
*(yk) - тоже не верно а как тогда?


Объявлять и выделять память так:

Код
int* yk = new int[n]


Обращаться же по индексу

Код
cin>>yk[i];
s=yk[i];


Пробуйте сортировать. Для сортировки сделайте функцию, которая в качестве параметра принимает указатель на начало массива. Можно конечно qsort, но так неинтересно.

Автор: InFuz 2.4.2010, 14:38

Вот отлаженный вариант

Код
# include <iostream.h>
# include <stdio.h>
# include <math.h>
# include <conio.h>
# include <alloc.h>

//----------------------------------------------------------------
    int Chislo(int x)
    {
      int j;
      if (x<4) return 1;
      else
       {
         for (j=2; j<ceil(sqrt(x))+1; j++)
         if (x%j==0) return 0;
       }
       return 1;
    }
//-----------------------------------------------------------------
    int main()
    {
      clrscr();
      int w,i,j,n,s,g;
      cout<<"n="; cin>>n;
      int* yk = new int[n];
      cout<<"El-ma \n"<<"\n";
      for (i=0; i<n; i++)
      {
    cin>>yk[i];
    s=yk[i];
    cout<<"s["<<i<<"]="<<s;
    if (Chislo(yk[i])) cout<<" - Prostoe\n"<<"\n";
    else cout<<" - Sostavnoe\n"<<"\n";
      }
      delete []yk;
      getch();
      return 0;
    }


прежде чем сорировать надо еще переписать в другой массив, а qsort что конкретно делает?
надо сегодня доделать, а то завтро уже здавать.

Автор: InFuz 2.4.2010, 14:52

Код
# include <iostream.h>
# include <stdio.h>
# include <math.h>
# include <conio.h>
# include <alloc.h>

//----------------------------------------------------------------
    int Chislo(int x)
    {
      int j;
      if (x<4) return 1;
      else
       {
         for (j=2; j<ceil(sqrt(x))+1; j++)
         if (x%j==0) return 0;
       }
       return 1;
    }
//-----------------------------------------------------------------
    int main()
    {
      clrscr();
      int k,j,i,n; j=0; k=0;
      cout<<"n="; cin>>n;
      int* mas1 = new int[n];
      int* mas2 = new int[n];
      cout<<"El-ma \n"<<"\n";
      for (i=0; i<n; i++)
      {
         cin>>mas1[i];
         if (Chislo(mas1[i])) {mas2[j]=mas1[i]; j=j+1; k=k+1;}
                }
      for (i=0; i<n; i++)
      {
    cout<<"\nmas1["<<i<<"]="<<mas1[i];
      }
      cout<<"\n";
      for (j=0; j<k; j++)
      {
        cout<<"\nmas2["<<j<<"]="<<mas2[j];
      }
      delete []mas1;
      delete []mas2;
      getch();
      return 0;
    }


вся щас буду сортировку пробовать делать.
сортироваку тоже надо в виде функции делать.

P.S. тут вопрос один. я под 2 массив виделяю памяти тоже n хотя там может столько и не потребоваться, как заранее просчитать сколько под него памяти веделять? или это не принципиально?

Автор: Vahappaday 2.4.2010, 16:26

qsort - быстрая сортировка, хороший алгоритм, вопрос, зачтут ли его Вам.
Что делает? Сортирует массив. Требует указатель на массив, количество элементов, размер одного элемента и функцию сравнения.
Вот тут хорошо описано, как раз для Вашего случая простых чисел.

http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/

Под второй массив можно выделять и меньше. Для этого достаточно посчитать, сколько простых чисел, а потом ещё раз прогнать и скопировать. А можно выделить и столько же... Смотреть надо на объёмы данных и учитывать, что важнее - скорость обработки или экономичность по памяти.

Сортировку, наверное, лучше написать свою. Пусть медленную, хоть пузырьком, но свою. Полезно))

Автор: InFuz 2.4.2010, 17:09

Чот не знаю как пузырек оформить в виде функции, если просто в main дописать понятно, а как в функцию сортировки передать все значения что бы он с ними работала?

Хочу в функции сортировки сделать копию массива с которым надо рабоать, потом там его отсортировать и печатать то что получилось.

Автор: Vahappaday 2.4.2010, 19:30

Цитата(InFuz @ 2.4.2010, 17:09) *

Хочу в функции сортировки сделать копию массива с которым надо рабоать, потом там его отсортировать и печатать то что получилось.


Плохое решение. Если Вы передаёте указатель на начало массива и количество элементов в нём, то изменяя элементы массива по указателю, Вы изменяете исходный массив. То есть, изменения будут "видны" и в вызывающей функции.

Вы понимаете, чем отличаются локальные данные и глобальные, данные кучи и данные стека?
Это то, с чего нам начали объяснять С на 1 курсе. И это правильно!
Это надо понимать. В С/С++ надо уметь работать с указателями, вот мне и интересно, у Вас с этим всё ок?

Поскольку сдавать завтра, скажу так: достаточно отсортировать массив по указателю, никуда его не копируя. А уже в main выводить его и всё прочее.

Но вообще рекомендую с указателями разобраться.
В качестве упражнения: выделите корректно память под трёхмерный массив, передайте его в функцию, отсортируйте как-нибудь, например, сначала по x, потом по y, потом по z (порядок сортировки сами выберите). А потом напечатайте и освободите корректно память - крайне полезное упражнения для начала.

PS. Если такие уж сильные проблемы с сортировкой, пузырёк могу по-быстрому написать))

Автор: InFuz 2.4.2010, 21:45

Вот пузырек реалезованый не как функция.

Код
# include <iostream.h>
# include <stdio.h>
# include <math.h>
# include <conio.h>
# include <alloc.h>

//-----------------------------------------------------------------
    int Chislo(int x)
    {
      int j;
      if (x<4) return 1;
      else
       {
         for (j=2; j<ceil(sqrt(x))+1; j++)
         if (x%j==0) return 0;
       }
       return 1;
    }
//-----------------------------------------------------------------
   /* int Sort()
    {
      return 0;
    } */
//-----------------------------------------------------------------
    int main()
    {
      clrscr();
      int t,k,i2,j,j2,i,n; j=0; k=0;
      cout<<"n="; cin>>n;
      int* mas1 = new int[n];
      int* mas2 = new int[n];
      cout<<"El-ma \n"<<"\n";
      for (i=0; i<n; i++)
      {
    cin>>mas1[i];
      }
      for (i=0; i<n; i++)
      {
    cout<<"\nmas1["<<i<<"]="<<mas1[i];
      }
      cout<<"\n";
//-----------------------------------------------------------------
      for (i2=1; i2<n; i2++)
   {
      for (i=0; i<n-1; i++)
      {
    if (mas1[i]>mas1[i+1])
    {
      t=mas1[i];
      mas1[i]=mas1[i+1];
      mas1[i+1]=t;
    }
      }
   }
//-----------------------------------------------------------------
      for (i=0; i<n; i++)
      {
    cout<<"\nmas1["<<i<<"]="<<mas1[i];
      }
      cout<<"\n";
      for (i=0; i<n; i++)
      {
    if (Chislo(mas1[i])==1) {mas2[j]=mas1[i]; j=j+1; k=k+1;}
      }
      for (j=0; j<k; j++)
      {
    cout<<"\nmas2["<<j<<"]="<<mas2[j];
      }
      cout<<"\n";
//-----------------------------------------------------------------
      for (j2=1; j2<k; j2++)
   {
      for (j=0; j<k-1; j++)
      {
    if (mas2[j]<mas2[j+1])
    {
      t=mas2[j];
      mas2[j]=mas2[j+1];
      mas2[j+1]=t;
    }
      }
   }
//-----------------------------------------------------------------
      for (j=0; j<k; j++)
      {
    cout<<"\nmas2["<<j<<"]="<<mas2[j];
      }
      delete []mas1;
      delete []mas2;
      getch();
      return 0;
    }

Автор: Vahappaday 3.4.2010, 5:13

а в чём проблема реализации как функции? Ведь то же самое!

Кстати, это нельзя считать ошибкой, но зачем Вы пишете, скажем,
j=j+1;

Ведь есть такой классный оператор инкремента)
j++;
Наверное, он даже где-то чуть-чуть оптимальнее. Рекомендую))

Автор: InFuz 3.4.2010, 9:21

j=j+1;
не знаю наверно привычка с паскаля еще так нагляднее, в паскалее вообщето то же есть альтернатива j:=j+1 или inc(j) ))

а че тоже самое то? )) функция она,... допустим считывает 1 элемент но там нельзя в самой функции написать mas1[i+1] т.к. у нее нет самоого массива и несчем сравнить, а на следующей итерации уже нет предыдущего [i-1].

P.S. приняли в таком виде, там было не принцепиально, главное чтобы функции вообще были ну у меня и была одна Chislo.

Автор: Vahappaday 3.4.2010, 13:34

В функцию нужно передавать весь массив, а не один элемент. Тогда после возврата из функции у вас на месте старого будет отсортированный массив.

например так

Код

void swap(int *p)
{
    int t=p[0];
    p[0]=p[1];
    p[1]=t;
}

void sort(int *arr, int n)
{
    int once_again, i;
    do
    {
        once_again=0;
        for(i=0;i<n-1;i++)
        {
            if(arr[i]<arr[i+1])
            {
                swap(arr+i);
                once_again=1;
            }
        }
    }while(once_again);
}


Это простейший пузырёк, реализованный в виде функции. Сортирует по возрастанию. Принимает указатель на начало и количество элементов.

Автор: InFuz 6.4.2010, 9:08

Final

Код
# include <iostream.h>
# include <stdio.h>
# include <math.h>
# include <conio.h>
# include <alloc.h>

//-----------------------------------------------------------------
    int Chislo(int x)
    {
      int j;
      if (x<4) return 1;
      else
       {
         for (j=2; j<ceil(sqrt(x))+1; j++)
         if (x%j==0) return 0;
       }
       return 1;
    }
//-----------------------------------------------------------------
    void swap(int *p)
    {
      int t=p[0];
      p[0]=p[1];
      p[1]=t;
    }
//-----------------------------------------------------------------
    void sort1(int *mas1, int n)
    {
      int again,i;
      do
      {
    again=0;
    for(i=0;i<n-1;i++)
    {
      if(mas1[i]>mas1[i+1])
      {
        swap(mas1+i);
        again=1;
      }
    }
      }
      while(again);
    }
//-----------------------------------------------------------------
    void sort2(int *mas2, int k)
    {
      int again,i;
      do
      {
    again=0;
    for(i=0;i<k-1;i++)
    {
      if(mas2[i]<mas2[i+1])
      {
        swap(mas2+i);
        again=1;
      }
    }
      }
      while(again);
    }
//-----------------------------------------------------------------
    void main()
    {
      clrscr();
      int t,k,i2,j,j2,i,n; j=0; k=0;
      cout<<"n="; cin>>n;
      int* mas1 = new int[n];
      int* mas2 = new int[n];
      cout<<"El-ma \n"<<"\n";
      for (i=0; i<n; i++)
      {
    cin>>mas1[i];
      }
      for (i=0; i<n; i++)
      {
    cout<<"\nmas1["<<i<<"]="<<mas1[i];
      }
      cout<<"\n";
      sort1(mas1,n);
      for (i=0; i<n; i++)
      {
    cout<<"\nmas1["<<i<<"]="<<mas1[i];
      }
      cout<<"\n";
      for (i=0; i<n; i++)
      {
    if (Chislo(mas1[i])==1) {mas2[j]=mas1[i]; j=j+1; k=k+1;}
      }
      for (j=0; j<k; j++)
      {
    cout<<"\nmas2["<<j<<"]="<<mas2[j];
      }
      cout<<"\n";
      sort2(mas2,k);
      for (j=0; j<k; j++)
      {
    cout<<"\nmas2["<<j<<"]="<<mas2[j];
      }
      delete []mas1;
      delete []mas2;
      getch();
    }


Один вопрос
swap пишиться для экономии места и времени или нет?
что измениться если написать

Код
void sort1(int *mas1, int n)
    {
      int again,i,t;
      do
      {
    again=0;
    for(i=0;i<n-1;i++)
    {
      if(mas1[i]>mas1[i+1])
      {
        t=p[i];
        p[i]=p[i+1];
        p[i+1]=t;
        again=1;
      }
    }
      }
      while(again);
    }

Автор: Vahappaday 6.4.2010, 13:32

Ответ: конкретно так работать не будет, потому что переменная p в функции sort не объявлена.
А вообще, swap я написал для наглядности кода, он так понятнее.
Естественно, можно и в теле sort1/sort2 менять местами элементы массива - не возбраняется.

Остальное не глядел, работает, в принципе?

Автор: InFuz 6.4.2010, 19:13

Ну вот тот что сверху полностью рабочий вариант, в точности совпадающий с тем что требовалось в задании.

Автор: InFuz 20.4.2010, 14:38

Лаба №6

Создать двоичный файл и записать в него n вещественных чисел. Сформировать массив из элементов исходного файла, внеся в него числа, превосходящие среднее значение положительных элементов файла. Задание должно быть выполнено в виде 2 программ. Первая должна сформировать бинарный файл. Вторая должна выполнить задание в соответствии с вариантом (см. выше).

Сделал 1 часть.
Во второй части сделал пока чтобы читала файл и записывала это все дело в массив, не понял что значит "внеся в него числа, превосходящие среднее значение положительных элементов файла", это просто что ли любых чисел которые соответствуют условию натыкать?

Автор: Vahappaday 20.4.2010, 15:36

Нет, все числа из файла, удовлетворяющие условию, я так понял задание.

Автор: InFuz 20.4.2010, 16:33

А я понял, вроде. Надо из файла брать (и добавлять в массив) только те числа которые соответствуют условию.

Автор: Vahappaday 20.4.2010, 18:27

да, только сначала для расчёта условий надо сначала все их прочитать

Автор: InFuz 21.4.2010, 12:17

Гляньте пожалуйста вроде должна работать, но чот ни фига не хочет blush.gif

1 часть

Код
# include <iostream.h>
# include <stdio.h>
# include <conio.h>

//-----------------------------------------------------------------
    void main()
    {
      clrscr();
      FILE *f;
      int i,n;
      double a;
      f=fopen("binfile.dat","wb");
      cout<<"n="; cin>>n;
      fwrite(&n, sizeof(int),1,f);
      for(i=0; i<n; i++)
      {
    cout<<"a["<<i<<"]="; cin>>a;
    fwrite(&a, sizeof(double),1,f);
      }
      fclose(f);
    }


2 часть

Код
# include <iostream.h>
# include <stdio.h>
# include <conio.h>

//-----------------------------------------------------------------
    void main()
    {
      clrscr();
      FILE *f;
      int i,n,t=-1,s=0,sym=0;
      double *a,*b;
      cout<<"n="; cin>>n;
      f=fopen("binfile.dat","rb");
      fread(a,sizeof(int),1,f);
      a-new double[n];
      fread(a,sizeof(double),n,f);
      for(i=0; i<n; i++)
      {
    if(a[i]>0)
    {
          sym=sym+a[i];
          s++;
    }
      }
      b-new double[s];
      for(i=0; i<s; i++)
      {
    if(a[i]>(sym/s))
    {
          t++;
      b[t]=a[i];
        }
      }
      for(i=0; i<t+1; i++)
      if (t=-1) cout<<"Net takix 4isel!";
      else
      {
        cout<<"\n"<<b[i]<<"\t";
    cout<<endl;
      }
      fclose(f);
      delete[]a;
      delete[]b;
      getch();
    }

Автор: Vahappaday 21.4.2010, 16:03

Есть много комментариев по 2 части.

Зачем записывать в файл n, а потом вводить его с клавы? Что-то уж одно)

fread(a,sizeof(int),1,f); - во-первых, надо сначала выделить память под указатель, а потом уж читать в него.
во-вторых, зачем читать в массив double? Формально ничего криминального, там тип входного параметра void*, но логики не вижу.
Тут уж Вы должны n прочитать.

a-new double[n]; - очепяточка?

sym=sym+a[i]; - вообще ужас))) Куда дробные части денутся?) К целому прибавлять double'ы, это надо же.

if(a[i]>(sym/s)) - а Вы в курсе, что sym / s -это целочисленное деление? Если делить одно целое на другое, то получится опять же целое. Например 10/3 = 3
А сравниваете Вы с double, так что ошибки вполне могут иметь место)

Последние две ошибки убиваются одним выстрелом: объявлением sym как double.

b-new double[s]; - и вновь очепяточка. Да, кстати, и почему именно s? Их там всегда будет меньше.

if (t=-1) cout<<"Net takix 4isel!"; - целых два косяка. Во-первых, (t==-1), во-вторых, если уж t и принимает такое значение, то цикл не прогонится не разу. Так что следует сделать if, а уж внутри if цикл.

Остальное дело вкуса. Хотя мне лично непонятно, почему в одном случае потоки cin и cout, а в другом fopen, fread, fwrite - либо STL, либо C Library)

Автор: InFuz 22.4.2010, 12:46

Все исправил, заработала.

Гляньте еще одну прогу.

Задание. Вычислить среднее значение элементов, расположенных в массиве между первым и последним нулевым значением. Поменять местами минимальный и максимальный элементы. Создать функции для определения среднего значения, макс. и мин.

Код
# include <iostream.h>
# include <stdio.h>
# include <math.h>
# include <conio.h>
# include <alloc.h>

//-----------------------------------------------------------------
    double Sred(int *a, int I, int I2)
    {
      int i,s=0,sym=0;
      for(i=I+1; i<I2-1; i++)
      {
    sym=sym+a[i];
        s++;
      }
      return (sym/s);
    }
//-----------------------------------------------------------------
    void MaxMin(int *a, int n)
    {
      int b,i,max=0,imax;
      for(i=0; i<n; i++)
      {
    if(a[i]>max)
        {
      imax=i;
      max=a[i];
        }
      }
      int min=0,imin;
      for(i=0; i<n; i++)
      {
    if(a[i]<min)
        {
      imin=i;
      min=a[i];
        }
      }
      b=max;
      a[imax]=a[imin];
      a[imin]=max;
    }
//-----------------------------------------------------------------
    int main()
    {
      clrscr();
      int b,i,I,n,I2,s=0;
      cout<<"n="; cin>>n;
      int* a = new int[n];
      cout<<"El-ma";
      for (i=0; i<n; i++)
      {
    cout<<"\na["<<i<<"]=";
    cin>>a[i];
        if(a[i]==0) s++;
      }
      if(s<2)
      {
    cout<<"Malo nylei!\n";
        return 0;
      }
      else
      {
    for (i=0; i<n; i++)
    if(a[i]==0)
        {
      I=i;
      break;
    }
    for (i=n; i>I; i--)
    {
      if(a[i]==0)
      {
        I2=i;
            break;
          }
        }
      }
      Sred(a,I,I2);
      MaxMin(a,n);
      for (i=0; i<n; i++)
    cout<<"\na["<<i<<"]="<<a[i];
      cout<<"Srednee zna4enie="<<Sred;
      delete []a;
      getch();
      return 1;
    }

Автор: Vahappaday 22.4.2010, 13:53

return (sym/s); - опять то же самое)) Результат-то будет типа double) Но средним значением чисел {1, 1, 2} будет 1.0

Не созданы функции для отдельного нахождения минимума и максимума.
В функции MaxMin цикл не обязательно гонять два раза. Всё это можно проделать и в одном цикле.
По той же функциями. Инициализация нулями min и max не верна. Например, у Вас будет массив {-1,-2,-3}.
И что, максимальный элемент у него 0? Именно так будет считать такой алгоритм. А индекс будет вообще не инициализирован. Это же замечание касается и min.

a[imax]=a[imin]; - уж написали бы =min ))) Хотя... в принципе ошибки не вижу. Но тогда никакой временной переменной не надо.

cout<<"Srednee zna4enie="<<Sred; - какие ужасы))) Что за Sred? Как же это Вы используете идентификатор функции без параметров.

return 1; - Ваше право, но корректно завершившееся приложение в Windows обычно имеет код возврата 0.

Автор: InFuz 22.4.2010, 17:17

Результат-то будет типа double ну так и функция типа double
отдельного нахождения это не пренципиально
вообще я хотел узнать в чем ошибка мешающая работе, а не косметический ремонт smile.gif
компилятор говорит что все гуд, но когда запускаешь, (пускай даже без отрец. знач. вообще) она начинает на что-ругаться. huh.gif

Автор: Vahappaday 22.4.2010, 20:29

Советую повнимательнее взглянуть сюда:
return (sym/s); - опять то же самое)) Результат-то будет типа double) Но средним значением чисел {1, 1, 2} будет 1.0

Проблема не в типе. Тип как раз верный. А вот результат вычислений косячный. У Вас будет целочисленное деление, а затем приведение к типу double. Тип правильный, а результат косячный.

Почему ругается, я тоже сказал.
max=0 и min=0.
Если у Вас нет отрицательных значений, то как раз и будут проблемы. У вас не встретится ни одного числа, которое бы удовлетворяло условию:

Код

if(a[i]<min)
{
    imin=i;
    min=a[i];
}

В итоге imin останется непроинициализированным. А Вы к нему таки обратитесь в конце.

Моё конструктивное предложение:
int imin=0, imax=0, min=a[0], max=a[0];

Я обычно делаю так.

Автор: InFuz 23.4.2010, 19:07

Все, готово, кое как своими кривыми ручонками отладил. laugh.gif
Спасибо, чтобы без вас делал, не знаю. thumbsup.gif

Автор: Vahappaday 23.4.2010, 19:47

А с делением поправили?)))
Косячить ведь будет)

Автор: InFuz 23.4.2010, 21:37

так точно! сделал еще печать в самой процедуре.

Код
    void Sred(int *a, int I, int I2)
    {
      int i,s=0,sym=0;
      double b;
      for(i=I+1; i<I2; i++)
      {
    sym=sym+a[i];
    s++;
      }
      b=(double)sym/s;
      cout<<"Srednee zna4enie="<<b;
    }


Хотел еще спросить, что значит linker warning:no module definition file specified: using defaults
в принципе это не ошибка и работе не мешает просто хотел узнать, что она мне хочет сказать.

Автор: Vahappaday 23.4.2010, 22:37

Если честно, не в курсе, это чисто борландовое предупреждение... Говорят, помогает пересоздание проекта, его перемешение или что-то типа того.

Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)