Přeskočení na druhý řádek v texťáku – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Přeskočení na druhý řádek v texťáku – C / C++ – Fórum – Programujte.comPřeskočení na druhý řádek v texťáku – C / C++ – Fórum – Programujte.com

 

ORION2060
Newbie
2. 5. 2017   #1
-
0
-

Zdravím,

potřeboval bych poradit, jak přeskočit na při čtení souborů na druhý řádek.

Pro čtení a zápis používám takovýto kod: 

// PODMINKA PRO ODRAZIVOST
	if (volba == 'O' || volba == 'o')
	{

		std::ifstream ifs("Mracno.pts", std::ifstream::in);
		std::ofstream ofs("POMOCNY_Cisla_Dle_Odrazivosti.pts", std::ofstream::out);

		cout << "Zadejte odrazivost pro vytvoreni souboru.\n";
		cout << "Zadejte meze odrazivosti: (nejpreve zapornou a pak kladnou)\n";
		cin >> odrazivost[0];
		cin >> odrazivost[1];

		int start = clock();
		int start_pulka = clock();

		int a = 0;

		if (ifs.is_open() && ofs.is_open())
		{
			std::string line;
			while (std::getline(ifs, line))
			{
				std::istringstream ss(line);
				std::string token;

				float pole[COLUMNS];
				int i = 0;
				while (std::getline(ss, token, ' '))
				{

					pole[i] = stof(token);

					i++;
				}
				radek soucasnejRadek;
				soucasnejRadek = MakeRow(pole);

				if (odrazivost[0] <= soucasnejRadek.odrazivost && odrazivost[1] >= soucasnejRadek.odrazivost)
				{
					a++;
					pocetRadku = a;
					ofs << soucasnejRadek.x << " " << soucasnejRadek.y << " " << soucasnejRadek.z << " " << soucasnejRadek.odrazivost << " " << soucasnejRadek.r << " " << soucasnejRadek.g << " " << soucasnejRadek.b << '\n';
				}

			}
			ifs.close();
			ofs.close();

		}
		else
		{
			std::cout << "Error opening file";
		}

Který vlastně přepisuje do nového souboru ve struktuře:

10 20 50 1520 20 20 20

Ale pokud mám na první řádku třeba jen jedno číslo, tak mi program spadne a nepracuje správně. Zkoušel jsem  přeskočit kurzorem na druhý řádek, ale nedaří se mi to. Neporadil by mi někdo prosím jak na to? Díky moc.

Nahlásit jako SPAM
IP: 91.139.6.–
Jerry
~ Anonymní uživatel
512 příspěvků
2. 5. 2017   #2
-
0
-

No každej řádek tvého textového souboru by měl končit znaky CR+LF nebo 0x0A + 0x0D

pro platformu DOS/Windows.

tady je stejná otázka jako dáváš ty a k ni je odpověď:

http://www.cplusplus.com/forum/beginner/11304/

a tady je popis jak pracovat s CRLF

http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf

a další:

http://stackoverflow.com/questions/13035674/how-to-read-line-by-line-or-a-whole-text-file-at-once

http://stackoverflow.com/questions/19123334/how-to-use-stdgetline-to-read-a-text-file-into-an-array-of-strings-in-c

uplně nechápu zdroják co si to tam napsal, ale pokud máš zadanej TXT soubor a v něm

čísla a jsou oddělená mezerou a jejich počet je variabilní (a tecy i nulový) a každý řádek je zakončen CRLF pak načteš řádek a pokud není prázdný rozparsuješ ho podle mezer. pokud je prázdný jdeš na další,

to že v řádku je méně čísel než např. 10 poznáš až při parsování.

pokud by si netrval na zadání TXT vstupního souboru tak by bylo lepší mít vstupní soubor v binárním tvaru. výrazně by to zrychlilo čtení a zpracování. a proč tu ulohu vlastně neděláš v C# .NET ???

Nahlásit jako SPAM
IP: 2a00:1028:83be:235a:7cb2:...–
ORION2060
Newbie
2. 5. 2017   #3
-
0
-

Díky za odpověď.

Mám za úkol to dělat v C++. Tak to prostě mastím v tom. :-) Zdrojový soubor má vždy sxtejnou strukturu tedy souřadnice x y z odrazivost r g b. Třeba takto:

