Przenoszenie zmiennej do innej metody

2

Witam

Ćwiczę sobie podstawy klas, metody itp. i chciałem zrobić takie zadanko, ale mam problem ze zmienną.
Ogólnie chodzi o to że mam tablice, a w niej kilka zmiennych. Jedną metodą zsumowałem wszystkie zmienne, a w drugiej metodzie chciałbym sprawdzić czy ich suma jest podzielna przez 3 i tu następuję problem.
Wiem co jest nie tak, ale nie wiem jak to naprawić.
Zainicjowałem na początku zmienną 'wynik' i w metodzie sumowania zmienna 'wynik' jest ok, ale gdy chcę jej użyć w metodzie dzielenie to zmienna 'wynik' jest pobierana z samej góry, czyli domyślnie 0.
Próbowałem już używać polecenia 'this.', ale to raczej jest stosowane pomiędzy klasami, a nie metodami.
Próbowałem również przypisać nową zmienną do 'wynik ( int wynik2 = wynik;), ale efekt jest ten sam.
Kolejnym moim pomysłem było zainicjowanie zmiennej w konstuktorze, ale to też mi średnio wyszło.
Problem jest pewnie łatwy do rozwiązania, ale utknąłem w miejscu i już nie mam pomysłów.

Kod prezentuję się tak:

