Pár otázok na C++

Pár otázok na C++
« kdy: 20. 11. 2020, 23:30:05 »
Ahojte mám pár otázok na STL. Ako donútiť ofstream aby namiesto \n nevkladal platformovo špecifické konce riadkov?

Keď do textového súboru (na platforme windows) ukladám \n, vloží sa automaticky \r\n teda namiesto 1 znaku vloží 2 ASCII znaky (0x0D 0x0A) niekto si povie, že riešim hovadiny, ale ja chcem mať kontrolu nad tým čo ukladám a u tak low level jazyka ako C++ človek očakáva že v základnej knižinici nebude podobná mágia (volitelne nech tam kludne je, ale rád by som mal možnosť to ovplyvniť, chcem aby keď aplikáciu preportujem na linux tak bude mať jednotné na vlas rovnaké chovanie s windows verziou). Viete mi poradiť ako by sa to dalo ovplyvniť? viem že v režime binary to bude ukladať korektne (znak \n ako \n) akurát neviem či mi pri binárnom móde bude fungovať aj ofstream.imbue(znaková sada).

Vopred ďakujem za tipy.

A keď už som založil toto fórum tak sa opýtam aj ďalšiu vec. V C# a Jave existuje trieda StringBuilder určená na spájanie veľkých reťazcov. Mala by ušetriť performance keďže v .NETe sú reťazce immutable a string builder je mutable.

Čo sa používa na spájanie reťazcov v C++? Bude std::string.append dostatočne efektívne aj keď budem spájať dajme tomu 100000 reťazco? Keďže v C++ sú reťazce mutable asi by to nemal byť problém nie? Na stackoverflow programátori odporúčajú na spájanie reťazcov std::stringstream čo je fajn objekt (aj ho občas použijem) ale niekde som čítal že má horší performance. Viem že najlepšie bude alokovať pamať a do pointeru pridať znaky priamo. Ale to je náchylné na chyby hlavne keď sa pracuje s wchar_t alebo inými charmi tak treba prerátavať velkosť a myslieť na znak \0 atď. Takže priamej práci s pamaťou sa chcem podľa možnosti vyhnúť (ak to neni nevyhnutné) a použiť ho len vo výnimočných prípadoch tam kde sa naozaj šetrí každá pikosekunda.

A keď už sme pri tom meraní efektivity čo používate na jej meranie?

1. Používate nejaký vlastný benchmark postavený na std::high_resolution_clock pustené v cykle?

2. alebo profiler?

3. Alebo nejaký špeciálny benchmark?  Ja som našiel toto: https://github.com/chronoxor/CppBenchmark a toto https://github.com/google/benchmark má to cenu kompilovať?


BoneFlute

  • *****
  • 2 155
Re:Pár otázok na C++
« Odpověď #1 kdy: 21. 11. 2020, 00:05:48 »
Citace od: fortran1986 kdy 20. 11. 2020, 23:30:05
Ahojte mám pár otázok na STL. Ako donútiť ofstream aby namiesto \n nevkladal platformovo špecifické konce riadkov?

Keď do textového súboru (na platforme windows) ukladám \n, vloží sa automaticky \r\n teda namiesto 1 znaku vloží 2 ASCII znaky (0x0D 0x0A) niekto si povie, že riešim hovadiny, ale ja chcem mať kontrolu nad tým čo ukladám a u tak low level jazyka ako C++ človek očakáva že v základnej knižinici nebude podobná mágia (volitelne nech tam kludne je, ale rád by som mal možnosť to ovplyvniť, chcem aby keď aplikáciu preportujem na linux tak bude mať jednotné na vlas rovnaké chovanie s windows verziou). Viete mi poradiť ako by sa to dalo ovplyvniť? viem že v režime binary to bude ukladať korektne (znak \n ako \n) akurát neviem či mi pri binárnom móde bude fungovať aj ofstream.imbue(znaková sada).

Teda mě přijde, že když vkládáš \n, tak bych očekával platformově závislé chování. A když chci platformově nezávislé, tak budu dávat \x0D, \x0D\x0A, \x0A. A ano, jsem si vědom toho, že to není úplně übr logické, ale skutečně to tak vnímám.

_Jenda

  • *****
  • 1 687
Re:Pár otázok na C++
« Odpověď #2 kdy: 21. 11. 2020, 01:11:36 »
Citace od: fortran1986 kdy 20. 11. 2020, 23:30:05
A keď už sme pri tom meraní efektivity čo používate na jej meranie?

1. Používate nejaký vlastný benchmark postavený na std::high_resolution_clock pustené v cykle?
Používám tohle