-2.527664 -6.172501 -1.749588 -1557 55 45 44
-18.999893 -22.491531 -0.102524 -1648 47 36 34
-24.240677 -24.054489 -0.108078 -1570 42 35 34
-24.530594 -25.052109 -1.108261 -1120 77 58 53
-24.709518 -25.535507 -1.423325 -1355 110 87 84
-24.704971 -25.546707 -1.423325 -1319 110 89 85
-24.711197 -25.506393 -1.422440 -1341 112 92 88
-24.700485 -25.511002 -1.422104 -1379 111 91 87
-24.602066 -25.552841 -1.431717 -1446 92 70 66

Ale občas na začátku toho souboru je číslo které říká kolik řádků (bodů) je v daném souboru (buď .pts nebo .txt). A já to potřebuji rozkouskovat dle nějakých mezí a právě bez těch počtu bodů. 

Nahlásit jako SPAM
IP: 91.139.6.–
Jerry
~ Anonymní uživatel
512 příspěvků
2. 5. 2017   #4
-
0
-

#3 ORION206
aha no ale to je zase uplně jiné zadání než to co si popsal v úvodu

protože pokud je na prvním řádku souboru číslo jen "občas" - což je podle mě blbost

v zadání - mělo by tam být vždy, tak s ohledem na složitost kodu a výslednou přehlednost bych to udělal tak,

že bych otevřel soubor a načetl první řádek (který také musí mít na konci CR+LF) a rozparsoval ho. protože načítáš string mužeš převést string na číslo a pokud vše dopadne dobře znamená to že na prvním řádku je počet všech řádků v souboru - resp. jediné celočíselné číslo. Pokud převod skončí chybou tak tam je souřadnice. Převodní funkce je tady.

http://www.zezula.net/cz/prog/string_na_int.html

to by byla první část programu a výsledkem je hodnota např. bool countValueExists

která muže být true nebo false podle toho jestli počet řádků existuje nebo ne. Na konci této první části soubor uzavřeš příkazem close.

pak bude druhá část, a vstupní hodnotou do této části bude countValueExists. otevřeš soubor a na dalším řádku napíšeš

if ( countValueExists == true ) {  // na prvnim radku je uveden pocet radku v souboru

   std::getline(ifs, line);  // nactes de-fakto nepotrebny prvni radek
}// if

while ( eof - podminka konce souboru ... ) { // nebo přímo řádek načteš

      nejake_pole[xx] = std::getline(ifs, line);

}// while

... close file

nejake_pole[xx]  značí strukturu kam načtený řádek ukládáš muže to být např pole nebo list z knihovny 

http://www.cplusplus.com/reference/list/

já bych si vybral List a vkládal bych ukazatel na sting který obsahuje celý řádek tedy:

x y z odrazivost r g b

takže ten řádek

nejake_pole[xx] = std::getline(ifs, line);

pak musíš nahradit příkazy

String* item = new String; a podobně protože List očekává ukazatel

tady to je napsaný s příkladem

http://stackoverflow.com/questions/3726586/easily-initialise-an-stdlist-of-stdstrings

mužeš ale použít aj vector je to fuk

no takže nyní máš načtené řádky v paměti a víš kolik jich je a teď je rozparsuješ

takže potřebuješ 2 cykly for:

for ( i = od řádku 0 do max-1) { // cyklus projde vsechny nalezene radky

    line = List[i];

    tady vložíš kod pro nalezení pozice první mezery a extrahuješ text až po první mezeru

    atd... až k poslednímu místu

    tady je příklad

    http://www.cplusplus.com/…string/find/

   až najdeš první mezeru dáš

    line = line od pozice první mezery + 1 do konce

   a to samý pro číslo na druhý pozici, prostě pokaždé si odřízneš kousek z i-tého řádku odzačátku

   a ta odříznutá část je řetězec a ten převedeš funkcí  atoi a pak si ho někam schováš

    http://stackoverflow.com/…ing-to-int-c

    Moje_Struktura item = new Moje_Struktura();

    item->x = první extrahované číslo

    .....atd

    item->b = posledni extrahovane cislo

    List muj_List.PushBack(item)

}// for