class Program
    {
        static void Main(string[] args)
        {
            Sumator suma = new Sumator();
            Sumator sumapodziel3 = new Sumator();
            Console.WriteLine(suma.Suma());
            Console.WriteLine(sumapodziel3.SumaPodziel3());

            Console.ReadLine();

        }
    }
    class Sumator
    {
        int[] Liczby = new int[] { 435, 32, 23, 65 };
        double dzielona;
        int wynik;

        public double Suma()
        {
            for (int i = 0; i < Liczby.Length; i++)
                wynik += Liczby[i];
            return wynik;
        }
        public double SumaPodziel3()
        {
             dzielona = wynik / 3;
            if (dzielona % 3 == 0)
                Console.WriteLine("Suma liczb jest podzielna przez 3 ");
            else
                Console.WriteLine("Suma liczb nie jest podzielna przez 3");

            return dzielona;

            

        }
4

Każdy obiekt ma własny zestaw pól (zmiennych), więc suma.wynik i sumapodziel3.wynik będą mieć inne wartości. Musisz wywołać Suma() i SumaPodziel3() na tym samym obiekcie.
Poza tym niewiele umiesz. Z czego się uczysz, masz jakąś książkę, tutorial?

1

Po co dzielisz przez 3 a potem jeszcze modulo 3?
Nie zainicjalizowałeś zmiennych.
Pracujesz na intach, po co Ci double? Modulo z int zwróci Ci int. Wynik dzielenia int przez int też da Ci int.

{
             dzielona = wynik / 3;
            if (dzielona % 3 == 0)
                Console.WriteLine("Suma liczb jest podzielna przez 3 ");
            else
                Console.WriteLine("Suma liczb nie jest podzielna przez 3");

            return dzielona;

        }

Zanim zaczniesz łapać się za klasy zrób dobrze podstawy. Przede wszystkim przekazywanie wartości do metody/funkcji przez argument.
Jeśli chodzi o klasy sprawdź jak wywołać metodę. To co napisałeś nie ma prawa się wykonać. Nazwy suma, sumapodziel3 to instancje (stworzenie obiektu) klasy a nie wywołanie metody. W dodatku sam sobie wprowadzasz chaos przez złe użycie ich nazw.

Zajrzyj tutaj:
http://c-sharp.ue.katowice.pl/?page_id=36
Tu znajdziesz rozwiązanie twojego problemu, a właściwie wszystkich twoich problemów. Ta książka jest udostępniona za darmo. Powinna być idealna dla Ciebie. 200 stron samej praktycznej wiedzy.

0

odradzam ćwiczenia przez robienie rzeczy niepotrzebnie skomplikowanych

import java.util.stream.*;

public class Sum {
	public static void main(String []args) {
		System.out.println(
			Stream.of(args)
				.mapToInt(s -> Integer.parseInt(s))
				.reduce(0, (acc, n) -> (acc + n))
		);
	}
}

Java 8

2

@rdk: Masz problem z zagadnieniami, do których potrzebne są podstawy języka:

  • Nie musisz robić sumowanie w pętli. Starczy skorzystać z mechanizmów języka i zrobić np. tab.Sum():
int[] tab = new int[] { 1, 2, 3, 4, 5 };
Console.WriteLine($"Suma: {tab.Sum()}");
  • Niepotrzebnie tworzysz osobne instancje klasy do wykonania każdej metody i dlatego chcesz niepotrzebnie przekazywać zmienne pomiędzy klasami.
  • Tak naprawdę ta klasa powinna być statyczna, bo nie ma sensu tworzenie instancji tylko po to by stwierdzić, że suma w tablicy jest podzielna przez 3 czy po to by zsumować elementy tablicy. Popatrz np. na klasę Math, wbudowaną w język;
0
kamil napisał(a):

Każdy obiekt ma własny zestaw pól (zmiennych), więc suma.wynik i sumapodziel3.wynik będą mieć inne wartości. Musisz wywołać Suma() i SumaPodziel3() na tym samym obiekcie.
Poza tym niewiele umiesz. Z czego się uczysz, masz jakąś książkę, tutorial?

Trochę źle zrobiłem, bo nie podałem jakie jest polecenie zadania. Chcę zrobić coś takiego i dlatego zrobiłem dwie osobne metody

Stwórz klasę Sumator z:
• publicznym polem Liczby będącym tablicą liczb
• metodą Suma zwracającą sumę liczb z pola Liczby
• metodę SumaPodziel3 zwracającą sumę liczb z tablicy, które są podzielne przez 3

Uczę się z kursu na udemy. Jestem na początku z programowania obiektowego dlatego wygląda to jak wygląda.

#####GironX napisał(a)
Po co dzielisz przez 3 a potem jeszcze modulo 3?
Nie zainicjalizowałeś zmiennych.
Pracujesz na intach, po co Ci double? Modulo z int zwróci Ci int. Wynik dzielenia int przez int też da Ci int.

Dzielenie np. 555 przez 3 da liczbę po przecinku dlatego użyłem typu double.

#####grzesiek51114 napisał(a)
Nie musisz robić sumowanie w pętli. Starczy skorzystać z mechanizmów języka i zrobić np. tab.Sum():

Jestem dopiero na początku i nie korzystałem jeszcze z takich gotowców. Nigdy też nie używałem $ w pisaniu. Najpierw chcę żeby to w ogóle działało, a później 'ulepszać'

#####grzesiek51114 napisał(a)
Niepotrzebnie tworzysz osobne instancje klasy do wykonania każdej metody i dlatego chcesz niepotrzebnie >przekazywać zmienne pomiędzy klasami.

Myślałem, że dla każdej metody musi być osobna instancja, ale spróbowałem na jednej i działa, nawet daje wynik z tego dzielenia więc tutaj musiał być problem. Dzięki :D
Wiem, że robię jeszcze dużo głupich błędów, ale właśnie taką metodą prób i błędów chcę się nauczyć.
Tak jak wspomniałem, uczę się z kursu, a tam nie ma żadnych zadań żeby robić samemu.

2

Stwórz klasę Sumator z:
• publicznym polem Liczby będącym tablicą liczb
• metodą Suma zwracającą sumę liczb z pola Liczby
• metodę SumaPodziel3 zwracającą sumę liczb z tablicy, które są podzielne przez 3

Twoje pole Liczby nie jest publiczne
Niepotrzebnie zapisujesz wynik sumowania.
SumaPodziel3 jest zupełnie źle zrobiona, przeczytaj jeszcze raz dokładnie zadanie.

Dzielenie np. 555 przez 3 da liczbę po przecinku dlatego użyłem typu double

Dzielenie liczb całkowitych zwróci liczbę całkowitą, tzn. 3/2 da 1 a nie 1.5
Poza tym % 3 na liczbie podzielonej przez 3 dałoby ci informację o podzielności przez 9.

PS jeżeli faktycznie uczysz się z jakiegoś kursu to przerób go porządnie, inaczej nie skończysz tej politechniki

0

@kamil: aa faktycznie źle to zinterpretowałem.

Poprawiłem kod i wygląda to teraz tak:

lass Program
    {
        static void Main(string[] args)
        {
            Sumator suma = new Sumator();
            Console.WriteLine(suma.Suma());
            Console.WriteLine(suma.SumaPodziel3());

            Console.ReadLine();
        }
    }
    class Sumator
    {
        public int[] Liczby = new int[] { 485, 9, 27, 65 };
        int wynik;
        int podzielne;

        public int Suma()
        {
            Console.WriteLine($"Suma liczb z tablicy:  {Liczby.Sum()}");
            return wynik;
        }
        public int SumaPodziel3()
        {
             for( int i = 0; i < Liczby.Length; i++)
            {
                if (Liczby[i] % 3 == 0)
                {
                    Console.WriteLine("Liczba {0} jest podzielna", i);
                    podzielne += Liczby[i];
                }
            }
            Console.WriteLine("Suma liczb podzielnych przez 3: " + podzielne);
            return podzielne;
        }
    }
}