#define GIGA 1000000000L
#define MEGA 1000000L
struct timespec start, end;
void meas(char * desc) {
  clock_gettime(CLOCK_REALTIME, &end);
  uint64_t diff = (GIGA*(end.tv_sec - start.tv_sec) + end.tv_nsec - start.tv_nsec) / MEGA;
  printf("time: %s took %" PRIu64 " ms\n", desc, diff);
  memcpy(&start, &end, sizeof(struct timespec));
}

a obalím tím jednotlivé věci co program dělá (meas("foo")).

Pozor, nějak to nefungovalo na MIPSu a nezkoušel jsem jestli to projde ubsanem.
Citace od: fortran1986 kdy 20. 11. 2020, 23:30:05
2. alebo profiler?
perf record, perf report

Re:Pár otázok na C++
« Odpověď #3 kdy: 21. 11. 2020, 08:25:18 »
Pokud chceš prostě spojit 100000 řetězců do jednoho, největší potíž při naivním přístupu  budou podle mě realokace, které se budou vyskytovat vždy když po nějakém počtu přidaných řetězců přeteče kapacita kontejneru, do kterého to sázíš (u std::string určitě, jak je interně implementovaný stringstream si nejsem jistý). Pokud ty spojované řetězce znáš předem, předalokuj si string s kapacitou takovou, aby se tam všechny vešly. Jestli je předem neznáš, zkus použít nějakou specializovanou strukturu jako je třeba rope.

A samozřejmě  benchmarkovat, benchmarkovat, benchmarkovat. S tím ti ale v C++ poradit nedovedu.

Re:Pár otázok na C++
« Odpověď #4 kdy: 21. 11. 2020, 13:40:13 »
Citace od: fortran1986 kdy 20. 11. 2020, 23:30:05
Ahojte mám pár otázok na STL. Ako donútiť ofstream aby namiesto \n nevkladal platformovo špecifické konce riadkov?

Keď do textového súboru (na platforme windows) ukladám \n, vloží sa automaticky \r\n teda namiesto 1 znaku vloží 2 ASCII znaky (0x0D 0x0A) niekto si povie, že riešim hovadiny, ale ja chcem mať kontrolu nad tým čo ukladám a u tak low level jazyka ako C++ človek očakáva že v základnej knižinici nebude podobná mágia (volitelne nech tam kludne je, ale rád by som mal možnosť to ovplyvniť, chcem aby keď aplikáciu preportujem na linux tak bude mať jednotné na vlas rovnaké chovanie s windows verziou). Viete mi poradiť ako by sa to dalo ovplyvniť? viem že v režime binary to bude ukladať korektne (znak \n ako \n) akurát neviem či mi pri binárnom móde bude fungovať aj ofstream.imbue(znaková sada).................

prej to funguje i vobráceně :o :o jakože když soubory pak bude ifstream číst v textovým režimu tak zase ty platform specific zakončovadla bude nahrazovat jenom vobyč '\n' :o ;)

nóó takže jestli jako nějak nestěhuješ ty vyrobený soubory mezi různejma platformama tak by to jako nemuselo vadit moc že si tam ve win bude připisovat ty '\r' :) ;)
lidi postižený environmentálním žalem hele choděj za ekopsycholožkama hele 🤡 💆 🤡 💆


Re:Pár otázok na C++
« Odpověď #5 kdy: 21. 11. 2020, 14:56:04 »
Citace od: BoneFlute kdy 21. 11. 2020, 00:05:48
Teda mě přijde, že když vkládáš \n, tak bych očekával platformově závislé chování. A když chci platformově nezávislé, tak budu dávat \x0D, \x0D\x0A, \x0A. A ano, jsem si vědom toho, že to není úplně übr logické, ale skutečně to tak vnímám.

\r = \x0D
\n = \x0A

Či do texťáku vložíš \n alebo \x0A je úplne jedno (je to to isté) STL ti tam (na platforme windows) namiesto \x0A práskne \x0D\x0A (skúšal som to pre istotu). Ono v retazci máš uložené naozaj len \n (resp \x0A) ale wofstream ti pri ukladaní do súboru pridá pred \n aj \r.

Citace od: Jenda
...

Ďakujem vyskúšam. Porovnám s mojim riešením. :)

Citace od: registrovany_ava
...

jo tiež sa snažím predalokovať velkosť (ak sa to dá), ale nie vždy sa to dá.

Citace od: Wrána
prej to funguje i vobráceně :o :o jakože když soubory pak bude ifstream číst v textovým režimu tak zase ty platform specific zakončovadla bude nahrazovat jenom vobyč '\n' :o ;)

