В общем закончили 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; */
}
Формула Герона.
pp=p*0.5;
s=sqrt(pp*(pp-a)*(pp- b )*(pp-c));
Не забудьте объявить pp как double.
Пару вопросов.
Что такое pp (p я так понимаю пириметр).
И как избавиться от ошибки когда вычисляется a, b, c и значение под корнем становиться отрицательным, например для треугольника а(1,1) b(-1,1) c(0,-1).
да pp - у него это периметр, а в Героне надо полу-периметр(p)
когда находишь длины сторон, поставь mod или abs (не помню, ну общем можно и самому написать функцию, возвращающую |x|(модуль) )))))
А хотя, я что то не понимаю, где там может быть отрицательное значение????
да фиг его знает, когда вводишь а(1,1) b(-1,1) c(0,-1) выдает ошибку что значение под корнем отрицательное, хотя по формуле ничего подобного нет.
Сделал вот так вроде работает, только фиг его знает правильно считает или нет
Попробую такую сдать.
# 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;
}
выведите на экран промежуточные значения a,b,c,p
abs- зачем используете?
без 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;
}
да Вы не для меня выводите эти значения, а для себя.
Если без abs выдает "под корнем отрицательное значение",
sqrt ( (((x1-x2)^2+(y1-y2)^2)) )
то нужно вывести значение выражения, под корнем и проверить его на отрицательность. Если оно действительно отрицательно, значит или Вы что-то не то делаете или система считает неправильно
Да я знаю что не для вас, не надо так сурово (:
как исправить ошибку function "sqr" should have a prototype;
здесь.
aa= sqr (x2-x3);
sqr что ознгачает?
возведение в квадрат.
Видимо, в math.h нету такой функции. Можно написать её самому, либо вместо sqr(x) писать x*x. Можно ещё поюзать pow, но она работать будет дольше,чем x*x.
я в принципе и хотел написать в виде х*х, просо с 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;
}
на счётах быстрее посчитаешь площадь. Уже 2 часа идет отладка программы
если бы я лучше знал язык я бы может и после первой подсказки сделал все.
да и интернет форум куда медленнее для общения чем хотя бы icq
Лаба №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 <<"Последовательность не знакочередующаяся";
}
}
я компилю в 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++ добавилось, вот учу потихоньку.
ясно, первая итерация как бы проходит в холостую (т.к. один элемент не является еще последовательностью).
да это С++, хотя # include <iostream.h> и отсутствие using namespace это как в С
в 3.1 нет типа bool как такового он появляется в версиях 5 и старше, так что приходится в место него использовать тип целых чисел где 0=false, а 1=true.
Лаба №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 надеюсь на ваши подсказки ))
ой... а зачем и 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 больше имеющегося, скопировать старый в новый, дописать новое число, освободить память из под старого, вернуть указатель на новый.
Вариантов куча на самом деле))
Определяйтесь, и пробуйте писать. Где будет тяжело - подмогу.
Пока делаю без функций т.к. с ними еще не разобрался.
Вот так пока получается, вроде переделал функцию из паскалевской без изменений, там работала, а тут чот ни фига
ой... не нравится мне этот код. Опишу в таком порядке, как бросилось в глаза.
1. Для освобождения памяти из под массива использовать надо
Гляньте функцию, еще хотел спросить как х присвоить yk[i]? Короче давайте еще подсказок, суть то функций понятен я имел в виду еще не совсем разобрался/"набил руку" как это все оформляется/выгядит конкретно в программе. Последовательность расположения функций в программе их взаимодействие другу с другом. От паскаля еще отвыкнуть не могу ))
На мой взгляд, вновь неверно... Теоретически функцию можно описывать внутри другой функции, но я не видел, чтоб к этому прибегали.
У Вас же Chislo описана внутри main.
Также советую разобраться в синтаксисе определения функции.
(i=2;i<x;i++)?
Разве может быть делителем x число которое >1/2x (например числа >5 не могут быть делителями 10)
можно сократитть количество проверок в цикле почти в 2 раза.
С функциями вроде разобрались, терь надо с дин. массивом разобраться.
yk[99] - получается статический
*(yk) - тоже не верно а как тогда?
Вот отлаженный вариант
qsort - быстрая сортировка, хороший алгоритм, вопрос, зачтут ли его Вам.
Что делает? Сортирует массив. Требует указатель на массив, количество элементов, размер одного элемента и функцию сравнения.
Вот тут хорошо описано, как раз для Вашего случая простых чисел.
http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/
Под второй массив можно выделять и меньше. Для этого достаточно посчитать, сколько простых чисел, а потом ещё раз прогнать и скопировать. А можно выделить и столько же... Смотреть надо на объёмы данных и учитывать, что важнее - скорость обработки или экономичность по памяти.
Сортировку, наверное, лучше написать свою. Пусть медленную, хоть пузырьком, но свою. Полезно))
Чот не знаю как пузырек оформить в виде функции, если просто в main дописать понятно, а как в функцию сортировки передать все значения что бы он с ними работала?
Хочу в функции сортировки сделать копию массива с которым надо рабоать, потом там его отсортировать и печатать то что получилось.
Вот пузырек реалезованый не как функция.
а в чём проблема реализации как функции? Ведь то же самое!
Кстати, это нельзя считать ошибкой, но зачем Вы пишете, скажем,
j=j+1;
Ведь есть такой классный оператор инкремента)
j++;
Наверное, он даже где-то чуть-чуть оптимальнее. Рекомендую))
j=j+1;
не знаю наверно привычка с паскаля еще так нагляднее, в паскалее вообщето то же есть альтернатива j:=j+1 или inc(j) ))
а че тоже самое то? )) функция она,... допустим считывает 1 элемент но там нельзя в самой функции написать mas1[i+1] т.к. у нее нет самоого массива и несчем сравнить, а на следующей итерации уже нет предыдущего [i-1].
P.S. приняли в таком виде, там было не принцепиально, главное чтобы функции вообще были ну у меня и была одна Chislo.
В функцию нужно передавать весь массив, а не один элемент. Тогда после возврата из функции у вас на месте старого будет отсортированный массив.
например так
Final
Ответ: конкретно так работать не будет, потому что переменная p в функции sort не объявлена.
А вообще, swap я написал для наглядности кода, он так понятнее.
Естественно, можно и в теле sort1/sort2 менять местами элементы массива - не возбраняется.
Остальное не глядел, работает, в принципе?
Ну вот тот что сверху полностью рабочий вариант, в точности совпадающий с тем что требовалось в задании.
Лаба №6
Создать двоичный файл и записать в него n вещественных чисел. Сформировать массив из элементов исходного файла, внеся в него числа, превосходящие среднее значение положительных элементов файла. Задание должно быть выполнено в виде 2 программ. Первая должна сформировать бинарный файл. Вторая должна выполнить задание в соответствии с вариантом (см. выше).
Сделал 1 часть.
Во второй части сделал пока чтобы читала файл и записывала это все дело в массив, не понял что значит "внеся в него числа, превосходящие среднее значение положительных элементов файла", это просто что ли любых чисел которые соответствуют условию натыкать?
Нет, все числа из файла, удовлетворяющие условию, я так понял задание.
А я понял, вроде. Надо из файла брать (и добавлять в массив) только те числа которые соответствуют условию.
да, только сначала для расчёта условий надо сначала все их прочитать
Гляньте пожалуйста вроде должна работать, но чот ни фига не хочет
1 часть
Есть много комментариев по 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)
Все исправил, заработала.
Гляньте еще одну прогу.
Задание. Вычислить среднее значение элементов, расположенных в массиве между первым и последним нулевым значением. Поменять местами минимальный и максимальный элементы. Создать функции для определения среднего значения, макс. и мин.
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.
Результат-то будет типа double ну так и функция типа double
отдельного нахождения это не пренципиально
вообще я хотел узнать в чем ошибка мешающая работе, а не косметический ремонт
компилятор говорит что все гуд, но когда запускаешь, (пускай даже без отрец. знач. вообще) она начинает на что-ругаться.
Советую повнимательнее взглянуть сюда:
return (sym/s); - опять то же самое)) Результат-то будет типа double) Но средним значением чисел {1, 1, 2} будет 1.0
Проблема не в типе. Тип как раз верный. А вот результат вычислений косячный. У Вас будет целочисленное деление, а затем приведение к типу double. Тип правильный, а результат косячный.
Почему ругается, я тоже сказал.
max=0 и min=0.
Если у Вас нет отрицательных значений, то как раз и будут проблемы. У вас не встретится ни одного числа, которое бы удовлетворяло условию:
Все, готово, кое как своими кривыми ручонками отладил.
Спасибо, чтобы без вас делал, не знаю.
А с делением поправили?)))
Косячить ведь будет)
так точно! сделал еще печать в самой процедуре.
Если честно, не в курсе, это чисто борландовое предупреждение... Говорят, помогает пересоздание проекта, его перемешение или что-то типа того.
Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)