Wydaje mi się, że według poleceń z zadania wszystko jest ok, ale mam jeszcze pytanie. Skoro robię metodę to muszę coś zwrócić i w moim przypadku jest to bezsensowne, bo wypisuję jakby dwa razy wynik. Jest jakiś sposób, żeby nie użyć tego 'return', albo żeby to ładniej wyglądało?
Spotkałem się ze stwierdzeniem 'void', ale nie za bardzo mi to działało.
Mógłbym też jakoś lepiej zainicjalizować zmienne np. od razu w metodzie, albo tak jak właśnie napisał @kamil jak nie zapisać tego sumowania?

2

Jeżeli nie chcesz zwracać wyniku z funkcji, to jako typ zwracanej wartości dajesz void. Ale w twoim zadaniu jest napisane, że metoda ma zwraca sumę, czyli musisz użyć return, a wywal Console.WriteLine z metody.

Czemu nie używasz zmiennych lokalnych?

PS. Jeżeli pomogłem to zostaw łapkę w górę przy moich postach.

1

@rdk: Lepiej zrobić z tego klasę statyczną i przekazywać obiekty przez argumenty metod.

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

namespace _4p
{
    static class MyMath
    {
        public static int Sum(int[] tab)
            => tab.Sum();

        public static int SumDivisableBy(int number, int[] tab)
            => tab.Where(d => d % number == 0).Sum();
    }

    class Program
    {
        public static void Main(string[] args)
        {
            int[] tab = new int[] { 2, 3, 4, 5, 6, 7, 8, 9 };
            Console.WriteLine($"Suma: {MyMath.Sum(tab)}");
            Console.WriteLine($"Suma podzielnych przez 3: {MyMath.SumDivisableBy(3, tab)}");
        }
    }
}
0

@rdk Twój kod wygląda już ok. Co do "void" to możesz go zastosować, tylko wtedy nie możesz nic zwracać (trzeba usunąć "return ..."). Oraz usunąć Console.WriteLine z Maina. Możesz też zostawić to zwracanie i usunąć wypisywanie na ekran w tych metodach.

@grzesiek51114 na Linq jeszcze przyjdzie czas :) no i to już przestaje być programowanie obiektowe.

0
using System;
namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int dz = 3;
            int sum = MyMath.SumaLiczb(new int[] { 3, 9, 12, -4, 10, 56, 3, 23, -10 });
            if (MyMath.CzyPodzielnaPrzez(sum , dz))
            {
                Console.WriteLine("Liczba {0} jest podzielna przez {1}", sum, dz);
            };
        }
    }

    public class MyMath
    {
        public static int SumaLiczb(int[] tabliczb)
        {

            int suma = 0;
            for (int i = 0; i < tabliczb.Length; i++)
            {
                suma = suma + tabliczb[i];
            }
            return suma;
        }

        public static bool CzyPodzielnaPrzez(int liczb, int dz)
        {
            return liczb % dz == 0;
        }
    }
}
0