nóó takže jestli jako nějak nestěhuješ ty vyrobený soubory mezi různejma platformama tak by to jako nemuselo vadit moc že si tam ve win bude připisovat ty '\r' :) ;)

Ale môžu nastať aj situácie kedy chceš mať možnosť voľby medzi \n a \r\n napríklad ak by si programoval editor, alebo konvertor. Preto ma zaujíma či má tento problém nejaké jednoduché riešenie. Neni to pre mňa teraz otázka života a smrti :D, ale raz možno bude. Robím si totiž takú sadu helperov nad STL a tie chcem mať podľa možnosti čo najuniverzálnejšie.

Re:Pár otázok na C++
« Odpověď #6 kdy: 21. 11. 2020, 16:04:46 »
Co otevřít ten stream v binárním režimu místo textového?

nula

  • ***
  • 103
Re:Pár otázok na C++
« Odpověď #7 kdy: 21. 11. 2020, 16:40:51 »
1) V norme jazyka je definovane ze \n znamena new-line. Neni tam nic o tom, ze by to melo znamenat LF.
Pokud chces zapisovat vyslovene x0A, tak to samozrejme muzes delat rucne. Jazyk s tim problem nema.
Mnohem casteji nez zapisovat nejake arbitrary znaky chces proste ukoncit radek. Takze je to za mne i logicke reseni.

2) Jednoduche a obvykle dostatecne rychle je proste normalni appendovani ke stringu. Realokace se deji vzdy na dvojnasobek, nebo velikost noveho stringu, podle toho co je vetsi. Tedy vetsinou nerealokujes tolikrat, kolikrat pridavas. Stat se to ofc muze pri supernevhodne rade, kterou spojujes. Kdyz znas vyslednou velikost, tak se zvetseni kapacity samozrejme oplati udelat manualne.

Co je treba rict je, ze castokrat by slo udelat vsechny stringove konkatenace uz v compiletimu. Bohuzel z mne neznamych duvodu std::string neni kompletne constexpr (nejspis opomenuti), takze to na standardnim std::stringu nepoujde. Vyjimecne tedy, pri maximalni optimalizaci, se oplati pouzivat i jine nez implementace, nez ty ze STL.

BoneFlute

  • *****
  • 2 155
Re:Pár otázok na C++
« Odpověď #8 kdy: 21. 11. 2020, 17:43:22 »
Citace od: fortran1986 kdy 21. 11. 2020, 14:56:04
STL ti tam (na platforme windows) namiesto \x0A práskne \x0D\x0A (skúšal som to pre istotu).
Tak to už je podraz.

nula

  • ***
  • 103
Re:Pár otázok na C++
« Odpověď #9 kdy: 21. 11. 2020, 19:17:09 »
Citace od: BoneFlute kdy 21. 11. 2020, 17:43:22
Citace od: fortran1986 kdy 21. 11. 2020, 14:56:04
STL ti tam (na platforme windows) namiesto \x0A práskne \x0D\x0A (skúšal som to pre istotu).
Tak to už je podraz.

Dalsi takovy, hosi mne z vas klepne.
V NORME jazyka C je definovane UMYSLNE, ze znak \n v TEXTOVEM modu znamena NOVY RADEK. Proto se da psat multiplatformne jednoduse:
printf("Hello\nWorld");
A vysledek bude na vsech systemech:

Hello
World


A nebude tam neco ve smyslu

Hello
       World

nebo

Hello?World



Tohle bylo zavedeno umyslne, protoze hodne casto potrebujes proste vypsat neco po radcich a fakt te nezajima binarni reprezentace, ale to, jak to vizualne v danem systemu vypada.
Pokud chces binarne presnou reprezentaci, tak pouzivas BINARNI zapis (to je jedna z uplne prvnich veci kterou se snad clovek musi naucit o IO).

Konec radku je na ruznych systemech velmi ruzny:
CR, CRLF, LF, LFCR, dokonce mam pocit ze se na to pouzivaly i jine znaky z ASCII.

V dobe kdy C vznikal bylo toto zcela normalni a jazyk ktery neumi do konzole jednoduse vypsat 2 radky, je absurdne nemultiplatformni. Takze to ma velmi dobry duvod.

