Wątek przeniesiony 2021-03-30 18:50 z Algorytmy i struktury danych przez kq.

tablica haszująca input

0

Cześć, mam coś takiego. Nie rozumiem jak mają być pobierane dane z pliku wejściowego.
screenshot-20210330001907.png

Czy po prostu wczytujemy pierwszą linię czyli ilość przypadków testowych czyli 1? Następnie wczytujemy drugi wiersz czyli wielkość tablicy. Następnie wczytujemy kolejne wiersze i w zależności od tego czy w kolejnym wierszu pliku jest add czy print czy delete wykonuje się konkretna metoda w programie? W jaki sposób zaimplementować, aby np. przy sprawdzaniu 3 linii program wiedział, że ma wykonać dodawanie stringa ala na indeksie 3 (13%10) w mojej tablicy? Czy to jest coś trywialnego, bo googlam chyba nie tam gdzie trzeba. Równie dobrze może być:
1
size 10
add 13 ala
add 23 ola
...
stop
czyli inna kolejność. Może porobić if`y i niech sprawdza czy w konkretnej lini jest słowo kluczowe np. add, jeżeli tak to wykonaj dodanie stringa itd.?

Możliwe, że zupełnie źle to rozumiem także proszę o wyrozumiałość.

4

Ale skąd my mamy znać polecenie które masz wykonać? o_O Możemy najwyzej zgadywać na podstawie tego pliku... Wygląda że masz zrobić prosty interpreter "kodu"

  • czytasz linię
  • parsujesz ją i sprawdzasz co oznacza taka "instrukcja"
  • wykonujesz zadana operacje
0

Trzeba utworzyć tablicę z mieszaniem umożliwiającą przechowanie danych obiektu składającego się z klucza oraz stringa, a następnie mają się wykonać operacje zawarte w pliku. Nie rozumiem po prostu tego w jaki sposób program ma odczytać którą operację ma wykonać (czy add czy print czy delete) oraz jak pobrać dane np. klucz 13 oraz wartość "ala" i wstawić ją do tablicy - czy możemy w konkretnej linii pobrać tylko wartość po pierwszej spacji i po drugiej? Chodzi bardziej o samo działanie tablicy z mieszaniem niż interpreter i stąd moje pytania czy mój tok rozumowania jest ok.

Tak jak napisałeś, chyba trzeba wczytać całą linię jako stringa i jeżeli linia zawiera dane słowo kluczowe to wykonuje się konkretna operacja, ale zanim się wykona to trzeba wstawić klucz-wartość do tablicy. Pytanie czy można w jakiś łatwy sposób z pobranej linii wyłuskać 13 i ala? Teoretycznie w stringu "add 13 ala" można pobrać tylko znak 5 i 6 czyli 13 i przekonwertować na inta i tak samo z pobrać 3 ostatnie znaki czyli ala.

0

Chyba poszedłem w złym kierunku, bo teraz jak będę chciał wyświetlić wszystkie elementy tablicy to będę miał dostęp tylko do ostatnio dodanego. Oczywiście w metodzie add powinno być jeszcze zabezpieczenie na wypadek takich samych indeksów. Czy może mi ktoś podpowiedzieć jak to ugryźć?

#include <iostream>
#include <fstream>
#include <map>

using namespace std;


void add(string t[], int w , long k, string ww);
void print(string t[], int w , long k, string ww);
//void delete();
//void stop();

int main()
{

    fstream pobierz;
    pobierz.open("test.txt");
    string linia_1;
    string linia_2;
    string linia_3;
    string linia_4;
    string linia_5;
    string linia_6;
    string linia_7;
    string linia_8;
    string linia_9;
    string linia_10;


    getline(pobierz, linia_1);
    int ilosc_przypadkow = stoi(linia_1);

    getline(pobierz, linia_2);
    string stablica = linia_2.substr(5,6);
    int wielkosc = stoi(stablica);
    //cout<<wielkosc;
    string*tablica= new string[wielkosc];

    getline(pobierz, linia_3);
    string wyrazenie = linia_3.substr(0,2);
    if (wyrazenie == "add")
        {
            string key_z = linia_3.substr(4,5);
            long key = stoi(key_z);
            string wartosc = linia_3.substr(7,9);
            add(tablica, wielkosc, key, wartosc);
            if (wyrazenie == "pri")
            {

                print(tablica, wielkosc, key, wartosc);
            }
          //if (wyrazenie == "del")
          //{

          //}
          //if (wyrazenie == "sto")
          //{

          //}

        }

}


     void add(string t[], int w, long k, string ww)
    {
     int indeks_1  = k%w;
     t[indeks_1] = ww;

    }

    void print(string t[], int w , long k, string ww)
    {
       for(int i = 0; i<10; i++)
        cout<<t[i];
    }
2

Pytanie czy można w jakiś łatwy sposób z pobranej linii wyłuskać 13 i ala?

w każdej linijce masz jakieś znaki oddzielone spacją.
Możesz więc (sposób ręczny) iterować po każdym znaku aż do spacji, wtedy pobierasz słowo np. "add" i zapamiętujesz je gdzieś, potem jedziesz dalej aż do kolejnej spacji i wyłuskujesz cyfry "13", potem iterujesz dalej i łapiesz "ola" (ale - przy delete 13 masz tylko dwa symbole).

Ale możesz użyć jakiejś gotowej funkcji, jeżeli taką masz w języku (wczoraj robiłem coś podobnego w JS i tam jest funkcja split do tego).

No i na podstawie tego, co masz w pierwszym symbolu (size, add, delete itp.) podejmujesz decyzję (np. if, switch), w jaki sposób się zachowasz dalej. Plus trzeba będzie skonwertować cyfry w stringu "13" na faktyczną liczbę 13.

    string linia_1;
    string linia_2;
    string linia_3;
    string linia_4;
    string linia_5;
    string linia_6;

Ale po co tak? W C++ masz pętle, więc możesz zrobić jedną zmienną linia i potem iterować po kolejnych liniach i obsługiwać każdą linię tak samo.

string stablica = linia_2.substr(5,6);

przecież to ci się rozwali za chwilę. Wystarczy, że zamiast 10, będziesz miał 100 :D

  string key_z = linia_3.substr(4,5);

Też zakładasz, że coś będzie miało dwa znaki zawsze (o ile w ogóle ta funkcja tak działa? https://www.cplusplus.com/reference/string/string/substr/ ). Czyli robisz program do obsługi jedynego pliku (który się wywali przy każdym innym pliku, chyba, że jakimś cudem będzie miał linijki w znaki w tych samych miejscach). To chyba wygodniej byłoby w ogóle nie robić tego programu, tylko napisać po prostu

cout << "ala";
cout << "ola";

na to samo by wyszło w tym momencie...

0

Przerobiłem wszystko. Utknąłem, bo w pętli nie jest przekazywany adres do tablicy Tabp oraz size. Pórbowałem z wskaźnikam, ale bez skutku ;/
Jeżeli chodzi o operacje na stringu to póki co łopatologicznie, potem zrobię myk z białym znakiem.

#include <iostream>
#include <fstream>
#include <map>

using namespace std;


void Add(string T[], int r, long k, string w);
//void print();
//void delete();
//void stop();



int main()
{
    string linie;
    int licznik = 0;
    ifstream policz("test.txt");
    while(getline(policz, linie))
        licznik++;
    policz.close();



    string * Tabp = new string[licznik];
    fstream plik;
    plik.open("test.txt");
    string wiersz;

    for (int b =0; b<licznik; b++)
    {
        getline(plik, wiersz);
        Tabp[b] = wiersz;
    }

    string iloscprzypadkow = Tabp[0].substr(0);
    int n = stoi(iloscprzypadkow);

    string rozmiarstring = Tabp[1].substr(5,7); 
    int size = stoi(rozmiarstring);
    string * Tabh = new string[size];


    for (int ite=2; ite<licznik; ite++)
        if (Tabp[ite].substr(0) == "a")
        {
            cout <<Tabp[2]; //TEST: nie wyswietla się czyli problem z zasięgiem. Kombinowałem z wskaźnikami, ale nie mogę rozkminić czemu nei działa
            cout <<size;  //TEST_2: nie wyswietla się czyli problem z zasięgiem Kombinowałem z wskaźnikami, ale nie mogę rozkminić czemu nei działa
            string temp = Tabp[ite].substr(4,5);
            long klucz = stoi(temp);

            string wartosc = Tabp[ite].substr(7,14);


            Add(Tabh, size, klucz, wartosc);

        }
        //if (wyrazenie == "p")
        //{

        //}
        //if (wyrazenie == "d")
        //{

        //}
        //if (wyrazenie == "s")
        //{

}
    void Add(string Tabh[], int rozmiar, long klucz, string wartosc)
    {

        cout<<rozmiar<<klucz<<wartosc;
    int indeks = klucz%rozmiar;
    Tabh[indeks] = wartosc;

    cout<<indeks<<" "<<klucz<<" "<<wartosc;

    }

Ma ktoś pomysł co robię nie tak? ;/

0

Hej, głupi błąd, zamiast if (Tabp[ite].substr(0) == "a") powinno być if (Tabp[ite].substr(0,1) == "a")```
Teraz mam problem jak wyświetlić klucz oraz indeks elementu tablicy w metodzie print. Podpowie ktoś?

