1 / 13
Nov 2017

Cześć, jestem początkujący, dlatego potrzebowałbym Waszej pomocy. Przerabiam kurs od zera do bohatera Mirosława Zelenta na yt. Dodatkowo zaczynam robić zadnka ze SPOJ-a. W jednym z nich potrzebuję zamienić łańcuch znaków (w którym liczby są przedzielone spacją ) na tablicę liczb. Próbowałem już na różne sposoby, napisałem dwa programy i każdy z nich nie działa.
Te wszystkie couty itd. w moich programach to dlatego, że starałem się znaleźć błąd, i sprawdzałem jak program działa.
Pierwszy z nich:

#include <iostream>
#include <cstring>
#include <math.h>

using namespace std;


int main() {
char liczba_przed_konwersja[20];
string przyklad,przyklad2;
for (;;)
{
cout<<"Podaj: "<<endl;
getline(cin,przyklad2);
przyklad=przyklad2;
int dlugosc_inta;
int a=0;
double liczba=0;
int *tablica_liczb;
int ile=0;
przyklad=przyklad + " ";
tablica_liczb = new int [przyklad.length()/2];
int b=0;

cout<<przyklad.length()<<endl;
char * tablica = new char[przyklad.length()-1];
strcpy( tablica, przyklad.c_str() );
delete [] tablica;


if (tablica[0]==' ')
{
    cout<<"prawda"<<endl;
}
    for (int i=0;i<przyklad.length();i++)
{
    cout<<tablica[i]<<"!";
    b++;
}
    cout<<"Przyklad.length"<<przyklad.length()<<endl;
    cout<<"B. "<<b<<endl;


    cout<<endl;
    for (int i=0;i<przyklad.length();i++)
    {
            cout<<"for2"<<endl;
            liczba_przed_konwersja[a]=tablica[i];
            a++;
            if (tablica[i]==' ')
            {
                cout<<"if 1"<<endl;
                for (int i=0;i<a-1;i++)
                {
                    cout<<"a: "<<a<<endl;
                    cout<<"potega"<<pow(10,(a-2-i))<<endl;
                    liczba+=(liczba_przed_konwersja[i]-48)*pow(10,(a-2-i));
                    cout<<i<<". "<<liczba<<endl;
                }
                ile++;
                *tablica_liczb=liczba;
                cout<<"teraz"<<endl;
                cout<<liczba<<endl;

                a=0;
                liczba=0;
                tablica_liczb++;


            }

    }
delete [] tablica_liczb;
tablica_liczb-=ile;
cout<<"!!!!"<<endl;
for (int i=0;i<ile;i++)
{
    cout<<*tablica_liczb<<endl;
    tablica_liczb++;
}
}

    return 0;
}

Nie utworzyłem tutaj nawet tablicy, bo program nie działa prawidłowo tzn, np. w drugiej pętli obcina pierwszy znak.

drugi z nich: (myślę, że lepiej napisany, przejrzyściej - nim się zajmijmy):

#include <iostream>
#include <cstring>
#include <math.h>

using namespace std;


int main() {
char liczba_przed_konwersja[20];
string przyklad,przyklad2;
for (;;)
{
cout<<"Podaj: "<<endl;
getline(cin,przyklad2);
przyklad=przyklad2;
int dlugosc_inta;
int a=0;
double liczba=0;
int *tablica_liczb;
int ile=0;
przyklad=przyklad + " ";
tablica_liczb = new int [przyklad.length()/2];
int b=0;

cout<<przyklad.length()<<endl;
char * tablica = new char[przyklad.length()-1];
strcpy( tablica, przyklad.c_str() );
delete [] tablica;


if (tablica[0]==' ')
{
    cout<<"prawda"<<endl;
}
    for (int i=0;i<przyklad.length();i++)
{
    cout<<tablica[i]<<"!";
    b++;
}
    cout<<"Przyklad.length"<<przyklad.length()<<endl;
    cout<<"B. "<<b<<endl;


    cout<<endl;
    for (int i=0;i<przyklad.length();i++)
    {
            cout<<"for2"<<endl;
            liczba_przed_konwersja[a]=tablica[i];
            a++;
            if (tablica[i]==' ')
            {
                cout<<"if 1"<<endl;
                for (int i=0;i<a-1;i++)
                {
                    cout<<"a: "<<a<<endl;
                    cout<<"potega"<<pow(10,(a-2-i))<<endl;
                    liczba+=(liczba_przed_konwersja[i]-48)*pow(10,(a-2-i));
                    cout<<i<<". "<<liczba<<endl;
                }
                ile++;
                *tablica_liczb=liczba;
                cout<<"teraz"<<endl;
                cout<<liczba<<endl;

                a=0;
                liczba=0;
                tablica_liczb++;


            }

    }
delete [] tablica_liczb;
tablica_liczb-=ile;
cout<<"!!!!"<<endl;
for (int i=0;i<ile;i++)
{
    cout<<*tablica_liczb<<endl;
    tablica_liczb++;
}
}

    return 0;
}