ideální pro schování  x y z odrazivost r g b  je struktura, pro kterou alokuješ paměť příkazem NEW

v každém cyklu for ( i = od řádku 0 do max-1)  což je logické

pro uložení množiny struktur zvolíš List - ale mužeš i array nebo vector, ale list je asi nejlepší...

struct Moje_Struktura {

  double x;

  double y;

   ....

   double b;

}

no a to je všecho .. je to zajímavý zadání ...

Nahlásit jako SPAM
IP: 2a00:1028:83be:235a:7cb2:...–
Jerry
~ Anonymní uživatel
512 příspěvků
2. 5. 2017   #5
-
0
-

#4 Jerry
errata:

řádek

"takže potřebuješ 2 cykly for:"

má být správně

"takže potřebuješ cyklus for:"

Nahlásit jako SPAM
IP: 2a00:1028:83be:235a:7cb2:...–
ORION2060
Newbie
2. 5. 2017   #6
-
0
-

Děkuji za obsáhlou odpověď. ještě bych měl dotaz. To co jsi napsal víceméně chápu, ale pokud počet řádků nepotřebuji, nebylo by jednoduší zjistit tedy jestli tam je, pomocí tebou zmíněné hodnoty countValueExists. Pokud to bude pravda, smazat tento řádek, soubor znovu uložit a pak použít ten můj kod úplně na začátku. Jde mi to, abych nemusel znovu psát ten kod, jak jsi to dál popsal, jelikož nejsem zatím moc zběhlý v programování, zabere mi to dost času. :-) a smazání toho řádku by to podstatně ulehčilo. 

Nahlásit jako SPAM
IP: 91.139.6.–
Jerry
~ Anonymní uživatel
512 příspěvků
2. 5. 2017   #7
-
0
-

#6 ORION206
hodnota countValueExists  je proměnná, kterou jsem vytvořil a pojmenoval sám podle mojí okamžité nálady v daný moment - mám se fajn měl sem rybí filé k obědu, kdybych měl prejt menovalo by se to cVExst. :)

ano možné to je ale smazání řádku z textového souboru tak, že řádek smažeš celý (fyzisky odstraníš všechny znaky daného řádku) není možné - soubor je zapsaný na disku sekvenčně.  Bohužel  jde udělat jen to, že soubor otevřeš a překopíruješ

všechny řádky do jiného souboru kromě prvního, ale to je ten samý algoritmus jako sem už psal výše. takže jak vidíš nijak si to nezjednodušíš a navíc zbytečně budeš vytvářet další soubor. Obávám se že to asi budeš muset napsat protože pan učitel to po tobě buch chtít .. což je problém ...

takže bych zachoval postup popsaný výše, který vede k bezchybnému a přehlednému cíli hned napoprvé a obzvláště pro začátečníka tedy:

1/ otevřeš soubor načteš první řádek a vyplníš proměnnou countValueExists a zavřeš soubor.

2/ Otevřeš soubor a podle hodnoty countValueExists načteš první řádek a buď ho vynecháš prázdným příkazem std::getline(ifs, line);  nebo pokračuješ na cyklus while ve kterém do Listu načteš jednotlivé řádky

3/ Jedním cyklem for - uvnitř cyklu rozparsuješ každý řádek textu do struktury kterou ukládáš do druhého Listu.

je to efektivní, rychlé, a snadno čitelné. to cos napsal ty na začátku nebude nikdy fungovat...

začal bych tím kouskem kodu pro vyplnění proměnné bool countValueExists to je cca na 8 řádku.

a pak bych dal vědět jak to dopadlo :)

Nahlásit jako SPAM
IP: 2a00:1028:83be:235a:7cb2:...–
ORION2060
Newbie
2. 5. 2017   #8
-
0
-