#include <iostream>
#include <fstream>


using namespace std;

void Add(string T[], int r, long k, string w);
void Print(string Print[], int size);

//void delete();
//void stop();

int main()
{
   string linie;
   int licznik = 0;
   ifstream policz("test.txt");
   while(getline(policz, linie))
         licznik++;
   policz.close();

   string * Tabp = new string[licznik];
   fstream plik;
   plik.open("test.txt");
   string wiersz;

   for (int b =0; b<licznik; b++)
   {
         getline(plik, wiersz);
         Tabp[b] = wiersz;
   }

   string iloscprzypadkow = Tabp[0].substr(0);
   int n = stoi(iloscprzypadkow);

   string rozmiarstring = Tabp[1].substr(5,7);
   int size = stoi(rozmiarstring);
   string * Tabh = new string[size];

   for (int ite=2; ite<licznik; ite++)
   {
            if (Tabp[ite].substr(0,1) == "a")
            {
               string temp = Tabp[ite].substr(4,5);
               long klucz = stoi(temp);
               string wartosc = Tabp[ite].substr(7,14);
               Add(Tabh, size, klucz, wartosc);
            }
            if (Tabp[ite].substr(0,1) == "p")
            {

               Print(Tabh, size);

            }
    }
          //if (wyrazenie == "d")
          //}
          //{
          //if (wyrazenie == "s")
          //{
          //}

}

