Trochę przesadziłem z tymi moimi włosami, sprawdziłem i okazało się, że tylko osiwiałem
Może nie tragiczny, w końcu twój kod uzyskał AC, ale bardziej zaawansowany koder zobaczyłby wiele rzeczy, które zrobiłby inaczej - prościej, np.:
1.
zamiast
int t = 0;
int k = 0;
można
int t, k; //nie trzeba ich zerować, bo zostaną za chwilę "nadczytane" nową wartością
gdybyś chciał nadać wartość początkową, to można:
int t = 0, k = 999;
2.
zamiast:
float min = 0;
float srednia = 0;
float suma = 0;
float roznica = 0; //nie jest używana
można:
double min, //nie trzeba zerować
srednia, //nie trzeba zerować
suma; //nie trzeba zerować w tym miejscu, tylko w pętli
//gdy nie wiesz czemu, używaj double a nie float
3.
zamiast [w pętli]:
suma = 0;
srednia = 0; //to jest tu zupełnie niepotrzebne
k = 0; //to jest tu zupełnie niepotrzebne
cin >> k;
można:
double suma = 0; // wtedy nie potrzebna deklaracja zmiennej suma wcześniej
cin >> k;
4.
tablica2 nie jest potrzebna, można "na bieżąco" przeglądać pierwszą tablice i "na bierząco" od razu zapamiętrywać pozycję [i] minimum.
Skoro tak, to spora dalsza część programu będzie zbędna.
Duża część zmiennych [większość] mogłaby być typu int, a tylko napewno średnia musi być typu rzeczywistego, np double.
Chyba tylko tyle
pozdrawiam i powodzenia.
Poprawnie:
w = tablica
lub
w = &tablica[0]
w - wskaźnik
*w - wartość "wskazywana" przez wskaźnik w
int *w deklaracja zmiennej wskaźnikowej w
Pozwolę sobie na jeszcze jedną uwagę.
Prawidłowo:
int *w = tablica; /// tu w takim przypadku wystarczyłoby int *w;
pętla [while, for, do]{
w = tablica;
....
}
A poniższy fragment, czy też działa poprawnie [tylko c++] i dlaczego [pytanie retoryczne, ja wiem, ale czy Ty to wiesz] ?
/// int *w = tablica; /// "przenosimy" do środka pętli
pętla [while, for, do]{
int *w = tablica;
....
}
Po przeanalizowaniu wydaje mi się to jasne. Gdy piszemy int w to nie mamy do czynienia już ze wskaźnikiem tylko zmienną typu liczby całkowitej o nazwie *w która ma wartość danego elementu tablicy. Tak mi się wydaje. Z drugiej strony gdy adres wskaznika ma przypisany adres pierwszego elementu tablicy (int *w,tablica; tablica=new int [cos]; w=tablica;) to wypisujac *w to pobieramy wartosc z pierwszego elementu tablicy a inkrementujac adres wskaznika dla inta, jego adres zwieksza sie o 4 czyli *w pobiera wartość z następnego elementu tablicy. Dobrze to rozumiem ?
Po przeanalizowaniu, twojej analizy, wydaje mi się, że to jest jednak, u Ciebie, nadal nie zupełnie jasne
Poprawione twoje zdanie/myśl:
Gdy piszemy:
int w;
to deklarujemy zmienną typu int o nazwie w, która nie ma nic wspólnego ani z wskaźnikiem ani z tablicą. Jest po prostu [sobie] zwykłą zmienną, która "przechowuje" [zawiera, "pamięta"] dowolną wartość liczbową w zakresie int [-2^31, +2^31-1].
Poprawione twoje zdanie/myśl:
... gdy wskaznik ma przypisany [zawiera/"pamięta"] adres pierwszego elementu tablicy:
int *w, *tablica;
tablica = new int [cos]; //po co tak?*/ a jeżeli już tak, to linię wcześniej *tablica
w = tablica;
to wypisujac *w pobieramy wartosc pierwszego elementu tablicy, a inkrementujac wskaznik ++w, typu int, jego wartość [przechowywany/wskazywany adres] zwieksza sie [dla typu int o 4] czyli *w [pobiera] jest wartością następnego elementu tablicy.
W tym wypadku, tak naprawdę, wskaźnik nie różni się specjalnie od indeksu tablicy, więc jak masz kłopoty ze zrozumieniem działania wskaźników, to może na razie zapomnij o wskaźnikach a używaj po prostu zwykłej tablicy i jej indeksów.
Ewentualnie poczytaj w "dobrej" książce rozdział poświęcony wskaźnikom.
W takim razie, po co są w ogóle wskaźniki, jeżeli są tym samym co indeks tablicy?
1. Czasami wskaźnik/i upraszczają zapis kodu.
2. Gdy tablica jest dwu i więcej wymiarowa i gdy koder wie jak poszczególne elementy takiej tablicy "siedzą/leżą" w pamięci i gdy koder wie co robi ..... to czasami używa wskaźników.
3. Użycie wskaźników czasami skraca znacząco kod i ukrywa/szyfruje jego faktyczne działanie [gdy brak komentarzy] przed okiem laika. [to taki trochę żart]
4. Koder, który liznął assemblera lub który orientuje się jak "to" działa od środka [procesor, pamięć, język maszynowy/assembler] nie powinien mieć problemu ze zrozumieniem i stosowaniem wskaźników lub z rezygnacji z ich usługi.
5. Gdy koder/programista używa tablic i struktur dynamicznych [alokowanych dynamicznie], wtedy wskaźniki mogą być/[są] niezastąpione.
PS
Uważam jednak, że więcej zyskasz czytając porządny opis tego wszystkiego, niż to co ja napisałem. Jeżeli jednak spodobał Ci się mój opis, domagam się serduszek w dużej ilości Z góry dzięki
*/ Zmienna tablica jest już wskaźnikiem, więc nie jest potrzebny następny wskaźnik: w
W takim przykładzie możemy zadeklarować tablicę statycznie:
int *w, tablica[coś];
Dobra, już rozumiem. Zmyliła mnie nazwa zmiennej. Rozjaśniła mi wszystko Twoja wypowiedź z tą deklaracją zwykłej zmiennej. Haha wiem trochę o tych pamięciach procesora, sam programuje płytki MSP430 na laboratoriach z Architektury Komputerów więc ogólną koncepcję liznąłem. Wskaźniki są niezastąpione według mnie choćby w celu użycia ich w strukturach danych typu lista, drzewo binarne no i nieraz znacznie skracają czas działania algorytmu gdzie zamiast właśnie jadąc po indeksach komputer przeskakuje po andresach zmiennych elementów tablicy.
Pozdrawiam i życzę udanego weekendu =)
Czy ktoś mógłby mi wytłumaczyć, dlaczego ten kod jest zły? https://ideone.com/INojNx67
Strzelałbym, że problem tkwi w tym punkcie
if((tab[y]==srednia-mini)||(tab[y]==srednia+mini))
przykład : średnia = 10;
mini = 5;
jeżeli t[0] == 10-5=5 lub t[0]= 10+5=15 to wszystko jedno i to samo, niech będzie moim wynikiem !
5 i 15 to nie to taka sama wartość przyjacielu
Do tego zaokrąglij sobie średnią gdy ją liczysz funkcją round.
Pozdrawiam
Przez tego if'a SPOJ nie chce zaliczyć mi zadania?
Wcześniej obliczona minimalna odległość wskazuje na liczbę najbliższą średniej, którą można przedstawić w postaci srednia-mini lub srednia+mini.
Ponieważ nie wiadomo czy najpierw wprowadzona została 5 czy 15, ten if ma kolejno sprawdzić wszystkie elementy tablicy i znależć pierwszą liczbę której odległość od średniej jest równa mini.
Albo 5 albo 15, nie ma różnicy, bo są tak samo oddalone od średniej
Co zmieni zaokrąglenie średniej?
Nie wiem, czemu SPOJ nie zalicza Ci tego kodu, ale mi też się twój kod nie podoba.
- Gdy używasz zmiennej typu double unikaj "dokładnego" jej porównywania --> "=="
- Taką funkcjonalność [3 x if] ma funkcja fabs(...) [nie mylić z abs]
Czy to powoduje WA? nie wiem i w tej chwili nie ma tego jak sprawdzić.
===============
JUŻ MOŻNA
===============
Faktycznie poniższa linijka jest błędem - błędy zaokrąglenia liczb zmiennoprzecinkowych:
Popraw to na:
if (odl[y] == mini)
Ale i tak twój kod dalej będzie mnie straszył i nawiedzał po nocach
Powyższa poprawka to tylko taka proteza - minimum na AC. Poprawić możnaby i należało dużo więcej.
Najpierw popraw swój kod, żeby był bardziej czytelny. Zastosuj wcięcia i popraw obie pętle for, bo nie wiem czy ci ucięło coś w tym kodzie, czy nie wiesz jak działa ta pętla. Od wklejania kodu formatowanego z wcięciami służy znacznik BBone.
PS. Ewentualnie możesz wkleić swój kod na ideone i podać linka na forum.
Bbone tutaj niestety nie działa. Przy edycji, zaznaczamy myszą wklejony kod i albo klikamy </> albo wciskamy dwa klawisze ctr k
PS
@jasieka - właśnie to za Ciebie zrobiłem.
PS 2
Kilka postów wyżej - fabs
A co gdy tym szukanym jest pierwszy element tablicy? : http://discuss.spoj.com/t/1102-srednia-arytmetyczna-pp0604a/11685/22
po pierwsze, do porównywania liczba z przecinkiem służy fabs, abs jest tylko do całkowitych. Poza tym zeruj jciekawe przy każdym obrocie pętli for (int i...), a najlepiej przenieś deklarację tej zmiennej do niej, poza nią potrzebujesz przecież tylko t. Po tym powinno ci zaliczyć to zadanie, nie zapomnij usunąć kodu jak to zrobi.
#include <iostream>
using namespace std;
int main()
{
int t;
cin>>t;
for(int i=0;i<t;i++)
{
int ile;
int suma=0, srednia=0;
cin>>ile;
int *tab;
tab = new int [ile];
for(int i=0;i<ile;i++)
{
cin>>tab[i];
suma += tab[i];
}
srednia = suma/ile;
int naj;
naj=srednia;
for(int i=0;i<ile;i++)
{
if (tab[i]>naj)
{
naj-tab[i]<naj;
tab[i]=naj;
}
else if (tab[i]<naj)
{
(naj-tab[i])*(-1)<naj;
tab[i]-naj;
}
}
cout<<naj<<endl;
delete [] tab;
}
return 0;
}
Witam! Mógłby mi ktoś pomóc w znalezieniu błędu w tym kodzie?
Błąd pierwszy:
int srednia;
a przez to błąd jest tutaj:
srednia = suma/ile;
Zauważ, że średnia rzadko kiedy jest liczbą całkowitą Ale to nie są jedyne błędy.
Nie wiem jak inni (bo ja może jestem w błędzie), ale całkowicie nie rozumiem tego zapisu w "ifach"...
if (tab[i]>naj)
{
naj-tab[i]<naj;
tab[i]=naj;
}
else if (tab[i]<naj)
{
(naj-tab[i])*(-1)<naj;
tab[i]-naj;
}
}
To chyba jest bez sensu. Mówię o tych porównaniach
To w ifach to jest tak że jak liczba jest mniejsza od naj które początkowo jest średnią to się ją tylko odejmuje i najmniejsza z nich będzie najbliższa średniej a jak liczba jest większa od naj to też się ją od naj odejmuje tylko że wtedy wyjdzie minus i dzięki *(-1) zamieni się na plus i najmniejsza będzie najbliższa średniej, Trochę pogmatwane ale na kartce działa