Ten kod co jsem postoval jako první, mi ten první řádek přečte. Ale našel jsem problém, že ve zdrojovém souboru .pts je za prvním číslem asi 20 mezer a to je ten problém, proč mi program padá.

124563256[20 mezer]      
-2.527664 -6.172501 -1.749588 -1557 55 45 44
-18.999893 -22.491531 -0.102524 -1648 47 36 34
-24.240677 -24.054489 -0.108078 -1570 42 35 34
-24.530594 -25.052109 -1.108261 -1120 77 58 53
-24.709518 -25.535507 -1.423325 -1355 110 87 84
-24.704971 -25.546707 -1.423325 -1319 110 89 85
-24.711197 -25.506393 -1.422440 -1341 112 92 88
-24.700485 -25.511002 -1.422104 -1379 111 91 87
-24.602066 -25.552841 -1.431717 -1446 92 70 66

a jelikož .pts soubor má 1GB, 14 mil. řádků, tak nejsem schopen ho nikde otevřít a mezery smazat. :-/

Nahlásit jako SPAM
IP: 91.139.6.–
Jerry
~ Anonymní uživatel
512 příspěvků
2. 5. 2017   #9
-
0
-

#8 ORION206
já pořád nevim nad čim špekuluješ, ano je tam 20 mezez ale to nevadí ne ?

ten řádek je zakončen znaky CR+LF (nebo alespoň 0x0D) a tí je dán konec řádku.

kopírování souboru do jiného je blbost, ano jde to ale je to blbost.

takže ten řádek normálně načti celý ne ? to je přeci součástí bodu 1/ co sem psal

tak proč ten kod neupravíš ???

Nahlásit jako SPAM
IP: 2a00:1028:83be:235a:8529:...–
2. 5. 2017   #10
-
0
-

Spadne, asi vyhodí vyjímku. Jakou? 

Pokud řádek načteš jako std::string a konvertuješ pomocí stoi, měl by zkonvertovat na číslo co jde a zbytek, tj. mezery, ignorovat.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
2. 5. 2017   #11
-
0
-

Kromě toho ti stoi může ukázat na znak který následuje za zkonvertovaným číslem, takže pak můžeš zkoumat, zda je to hromada mezer nebo jedna mezera a následuje další číslo...

http://www.cplusplus.com/reference/string/stoi/ 

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Jerry
~ Anonymní uživatel
512 příspěvků
2. 5. 2017   #12
-
0
-

#8 ORION206
už to máš ? ten bod 1/ by měl bejt takhle ne ?

// Win32Project1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <iostream>
#include <fstream>

using namespace std;

int main()
{

   char setOfChars[255];
   int countValueExists;

   std::ifstream ifs;
   
   ifs.open("c:\\Mracno.pts", std::ifstream::in);
  
   ifs.getline(setOfChars,255);

   string line(setOfChars);

   if ( line.find_first_not_of("0123456789") == string::npos ) {
      countValueExists = atoi(setOfChars);
   } else
   {
      countValueExists = -1;
   }// if else

   ifs.close();


   std::cout << setOfChars;
   std::cout << "\n";
   std::cout << countValueExists;
   std::cout << "\n";
   std::cout << atoi(setOfChars);
   std::cout << "\n";


   return 0;
}
Nahlásit jako SPAM
IP: 2a00:1028:83be:235a:8529:...–
ORION2060
Newbie
2. 5. 2017   #13
-
0
-

Teď jsem dojel domů. Díky moc za kód. Já prostě nevěděl jak to napsat, aby to načetlo pouze jeden řádek z celého velkého souboru.

Nahlásit jako SPAM
IP: 89.176.56.–
Jerry
~ Anonymní uživatel
512 příspěvků
2. 5. 2017   #14
-
0
-

#12 Jerry, ERRATA
pardon, chybička se vloudila :)

// Win32Project1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <iostream>
#include <fstream>

using namespace std;