void Add(string Tabh[], int rozmiar, long klucz, string wartosc)
{

int indeks = klucz%rozmiar;
    if (Tabh[indeks] == "")
        {
        Tabh[indeks] = wartosc;

        }
    else
        {
        Tabh[indeks+1] = wartosc;

        }

}

void Print(string Tabh[], int size)
{
    for (int e=0; e<size; e++)
    cout<<indeks<<klucz<<Tabh[e];
}



0
  • Nie musisz magazynować danych w pamięci
  • Nie musisz używać dziwnych substr.
  • Radze zrobić to po ludzku
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;

struct Record {  int number; string text; };
struct TestData {  size_t capacity,size; Record *tb; }; // lepiej użyć wektora zamiast całej TestData

typedef void Executer(TestData &data,istream &is);

void executeSize(TestData &data,istream &is)
{
   int capacity;
   is>>capacity;
   data.tb=new Record[capacity]; // lepiej użyć wektora zamiast całej TestData, tu będzie reserve(capacity)
}

void executeAdd(TestData &data,istream &is)
{
   int number;
   string text;
   is>>number>>ws>>text;
   // zrobić dodawanie
}

void executePrint(TestData &data,istream &is)
{
   for(int i=0;i<data.capacity;++i) cout<<data.tb[i].number<<' '<<data.tb[i].text<<endl;
}

void executeDelete(TestData &data,istream &is)
{
   int number;
   is>>number;
   // zrobić usuwanie
}

void executeStop(TestData &data,istream &is)
{
   delete[] data.tb; // lepiej użyć wektora zamiast całej TestData, tu będzie zwyczajnie NIC!
}

struct { string key; Executer executer; } map[]=
{
   {"size",executeSize},
   {"add",executeAdd},
   {"print",executePrint},
   {"delete",executeDelete},
   {"stop",executeStop},
};

int main()
{
   ifstream file("test.txt");
   int tests;
   for(file>>tests;tests--;)
   {
     TestData data;
     string word;
     file>>ws>>word;
     for(int i=0;i<sizeof(map)/sizeof(*map);++i) if(word==map[i].key) map[i].executer(data,file);
   }
   return 0;
}

Uwaga pisane na kolanie, więc mogą być drobne błędy.

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