• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

C++ czytanie danych z pliku

0 głosów
907 wizyt
pytanie zadane 11 kwietnia 2019 w C i C++ przez Lisu Początkujący (270 p.)

Witam,
Wiem jak czytać i zapisywać dane do plików, lecz problem pojawia się przy większej złożoności zadania.

W pliku mam dane w postaci:

Kolo [(0,0)-(4,4)]

Kolo [(0,0)-(3,3)]

Trojkat [(0,0)-(8,8)] [(8,8)-(3,3)] [(3,3)-(0,0)] 

Kolo [(0,0)-(2,2)]

Kolo [(0,0)-(1,1)]

Kolo [(0,0)-(0,0)]

Czy jest jakiś prosty sposób w C++, żeby dostać się do liczb np. w linijce z Trójkątem chciałbym otrzymać Napis oraz 3 tablice dwuelementowe wskazujące na punkt.

Czy istnieje może jakiś obiekt, który by działaj jak stringstream, ale żeby czytać z niego danie np dla koła:
 

int x, y, w, q;

obj >> Nazwa_Figury >> " " >> "[(" >> x >> "," >> y >> ")-(" >> w >> "," << q ")]";

 

2 odpowiedzi

+2 głosów
odpowiedź 11 kwietnia 2019 przez Bondrusiek Maniak (61,440 p.)

Wydaje mi się że najlepszym sposobem byłoby czytanie pojedynczych lini z pliku a następnie parsowanie danych

#include <sstream>
#include <string>

std::string line;
while (std::getline(infile, line))
{
//obróbka zmiennej line
}

 

komentarz 11 kwietnia 2019 przez Teslum_369 Gaduła (4,190 p.)
Też tak uważam
+1 głos
odpowiedź 11 kwietnia 2019 przez mokrowski Mędrzec (159,000 p.)

Cel prosty. Masz zrozumieć więc jest to "boleśnie linearne".

Uprzedzam, po zmianie formatu danych, kod jest "bardzo kruchy".

#include <iostream>
#include <sstream>
#include <string>

struct Point {
    int x;
    int y;
};

struct Segment {
    Point startPoint;
    Point endPoint;
};

Point pointParse(const std::string& str) {
    std::string msg{str.cbegin() + 1, str.cend() - 1};
    std::stringstream ss;
    ss.str(msg);
    char comma;
    int x;
    int y;
    ss >> x >> comma >> y;
    return Point{x, y};
}

Segment segmentParse(const std::string& str) {
    std::string msg{str.cbegin() + 1, str.cend() - 1};
    std::stringstream ss;
    ss.str(msg);
    std::string msg1;
    std::string msg2;
    std::getline(ss, msg1, '-');
    std::getline(ss, msg2);
    return Segment{pointParse(msg1), pointParse(msg2)};
}

void showSegment(const Segment& seg) {
    std::cout << "Segment:\n"
      << "Start point:\tx = " << seg.startPoint.x << '\t'
      << "y = " << seg.startPoint.y << '\n'
      << "End point:\tx = " << seg.endPoint.x << '\t'
      << "y = " << seg.endPoint.y << '\n';
}

int main() {
    std::string record = "Trojkat [(0,0)-(8,8)] [(8,8)-(3,3)] [(3,3)-(0,0)]";
    std::string objName;
    std::string segment1;
    std::string segment2;
    std::string segment3;
    std::stringstream ss;
    ss.str(record);
    ss >> objName >> segment1 >> segment2 >> segment3;
    Segment sg1 = segmentParse(segment1);
    showSegment(sg1);
}

Innym rozwiązaniem była by gramatyka regularna... ale to bardziej skomplikowane.

komentarz 11 kwietnia 2019 przez j23 Mędrzec (195,220 p.)
edycja 11 kwietnia 2019 przez j23

Dodajmy zatem regexy:

struct Point {
    int x;
    int y;
};

struct Segment {
    Point startPoint;
    Point endPoint;
};

struct Object {
	std::string name;
	std::vector<Segment> segments;
};

template<typename Iter>
int toInt(Iter beg, Iter end)
{
	char tab[50];
	*std::copy(beg, end, tab) = 0;
	return atoi(tab);
}

Object parseObject(const std::string &line)
{
	static std::regex r(R"-(\[\(([+-]?\d+),([+-]?\d+)\)-\(([+-]?\d+),([+-]?\d+)\)\])-");
	std::smatch m;
	
	Object obj;
	
	auto it = line.cbegin();
	while(it != line.cend() && !isspace(*it)) ++it;
	obj.name.assign(line.cbegin(), it);
	
    while(regex_search(it, line.cend(), m, r))
    {
		obj.segments.push_back(Segment{{ toInt(m[1].first, m[1].second), toInt(m[2].first, m[2].second) }, 
									   { toInt(m[3].first, m[3].second), toInt(m[4].first, m[4].second) }});
		
		it = m.suffix().first;
    }

	return obj;
}
    std::string s = "Trojkat [(0,0)-(8,8)] [(8,8)-(3,3)] [(3,3)-(0,0)]";
    
	auto o = parseObject(s);

	std::cout << o.name << '\n';
	for(auto &s : o.segments)
	{
		std::cout << s.startPoint.x << ' ' << s.startPoint.y << ' ';
		std::cout << s.endPoint.x << ' ' << s.endPoint.y << '\n';
	}

 

Podobne pytania

0 głosów
2 odpowiedzi 5,728 wizyt
pytanie zadane 9 maja 2016 w C i C++ przez Leonnn Nowicjusz (150 p.)
0 głosów
1 odpowiedź 1,559 wizyt
pytanie zadane 13 kwietnia 2019 w Python przez yteicosf Użytkownik (640 p.)
0 głosów
2 odpowiedzi 314 wizyt

93,776 zapytań

142,732 odpowiedzi

323,384 komentarzy

63,379 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Twierdza Linux. Bezpieczeństwo dla dociekliwych

Aby uzyskać rabat -10%, użyjcie kodu pasja-linux, wpisując go w specjalne pole w koszyku.

...