Tablica obiektów – problemy z prawidłowym wypisaniem

0

Chcę zrobić poniższe zadanie od deski do deski w 100% tak jak autor miał na myśli i mam problem z wypisaniem Zamówienia. Wartości są przypisane do odpowiednich indeksów zdaje się prawidłowo. Dlaczego mój wynik jest różny od wyniku autora zadania?

Na załączonym przez niego listingu on też deklaruje 20-elementową tablice, jednak na ekranie, linia wypisująca obiekt z na ktorym pracuje, drukuje mu ładnie 2 pozycje. W mojej wersji wpisanie analogicznej metody: **Console.WriteLine(z) **daje wynik: **Obsluga_Zamówien.Zamówienie ** - nazwe namespacea? Proszę o jakieś nakierowanie bo próbuje sobie z tym poradzić od tak długiego czasu, że aż wstyd się przyznać, a bez efektów.

Zadanie: http://www.jkozak.pl/przedmioty/java/zadania7.pdf

Klasa Pozycja:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Obsluga_Zamowien
{
    class Pozycja
    {
        public string nazwaTowaru;
        public int ileSztuk;
        public double cena;

        public Pozycja(string nT, int iS, double c)
        {
            nazwaTowaru = nT;
            ileSztuk = iS;
            cena = c;
        }

        public double obliczWartosc()
        {
            double wartosc = cena * ileSztuk;
            return wartosc;
        }

        public string toString()
        {
            string lancuch;
            lancuch = nazwaTowaru +"          "+ cena+" zł   " + ileSztuk+" szt.    " + obliczWartosc()+" zł";
            return lancuch;
        }
    }
}

Klasa Zamówienie:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Obsluga_Zamowien
{
    class Zamówienie
    {
        Pozycja [] pozycje;
        public int ileDodanych;
        public int maksRozmiar;
        
        public Zamówienie()
        {
            maksRozmiar = 10;
        }

        public Zamówienie(int ileDodanych)
        {
            this.ileDodanych = ileDodanych;
            pozycje = new Pozycja[this.ileDodanych];
        }

        public void dodajPozycje(Pozycja p)
        {
            for (int i = 0; i < ileDodanych; i++)
            {
                pozycje[i] = p;

                Console.WriteLine(pozycje[i].toString());
            }
        }
    }
}

Main:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Obsluga_Zamowien
{
    class Program
    {
        static void Main(string[] args)
        {
            Pozycja p1 = new Pozycja("Cukier", 10, 2.5);
            p1.obliczWartosc();
            Console.WriteLine(p1.toString());
            Pozycja p2 = new Pozycja("Chleb", 5, 2.38);
            Console.WriteLine(p2.toString());

            Zamówienie z = new Zamówienie(20);

            z.dodajPozycje(p1);
            z.dodajPozycje(p2);
            Console.WriteLine(z);

            Console.ReadLine();
        }
    }
}
1

W klasie Zamówienie nie masz metody ToString().

0

Więc tak:
Napisałem metodę w Zamówienie:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Obsluga_Zamowien
{
    class Zamówienie
    {
        Pozycja [] pozycje;
        public int ileDodanych;
        public int maksRozmiar;
       
        public Zamówienie()
        {
            maksRozmiar = 10; 
        }
 
        public Zamówienie(int ileDodanych)
        {
            this.ileDodanych = ileDodanych;
            pozycje = new Pozycja[this.ileDodanych];
        }
 
 
        public void dodajPozycje(Pozycja p)
        {
            for (int i = 0; i < ileDodanych; i++)
            {
                pozycje[i] = p;  
            }
        }
 
        public string toString()
        {
            Console.WriteLine(pozycje[0].ToString() +
            pozycje[1].ToString());
            return pozycje[0].ToString() +
            pozycje[1].ToString();
        } 
    }
}

Main:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Obsluga_Zamowien
{
    class Program
    {
        static void Main(string[] args)
        {
            Pozycja p1 = new Pozycja("Cukier", 10, 2.5);
            p1.obliczWartosc();
            Console.WriteLine(p1.toString());
            Pozycja p2 = new Pozycja("Chleb", 5, 2.38);
            Console.WriteLine(p2.toString());
           
            Zamówienie z = new Zamówienie(20);
 
            z.dodajPozycje(p1);
            z.dodajPozycje(p2);

            Console.WriteLine(z.toString());
            Console.ReadLine();
        }
    }
}

Wynik:

title

Co robię źle, bo sam nie jestem sobie w stanie odpowiedzieć na to pytanie?

1
public string toString()
{
    Console.WriteLine(pozycje[0].ToString() +
    pozycje[1].ToString());
    return pozycje[0].ToString() +
    pozycje[1].ToString();
}

To jest źle – metoda toString ma dokonywać wyłącznie konwersji, a nie wyświetlać dane w konsoli:

public string toString()
{
    return pozycje[0].ToString() + pozycje[1].ToString();
}

Co i tak nie zmienia faktu, że hardkodowane indeksy pozycji są złe.

1
  • A kiedy po wpisaniu 20'tej pozycji zamówienia użytkownik przypomni sobie, że powinien dodać jeszcze dwie? Wtedy od nowa wszystko? :-)
    Zamiast tablicy zastosuj listę.

  • Takie rzeczy jak ta metoda public double obliczWartosc() można, a nawet trzeba zastąpić własnością:

public double Wartosc
{
    get => cena * ileSztuk;
}
  • Analogicznie do tego co napisał @furious programming, metoda public void dodajPozycje(Pozycja p) powinna zajmować się jedynie dodawaniem nowej pozycji, a nie wypisywaniem informacji na ekranie.

  • Pętla w tej metodzie jest bez sensu:

public void dodajPozycje(Pozycja p)
        {
            for (int i = 0; i < ileDodanych; i++)
            {
                pozycje[i] = p;  
            }
        }

Skoro masz informacje o tym ile pozycji jest dodanych do nie potrzeba robić iteracji. Starczy, że zrobisz: pozycje[++ileDodanych] = p;, choć cała idea wykorzystania tutaj tablicy jest bez sensu, jak wcześniej pisałem i chyba także źle rozumiem to co ta zmienna ma robić. Nie mniej jest to bez sensu. :-)

Zrobiłbym coś w stylu:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _4p
{
    class Product
    {
        public string Name { get; private set; }
        public decimal Price { get; private set; }
        public int Count { get; private set; }
        public decimal Value { get => Price * Count; }

        public Product(string name, decimal price, int count)
        {
            Name = name;
            Price = price;
            Count = count;
        }

        public override string ToString()
        {
            return $"Nazwa: {Name}, Cena: {Price}, Ilość: {Count}szt, Wartość: {Value}";
        }
    }

    class Order
    {
        private IList<Product> products = new List<Product>();

        public void AddProduct(Product product)
        {
            products.Add(product);
        }

        public override string ToString()
        {
            var sb = new StringBuilder();
            foreach (var p in products)
            {
                sb.AppendLine(p.ToString());
            }
            return sb.ToString();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var p1 = new Product("Volvo", 100m, 2);
            var p2 = new Product("Citroen", 50m, 3);

            var order = new Order();
            order.AddProduct(p1);
            order.AddProduct(p2);

            Console.WriteLine(order.ToString());
        }
    }
}

IMHO ucząc się C# powinieneś raczej ukierunkowywać kod swoich programów na składnie i możliwości tegoż, zamiast sztywno trzymać się konwencji z zadań Javowych.

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