Re:Pár otázok na C++
« Odpověď #10 kdy: 21. 11. 2020, 22:39:29 »
Citace od: nula kdy 21. 11. 2020, 19:17:09
Citace od: BoneFlute kdy 21. 11. 2020, 17:43:22
Citace od: fortran1986 kdy 21. 11. 2020, 14:56:04
STL ti tam (na platforme windows) namiesto \x0A práskne \x0D\x0A (skúšal som to pre istotu).
Tak to už je podraz.
Dalsi takovy, hosi mne z vas klepne. ........................
nóó ale stejně je takový zajímavý žeto c++kový '\n' je schodný zrovinka se zakončením řádku v linuxu. bych se taky jako mohla zeptat proč jinde potřebujou mit něco extra a jestli to jako dneska ještě vůůůbec dává nějakej smysl :P :P ;D ;)
lidi postižený environmentálním žalem hele choděj za ekopsycholožkama hele 🤡 💆 🤡 💆

BoneFlute

  • *****
  • 2 155
Re:Pár otázok na C++
« Odpověď #11 kdy: 21. 11. 2020, 22:54:29 »
Citace od: nula kdy 21. 11. 2020, 19:17:09
Citace od: BoneFlute kdy 21. 11. 2020, 17:43:22
Citace od: fortran1986 kdy 21. 11. 2020, 14:56:04
STL ti tam (na platforme windows) namiesto \x0A práskne \x0D\x0A (skúšal som to pre istotu).
Tak to už je podraz.

Dalsi takovy, hosi mne z vas klepne.

Mě zase z tebe. Že neumíš číst. Argumentuješ tu přesně to samé co jsem psal já. Úžasné.

nula

  • ***
  • 103
Re:Pár otázok na C++
« Odpověď #12 kdy: 23. 11. 2020, 09:42:54 »
Citace od: BoneFlute kdy 21. 11. 2020, 22:54:29
Citace od: nula kdy 21. 11. 2020, 19:17:09
Citace od: BoneFlute kdy 21. 11. 2020, 17:43:22
Citace od: fortran1986 kdy 21. 11. 2020, 14:56:04
STL ti tam (na platforme windows) namiesto \x0A práskne \x0D\x0A (skúšal som to pre istotu).
Tak to už je podraz.

Dalsi takovy, hosi mne z vas klepne.

Mě zase z tebe. Že neumíš číst. Argumentuješ tu přesně to samé co jsem psal já. Úžasné.

Omlouvam se, sypu si popel na hlavu. Preskocil jsem prispevek od fortrana a to cos citoval nebylo jasne, ze se nevztahuje porad k \n. Tedy, dosel jsem k nazoru, ze to tak je.

Takze uznavam, jsem mamlas, ze jsem si to neprecet poradne. Nicmene porad plati to o tom binarnim rezimu.

BoneFlute

  • *****
  • 2 155
Re:Pár otázok na C++
« Odpověď #13 kdy: 23. 11. 2020, 18:58:25 »
Citace od: nula kdy 23. 11. 2020, 09:42:54
Citace od: BoneFlute kdy 21. 11. 2020, 22:54:29
Citace od: nula kdy 21. 11. 2020, 19:17:09
Citace od: BoneFlute kdy 21. 11. 2020, 17:43:22
Citace od: fortran1986 kdy 21. 11. 2020, 14:56:04
STL ti tam (na platforme windows) namiesto \x0A práskne \x0D\x0A (skúšal som to pre istotu).
Tak to už je podraz.

Dalsi takovy, hosi mne z vas klepne.

Mě zase z tebe. Že neumíš číst. Argumentuješ tu přesně to samé co jsem psal já. Úžasné.

Omlouvam se, sypu si popel na hlavu. Preskocil jsem prispevek od fortrana a to cos citoval nebylo jasne, ze se nevztahuje porad k \n. Tedy, dosel jsem k nazoru, ze to tak je.

Takze uznavam, jsem mamlas, ze jsem si to neprecet poradne. Nicmene porad plati to o tom binarnim rezimu.

+1

Re:Pár otázok na C++
« Odpověď #14 kdy: 24. 11. 2020, 16:47:47 »
Citace od: Wrána diskuze kdy 21. 11. 2020, 22:39:29
nóó ale stejně je takový zajímavý žeto c++kový '\n' je schodný zrovinka se zakončením řádku v linuxu. bych se taky jako mohla zeptat proč jinde potřebujou mit něco extra a jestli to jako dneska ještě vůůůbec dává nějakej smysl :P :P ;D ;)
Jestli dneska ještě něco vůbec dává smysl je vedlejší, protože zpětná kompatibilita, žeáno. Wokna mají CRLF protože to tak měl DOS a ten, protože to tak mělo CP/M a ten, protože to tak chtěly staré teletextové mašiny. Jabčáci měli původně CR, ale ti se nekompatibilních změn evidentně nebojí, tak přešli na Unixové LF. U Microsoftu změna nehrozí, tam občas neopravují ani bugy ale přidávají nová rozhraní, protože by opravou rozbili háky, co ty bugy obcházejí.