int main()
{

   char setOfChars[255];
   bool countValueExists;
   int count;

   std::ifstream ifs;
   
   ifs.open("c:\\Mracno.pts", std::ifstream::in);
  
   ifs.getline(setOfChars,255);

   string line(setOfChars);

   line.erase(0, line.find_first_not_of(' '));      
   line.erase(line.find_last_not_of(' ') + 1);

   if ( line.find_first_not_of("0123456789") == string::npos ) {
      countValueExists = true;
      count = atoi(setOfChars);
   } else
   {
      countValueExists = false;
      count = -1;
   }// if else

   ifs.close();

   std::cout << "nacteny retezec znaku: " << setOfChars;
   std::cout << "\n";
   std::cout << "je pocet radku platne cislo: " << countValueExists;
   std::cout << "\n";
   std::cout << "pocet radku: " << count;
   std::cout << "\n";
   std::cout << "funkce atoi: " << atoi(setOfChars);
   std::cout << "\n";

   return 0;
}
Nahlásit jako SPAM
IP: 2a00:1028:83be:235a:8529:...–
gna
~ Anonymní uživatel
1891 příspěvků
2. 5. 2017   #15
-
0
-

Pokud je na prvním řádku jen jedna hodnota, tak je to počet řádků a chce ho přeskočit.

Je těžké to zapsat do ifu?

Nahlásit jako SPAM
IP: 213.211.51.–
ORION2060
Newbie
2. 5. 2017   #16
-
0
-

Pokud máš ještě chvilku, rád bych se zeptal jak pokračovat. Pokud tedy mám countValueExists jako pravdu, jak jsi psal výšel, vytvořím podmínku if(countValueExists== true) a načtu zase ten první řádek do getline(ifs, line), zkusil jsem i toto vypsat do souboru a vypsalo mi to jen počet těch řádků, ale teď nevím, jak pokračovat, aby se mi načítání a vypisování čísel do nového souboru pokračovalo od druhého řádku, respektive od konce hodnoty countValueExists.

Nahlásit jako SPAM
IP: 89.176.56.–
gna
~ Anonymní uživatel
1891 příspěvků
2. 5. 2017   #17
-
0
-

Nebo ještě jednodušeji prostě ignorovat všechno, co není datový řádek. Bez píčovin.

while (std::getline(ifs, line))
{
	std::istringstream ss(line);
	radek soucasnejRadek;

	if (!(ss
	         >> soucasnejRadek.x >> soucasnejRadek.y >> soucasnejRadek.z
	         >> soucasnejRadek.odrazivost
	         >> soucasnejRadek.r >> soucasnejRadek.g >> soucasnejRadek.b))
	{
		continue;
	}

	if (odrazivost[0] <= ...
Nahlásit jako SPAM
IP: 213.211.51.–
ORION2060
Newbie
2. 5. 2017   #18
-
0
-

#17 gna
Děkuji moc, to je přesně to, co jsem potřeboval. A pokud to tedy chápu dobře, tak pokud se daný řádek nerovná tomu stringu ss, tak se prostě ignoruje a pokud je to pravda, daný řádek se načte.

Nahlásit jako SPAM
IP: 89.176.56.–
gna
~ Anonymní uživatel
1891 příspěvků
2. 5. 2017   #19
-
0
-

#18 ORION206
operator>> načítá data ze streamu. operator! testuje stav streamu. příkaz continue přejde na další iteraci cyklu.

Takže když se z toho stringstreamu (řádku) nepodaří načíst těch 7 hodnot (kvůli množství nebo formátu dat), tak se zbytek těla cyklu přeskočí (čte se další řádek).

Nahlásit jako SPAM
IP: 213.211.51.–
gna
~ Anonymní uživatel
1891 příspěvků
2. 5. 2017   #20
-
0
-

#18 ORION206
Samozřejmě bys to mohl udělat i s tím tvým původním načítáním, že bys testoval hodnotu a/nebo počet těch tokenů a podle toho pokračoval.

Nahlásit jako SPAM
IP: 213.211.51.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 78 hostů

Podobná vlákna

Kazdy druhy radek ma jinou barvu — založil Anonymní uživatel

Mazanie textaku — založil Dodo

Rychlejší přepis texťáku — založil Franceq

Export z sql do textaku — založil Plech

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý