Kalkulator liczb zespolonych i kwaternionów C++/CLI Windows Forms

0

Witam,
Mam problem ponieważ mam za zadanie napisać program który będzie wykonywał podstawowe operacje na liczbach rzeczywistych, liczbach zespolonych oraz kwaternionach. Program musi wyglądać jak na obrazku poniżej i mieć jedno okienko wejścia a i b.Wszystko szło pięknie dopóki nie zacząłem zajmować się liczbami zespolonymi i kwaternionami.

Program wygląda tak :

user image

Dla liczb rzeczywistych sprawa jest prosta kod wygląda tak:

if (this->liczbyRzeczywisteToolStripMenuItem->Checked == Enabled)
{
	Double x, y;
	try
	{ 
		x = Convert::ToDouble(a->Text); 
		y = Convert::ToDouble(b->Text); 
		wynik->Text=""+ (x+y); 
	} 
	catch (FormatException^ e) 
	{ 
		wynik->Text="Błędny format danych wejściowych"; 
	} 
}
 

I teraz czy da się zrobić tak ażeby ten String który wprowadza użytkownik wpisać do obiektu klasy Liczba_zespolona czy kwaternion ? Próbowałem to robić konwersją na std::string oraz potem konwersja na int albo tablica char ale żaden z tych sposobów
nie poradził sobie ze znakami +/-. W liczbach zespolonych są 4 kombinacje 3+3i, 3-3i, -3+3i, -3-3i. To dla kwaternionów
chyba bym się załamał zanim bym zaprogramował wszystkie kombinacje znaków + i / i jeszcze kod który to wyszukuje ze stringa.
Czy znacie jakieś sposoby na to ażeby "wyłowić" te dwie wartości ze Stringa ze znakami ? i,j,k to już sobie mogę dopisać przy wyświetlaniu bo format jest zawsze ten sam ale żeby chociaż liczby zachowały znaki.
Z góry dziękuję za pomoc.

1

Hmm, współczuję ludziom którzy się uczą (jako pierwszego języka?) C++/CLI. Nie żeby to był zły język, po prostu na tyle skomplikowany że średnio nadaje się do pisania zwykłych programów, nie mówiąc już o uczeniu się programowania za jego pomocą.

Tak czy inaczej, najprościej chyba wczytywać te dane za pomocą stringstreama (podobnie by się dało używając strtola):

#include <string>
#include <sstream>
#include <cstdio>

struct complex {
    complex(double i, double j) : i(i), j(j) { }
    double i, j;
};

complex to_complex(std::string num) {
    std::istringstream stream(num);
    double i, j; stream >> i >> j;
    return complex(i, j);
}

int main() {
    complex samples[] = {
        to_complex("2+3i"), to_complex("-2+3i"),
        to_complex("+2-3i"), to_complex("-2-3i")
    };

    size_t sample_ct = sizeof(samples) / sizeof(*samples);
    for (int i = 0; i < sample_ct; i++) {
        std::printf("%+g%+gi\n", samples[i].i, samples[i].j);
    }
}

Ciebie interesuje tutaj funkcja to_complex (reszta do celów demonstracyjnych), a ściśle:

std::istringstream stream(num);
double i, j; stream >> i >> j;

Dla przykładowych danych, kod działa poprawnie:

D:\>example.exe
+2+3i               
-2+3i               
+2-3i               
-2-3i               
0

Dziękuję bardzo za odpowiedź, zaraz postaram się zastosować to w moim programie.
Tzn. taki kalkulator kwaternionów robiliśmy już wcześniej w zwykłym C++ w konsoli.
Teraz jako końcówka kursu programowania obiektowego mamy Windows Forms no i takie zadania.
Najbardziej denerwujące jest to że nie można sobie po prostu przeciążyć operatora jak to się robiło w zwykłym C++
żeby okienko pobierało całość jako obiekt klasy. Chyba że jestem w błędzie ?
C++/CLI używa się gdzieś poza celami akademickimi ?:)

0

No to że std::string ma takie metody to wiem bo zrobiłem dodawanie liczb zespolonych ale tylko o znakach dodatnich, problem polegał na tym że nie znałem polecenia jakim wyświetlić znak liczby
w C++ używałem << showpos a tutaj nie miałem pomysłów na to. Dobrze wiedzieć że String też ma takie metody wtedy konwersja na string już odpada więc już jest lepiej :) Dziękuję za odpowiedź.

// PS. Post na który odpowiadałem zniknął ?

1

Najbardziej denerwujące jest to że nie można sobie po prostu przeciążyć operatora jak to się robiło w zwykłym C++
Jak nie jak tak.

żeby okienko pobierało całość jako obiekt klasy.
Nie rozumiem.

PS. zaraz pewnie pojawi się pytanie jak przekonwertować System::String na std::string.
Do tego służy marshal_as<T>. Działa jak rzutowanie:

#include <string>
#include <msclr/marshal_cppstd.h>

using namespace System;
using namespace std;
using namespace msclr::interop;

int main()
{
    string s = "Ala ma kota";

    // w jedną stronę
    String ^t = marshal_as<String^>(s);

    // w drugą stronę
    string u = marshal_as<string>(t); 
}
0

Zrobiłem dodawanie liczb zespolonych na podstawie odpowiedzi MSM oraz Azariena, z tym że jest jeden problem, chciałbym aby wyświetlany był znak + drugiej liczby.
Wynik jest poprawny ale jest w formie np 55i. I czy jest możliwość wyświetlenia obiektu klasy:

wynik->Text = "" + Wynik + "i";	 

?

if (this->liczbyZespoloneToolStripMenuItem->Checked == Enabled)
{
	string pierwsza_liczba;		
	string druga_liczba;
	Liczba_zespolona L1;
	Liczba_zespolona L2;
	Liczba_zespolona Wynik;
	try
	{
		pierwsza_liczba = marshal_as<string>(a->Text);
		druga_liczba = marshal_as<string>(b->Text);
		L1 = L1.To_LiczbaZespolona(pierwsza_liczba);
		L2 = L2.To_LiczbaZespolona(druga_liczba);
		Wynik = L1 + L2;
		wynik->Text = "" + Wynik.re + Wynik.im + "i";	
	}
	catch (FormatException^ e)
	{
		wynik->Text="Błędny format danych wejściowych";
	}
}

Oraz klasa Liczba_zespolona:

class Liczba_zespolona
{
public:
	double re;
	double im;

	Liczba_zespolona():re(0),im(0) {};
	Liczba_zespolona(int re,int im):re(re),im(im) {};
	Liczba_zespolona(Liczba_zespolona & q):re(q.re),im(q.im) {};
	Liczba_zespolona To_LiczbaZespolona(string liczba_zespolona)
	{
		istringstream stream(liczba_zespolona);
		double i, j;
		stream >> i >> j;
		return Liczba_zespolona(i, j);
	}
	Liczba_zespolona operator+(Liczba_zespolona & L)
	{
		L.re += re;
		L.im += im;

		return L;
	}
};
1

Jak mam użyć printfa w textBoxie ?

The wrong way:

	wchar_t ws[256];
	swprintf(ws, 256, L"Ala ma %d koty", 42);
	textBox->Text = gcnew String(ws);

The right way:

	textBox->Text = String::Format(L"Ala ma {0} koty", 42);
0

A czy da się wyświetlić znak liczby typu double poprzez

wynik->Text = String::Format(L"{0} {1}", Wynik.re , Wynik.im); 

żeby wstawić go pomiędzy {0} i {1} i uzyskać znak obiektu {1}.
Tak jak to robił <<showpos ?

wynik->Text = String::Format(L"{0} (showpos) {1}", Wynik.re , Wynik.im); 
0

Czytałem dokumentację, czytałem ten link już chyba z 10 razy.
Nie wiem, może jestem głupi ale nie widzę odpowiedzi na moje pytanie ;/

1

String.Format("{0:0.00;minus 0.00;zero}", 0.0); - i tego wiersza nie zauważyłeś

0

Zauważyłem, nawet kilka razy próbowałem go użyć, wtedy wynikiem programu był komunikat:

catch (FormatException^ e) 
{ 
     wynik->Text="Błędny format danych wejściowych"; 
}
 

Zależy mi na wyświetleniu plusa, więc próbowałem:

 
	wynik->Text = String::Format(L"{0;plus 1;plus}", Wynik.re,Wynik.im);	

Niestety niepowodzenie :P
Wiem że może dla was to jest banalne i oczywiste ale dopiero się uczę...

1

Dostarczasz niezbitych dowodów na słowa @n0name_l : - "... jakies 95% ludzi, ktorzy: nie rozumieja dokumentacji ...".
Już nawet konkretny wiersz z przykładów ci wyjąłem ...

wynik->Text = String::Format(L"{0}{1:+0.00i;-0.00i;}",Wynik.re,Wynik.im);

0
String.Format("{0:0.00;minus 0.00;zero}";  
String::Format(L"{0}{1:+0.i;-0.i;}",Wynik.re,Wynik.im);  

Nie no faktycznie bliźniaczo podobne przykłady. Teraz już działa. Dziękuję za pomoc.

0

A jeszcze chciałem zapytać czemu mi nie działa wczytanie kwaternionu skoro liczby zespolonej działa.
Oto kod:
Przeciążenie <<

istream & operator>>(istream& wejscie, kwaternion& q)
{
	wejscie >> q.a;
	wejscie >> q.b;
	wejscie.ignore();
	wejscie >> q.c;
	wejscie.ignore();
	wejscie >> q.d;
	wejscie.ignore();

	return wejscie;
}

Metoda

kwaternion kwaternion::To_Kwaternion(string q)
{
	istringstream stream(q);
	kwaternion a;	
	stream >> a;	
	return a;
}
if (this->kwaternionyToolStripMenuItem->Checked == Enabled)
{
	string pierwsza_liczba;		
	string druga_liczba;
	kwaternion L1;
	kwaternion L2;
	kwaternion Wynik;
	try
	{
		pierwsza_liczba = marshal_as<string>(a->Text);
		druga_liczba = marshal_as<string>(b->Text);
		L1.To_Kwaternion(pierwsza_liczba);
		L2.To_Kwaternion(druga_liczba);
		Wynik = L1 + L2;
		wynik->Text = String::Format(L"{0}{1:+0.i;-0.i;}{2:+0.j;-0.j;}{3:+0.k;-0.k;}",Wynik.a,Wynik.b,Wynik.c,Wynik.d);
	}
	catch (FormatException^ e)
	{
		wynik->Text="Błędny format danych wejściowych";
	}
}

Wydaje mi się że wszystko jest dobrze, sprawdzałem bez przeciążenia >> i wynik jest tam sam czyli 0+0i+0j+0k.
W czym problem ?

1 użytkowników online, w tym zalogowanych: 0, gości: 1