Program działa pięknie, dopóki łańcuch znaków, który podaję przez cin nie przekroczy długości 9. Pętla jest nieskończona tylko do testów.

  • created

    Nov '17
  • last reply

    Nov '17
  • 12

    replies

  • 1.5k

    views

  • 3

    users

  • 1

    like

  • 5

    links

Poprawiłem twoje wklejenie i niestety to by było na tyle z mojej strony.

Powodzenia

PS
Przeniosłem też wątek z pl.spoj.com4 do innego działu.

Poprzez edycję, możesz wejść do swojego postu i zobaczyć jak to zrobiłem [nie jest to jedyny sposób].

widzę już, dzięki, następnym razem bez takiej fuszerki będzie.

Cześć :stuck_out_tongue:

Od zera na pewno, ale czy do bohatera? Wyszukaj hasło “Mirosław Zelent” na SPOJu a wyjdzie, co wyjdzie :wink:

Nie rozumiem na czym polega Twoja trudność, ale w tym kodzie ciężko cokolwiek ogarnąć m.in. z powodu formatowania i coutów (kurs od zera do… a no tak!).

Poniżej przykładowa koncepcja. Kod jest tragicznie napisany i sam nigdy bym tego tak nie zrobił :wink: Ale to celowe. 1) Jest tam kilka rzeczy, które nie koniecznie powinny być używane, ale warto wiedzieć, że istnieją. 2) Algorytm jest tragiczny, ale na ile pamiętam moje początki w kodzeniu - bardzo intuicyjny gdy ktoś nie zna dobrze danego języka. Ściślej: nie optymalizuj, nie komplikuj, nie googluj funkcji tylko pisz własne itd. Dziel program na części i na tą chwilę nie przejmuj się tym, że coś liczysz kilka razy bo nie umiesz tego w jakiś fajny sposób (np w strukturze) zapamiętać.

#include <bits/stdc++.h>

int main(int argc, char* argv[])
{
  std::string s = "1 2 3 4 5 6 7 13 9 12312 1233 4 23 25 3 543321 312 3432543 353 54";
  int ile_liczb;
  int* tablica_z_liczbami;
  int ile_cyfr_ma_ita_liczba_w_stringu[1000];

  for(std::size_t i = 0; i < s.length(); ++i) {
    //Stworz wlasna funkcje typu token/tokenize/atoken/... cos a la token ;)
    //Innymi slowy policz ile jest liczb w stringu, a wynik zapisz w ile_liczb
    //Jednoczesnie dla kazdej kolejnej liczby policz ile ma cyfr i zapamietaj tam gdzie trzeba
  }

  //Dynamiczna alokacja tablicy odpowiednich rozmiarów 

  //Jeszcze raz peta for po od 0 do ile_liczb
  //W niej kolejna petla for korzystajaca z informacji o tym ile cyfr ma liczba w stringu
}

Jak zrobisz działający program wg tej albo jakiejś innej koncepcji to pewnie uznasz, że kod jest tragiczny. Słusznie! Kolejne zadanie to napisać to ładnie i wydajnie :wink:

I w sumie nie wiem co jeszcze mogę Ci napisać nie dając gotowca.

EDIT
Wiem, co jeszcze mogę Ci napisać. Nie realizuj schematu z mojego kodu! Stwórz jednak własny kilkuczęściowy schemat i realizuj go część po części. Gdy testy wykażą, że jedna część jest dobra, dopiero przechodź do następnej.

  1. Wczytaj wejście
  2. Stwórz coś w rodzaju: podaj mi i-tą liczbę w ciągu jako string
  3. Stwórz coś w rodzaju: podaj mi ile cyfr ma i-ta liczba w ciągu (wynik to int)
  4. Stwórz coś w rodzaju: zamień i-tą liczbę w stringu na inta. Nie używaj funkcji pow.
  5. Stwórz coś w rodzaju: zamień każdą liczbę w stringu na inta i zapisz do tablicy intów
  6. Zastanów się, czy da się to zrobić lepiej.

EDIT 2
Dobra, przeczytałem to co napisałem raz jeszcze i wydaje mi się, że bardziej namieszać Ci nie mogłem. Jeżeli tak to przepraszam i zignoruj mój post. Widać nie każdy może być nauczycielem.

Jutro napiszę kod, który będzie robił po kolei to co wymieniłeś. Ale powiedz mi jeszcze jak nie używając powa zmienić dowolną liczbę zapisaną jako string na inta. A te wszystkie couty to dlatego, żeby widzieć po kolei gdzie wchodzi, jakie wartości przyjmuje itp, metodą prób i błędów chciałem dociec czemu program nie działa. Ale nie dociekłem jak widać… no dobra to tyle :slight_smile:

Powa możesz napisać własnego :slight_smile: Do wyboru while coś mnożysz przez 10 vs Exponentiation by squaring. Oczywiście kod możesz pisać jak chcesz, niemniej zalecam jak najszybciej przejść na funkcje - dla tak prostej funkcjonalności za trudne to nie będzie, za to uda Ci się w pełni “zmodularyzować” program. Jeżeli Ci to pomoże możesz najpierw robić wszystkie funkcje jako void i mogą one operować na zmiennych globalnych, a dopiero jak program zacznie działać - w ramach pierwszej poprawki - zrób porządne funkcje, które przyjmują i zwracają odpowiednie zmienne. Szybko zauważysz, że rozbijanie kodu na funkcje ułatwia pracę nad nim. Nie używaj jeszcze struktur, ale wskazane jest byś użył choć raz goto (niekoniecznie w tym programie, ale może w jakimś innym?) - tylko wtedy dowiesz się, dlaczego to zło wcielone.

Oczywiście to tylko mój pomysł na sensowną acz intensywną i może czasochłonną naukę. Możesz go odrzucić jeżeli Ci on nie odpowiada albo zmodyfikować go.

  1. Zerowe umiejętności kodzenia: zrealizuj wymienione przeze mnie funkcjonalności w mainie, jak będziesz potrzebował tablicy - nie rób jej (jeszcze) dynamicznie, bo póki co nie komplikujemy. W każdym z wymienionych kroków staraj się jak najmniej używać “gotowców” - w jednym z etapów dojdziesz do tego, że string do obsługi stringów jest zbędny bo i generalnie celem takiego intensywnego ćwiczenia jest jak najdalej idące zdobywanie wiedzy :wink:
  2. +1 do umiejętności kodzenia: zmienne zamień na globalne i operuj na nich w mainie wywołując kolejne voidy
  3. +2 do umiejętności kodzenia: zmienne mają wrócić do maina i funkcje mają otrzymywać oraz zwracać odpowiednie zmienne odpowiednich typów. Sprawdź czym różni się przesyłanie przez referencję od zwykłego przekazania argumentu do funkcji (ale nie w Google tylko tworząc odpowiedni kod i coutując co trzeba)
  4. +2 do umiejętności kodzenia: wszystkie zmienne mają być dynamicznie alokowane - w programie nie może wystąpić nic, co nie jest zadeklarowane jako wskaźnik
  5. +1 do umiejętności kodzenia: spraw by program działał bez using namespace std;
  6. +1 do umiejętności kodzenia: zrób obsługę stringa na tablicy char
  7. +2 do umiejętności kodzenia: rozwiń program w taki sposób, aby obsługa wejścia i wyjścia była realizowana bez użycia iostream - printfy, scanfy itd.
  8. +1 do umiejętności kodzenia: w pewnym kroku musiałeś jakoś obsłużyć potęgowanie. W sposób bezmyślny, jedynie dla poznania nowego pojęcia, zastosuj tam szablon funkcji
  9. +2 do umiejętności kodzenia: pokoloruj program - niech wyświetla literki w różnych kolorach, może nawet wydaje jakiś dźwięk, … :wink:
  10. Podsumuj wszystko to czego się dowiedziałeś z poprzednich kroków. Prześpij się z uzyskaną wiedzą i wprowadź oczywiste poprawki do kodu. Nie siedź nad tym długo, bo to tylko ćwiczenie. Jak czegoś nie rozumiesz - while(nie rozumiesz) google it. Nie rozwijaj bardziej tego kodu, choć da się napisać np. własną klasę string - co za dużo to niezdrowo i problemy trzeba co jakiś czas zmieniać. Znajdź sobie inny problem i tam się realizuj. Problem niekoniecznie związany z programowaniem - możesz np pobiegać, pouczyć się matmy albo odłączyć mysz od komputera i pokazać, że da się pracować bez myszy. Oczywiście nim to zrobisz wyszukaj w Google listę skrótów klawiszowych i poćwicz kilka chwil na sucho :wink:

PS
Do każdego kroku może przydać się kartka, długopis/ołówek i dużo myślenia nad tym jak poruszać się po stringu.

Dzięki wielkie za wszystkie uwagi i za poświęcony czas. Ale powoli… :wink: Z gotowych rozwiązań nie korzystałem, tamte programy to wytwór moich rozważań :stuck_out_tongue:

Dobra…


#include
#include

using namespace std;
string podzial_stringa(string linia)
{
/deklaracje/
string wyraz;
linia+=" “;
string *tablica_wyrazow;
tablica_wyrazow=new string [linia.size()/2];
int dlugosc_lini=linia.size();
/deklaracje/
for (int i=0;i<dlugosc_lini;i++)
{
if (linia[i]==’ ')
{
cout<<wyraz<<endl;
*tablica_wyrazow=wyraz;
wyraz=”";
tablica_wyrazow++;
}
else
{
wyraz+=linia[i];
}
}
delete [] tablica_wyrazow;
return “kot”;
}
int main()
{
/deklaracje/
string linia;
/deklaracje/
getline(cin,linia);
podzial_stringa(linia);

return 0;

}


Ten program. Jest rozbity na funkcje. I tu kilka pytań :

  1. Po pierwsze, czemu się wysypuje ? powinien wypisywać wszystkie liczby jako łańcuchy oddzielnie (robi to ) i zapisywać do tablicy kolejne wyrazy (dopóki nie stworzyłem tablicy to program śmigał i wypisywał wyrazy bez wysypywania się).
  2. w returnie podałem “kot” bo nie wiem jak podać do funkcji głównej tablicę, jeżeli znajdziesz jeszcze chęci i dobrą wolę to proszę o wytłumaczenie jak to zrobić.
  3. Deklarując tablicę “new string [linia.size()/2]” zrobiłem to w te sposób, ponieważ nie chcę zajmować niepotrzebnie większej ilości komórek pamięci, a ten model linia.size()/2 będzie prawdziwy dla łańcuchów o długości 1, czyli gdybym wypisywał liczby np. 2 4 5 6 7. Zatem będzie prawdziwy dla każdej długości łańcuchów.

Wklej kod prawidłowo albo przekaż go jako link na ideone to ewentualnie rzucę na to okiem. Przy obecnej wersji nie nadaje się to do komentowania. Poza tym przedstaw kod z prawidłowym formatowaniem (wcięcia).

To zadanie na googlowanie :wink: Nie wiem czy dodałem, ale oczywiście nie googlujemy polskojęzycznych stron internetowych :wink: No i oczywiście możesz użyć czegoś innego niż Google, np https://duckduckgo.com/1 :wink:

Abyś walczył z tym problemem nieco później zaleciłem Ci najpierw zapisywanie wyników do publicznych tablic o dowolnie dużym rozmiarze. Jeżeli jednak już teraz chcesz robić to ambitnie to ok.

Nie jestem pewien o co Ci chodzi, ale ok - jakoś to tam sobie robisz i ufam, że wiesz co jak gdzie kiedy i po co.

Opiszę wszytko co widzę już teraz, w tym nawet przyczynę problemów:

  1. Najpierw wołasz funkcję linia.size() do alokacji a potem i tak tworzysz inta zawierajacego linia.size(). Bez sensu - po co wołać size() 2x jak można 1x?
  2. Plusik za formatowanie i zaznaczenie deklaracji. Na ogół deklaracji tak się nie oznacza, ale w tym przypadku poprawia to czytelność.
  3. Plusik za to, że to w ogóle zaczyna działać (testy: Lama alpaka guanako wikunia oraz 123 213 12 123 12 43 1 3123 1 123 2 1)
  4. Jeżeli coś nie działa to w tym przypadku wystarczy zakomentować (staroświecko: zaremować) tablica_wyrazów w forze i już wiadomo, że to z nią jest problem. Ponieważ problem jest związany z używaniem pamięci w sposób dynamiczny celowo nie powiem Ci jak go poprawić - więcej nauczysz się gdy sam będziesz szukał. Podpowiem Ci jednak, że szukanie oświecenia możesz zacząć od tego: http://www.cplusplus.com/doc/tutorial/1 (pointery i tablice to wbrew pozorom jedna z bardziej złożonych części C++ więc daj sobie czas na pełne pojęcie treści nawet tego elementarnego tutorialu, a także rób rysunki do wszelkiej maści int***, abyś widział, jak to co definiujesz/deklarujesz przekłada się na to co dzieje się w pamięci).