Jak nie chcesz używać wbudowanej metody Sum(), no bo co to za programowanie pisać funkcję sumującą przy użyciu funkcji Sum() .... ;) ,to polecam Ci bardziej hipsterskie rozwiązanie:

public static int SumDivisableBy(int number, int[] tab)=> tab.Aggregate(0,(x, y) => y % number == 0 ? x + y : x);
0

Wiem że to można zrobić lepiej lub gorzej . Ze statycznymi składowymi trzeba ostrożnie bo one istnieją przez cały czas działania programu .

using System;
namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int dz = 3;
            int sum = MyMath.SumaLiczbPodzielnychPrzez(new int[] { 3, 9, 12, 4, 10, 56, 3, 23, 10 }, dz);
            Console.WriteLine("Suma liczb podzielnych przez {0} = {1}", dz, sum);
        }
    }

    public static class MyMath
    {
      
        public static int SumaLiczbPodzielnychPrzez(int[] tabliczb, int dz)
        {
            int suma = 0;
            for (int i = 0; i < tabliczb.Length; i++)
            {
                if (CzyPodzielnaPrzez( tabliczb[i], dz))
                suma = suma + tabliczb[i];
            }
            return suma;
        }

        public static bool CzyPodzielnaPrzez(int liczb, int dz)
        {
            return liczb % dz == 0;
        }
    }
}
0

Spróbuj coś w ten deseń ale np z pętlą for, żebyś zrozumiał o co chodzi. Mam wrażenie, że nie bardzo rozumiesz jak działa operator modulo.

public int SumaPodziel3(int[] liczby)
        {
            int suma3 = 0;
            foreach (var item in liczby)
            {
                if (item % 3 == 0)
                {
                    suma3 += item;
                }
            }
            return suma3;
        }

0

O właśnie. O to chodzi, żeby ktoś obcy nie miał dostępu do biblioteki. Do biblioteki ma mieć dostęp tylko obiekt. Metody mają być publiczne, klasy internal albo protected, właściwości private. Czasami faktycznie klasa musi być publiczna, ale nie w tym wypadku. Obejrzyj to sobie: https://github.com/igorzeler/Training/tree/master/4pr-Sumator

0

@kamil: Poprawiłem na coś takiego:

class Program
    {
        static void Main(string[] args)
        {
            Sumator suma = new Sumator();
            suma.Suma(0);
           suma.SumaPodziel3(0);

            Console.ReadLine();
        }
    }
    class Sumator
    {
        public int[] Liczby = new int[] { 485, 9, 23, 65 };

         public void Suma(int wynik)
        {
            wynik = Liczby.Sum();
            Console.WriteLine("Suma liczb z tablicy: " + wynik);
        }
         public void SumaPodziel3(int podzielne)
        {
             for( int i = 0; i < Liczby.Length; i++)
            {
                if (Liczby[i] % 3 == 0)
                {
                    Console.WriteLine("Liczba {0} jest podzielna", i);
                    podzielne += Liczby[i];
                }
            }
            Console.WriteLine("Suma liczb podzielnych przez 3: " + podzielne);
        }
    }

Wszystko działa tylko nie jestem za bardzo przekonany do tych zer tutaj: 'suma.Suma(0); suma.SumaPodziel3(0);'. Wydaje mi się, że obszedłem problem, ale nie jest to dobre rozwiązanie.

1

Ty dodałeś parametry do metod a ja pisałem, żebyś dodał zmienne lokalne:

public int Suma()
{
  int wynik = 0;
  wynik = Liczby.Sum();
  return wynik;
}

oczywiście w tym przypadku można obejść się bez używania zmiennych

public int Suma()
{
  return  Liczby.Sum();
}

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