Witam.
Chciałbym się was zapytać, czy można zmieniać znaki na inne po danym kodzie ASCII?
char c = 'A';
c = static_cast<char>(51);
cout << c << endl;
Można.
Wielkie dzięki, a czy mogę za pomocą jakieś funkcji \ pętli czegokolwiek zrobić tak, aby zmieniało jakiś podany kod ascii na inny (w całym pliku tekstowym) ??
Wstaw tamten kod w pętlę po wszystkich znakach z pliku? o_O
A można zrobić tak, aby wszystkie znaki z jakimi C++ ma problem odczytać zamieniać na spacje. Mam tu na myśli takie znaki jak SUB (Alt+26) ?
C++ nie ma problemu z żadnymi znakami.
OK. W takim razie używam złej funkcji / otwieram plik w złym kodowaniu, itp.
Gdyż podczas otwarcia pliku, który zawiera znaki SUB program kończy wczytywanie na ostatnim znaku przed tym SUBem. Jak sobie z tym poradzić.
Korzystam z fstream w jak prostszym trybie otwarcia iso::in.
Jakieś sugestie ? Otworzyć plik binarnie ? Jeśli tak to co dalej ?
- pokaż kod
- co to są „znaki SUB”?
Co to jest znak SUB: https://en.wikipedia.org/wiki/Substitute_character
Gdzie miałem z tym do czynienia: na końcu pliku (ale w Pascalu).
Nie wiem skąd Ci się to wzięło w C/C++, ale jak pokażesz kod (i ew. plik, chociaż chyba niepotrzebny) to może coś się poradzi.
Kod jest dosyć prosty, bo jak pisałem jest na zasadzie funkcji fstream:
fstream plik (PLIK.c_str(), ios::in);
do
{
getline(plik, line);
linie=linie+1;
}while(!plik.eof());
Problem jest w tym, że program przestaje wczytywać przy pierwszym napotkaniu znaku SUB, co bardzo komplikuję sprawę :(
Ponawiam pytanie. Jak uporać się z tymi znakami ?
Ale tak ma być przecież. Nic z tym nie zrobisz. Ten znak jest wysyłany np. na standardowe wejście w konsoli po wciśnięciu Ctrl+Z. Co oznacza EOF. Koniec kropka. Bo znak SUB oznacza właśnie koniec pliku. Osobiście nie spotkałem się z plikiem który by ten znak posiadał w sobie. Możesz kombinować z API systemowym. Czyli pobrać wielkość pliku oraz pobrać sekwencyjnie tyle bajtów z pliku ile ma jego rozmiar. Ale to już będzie zależne od platformy.
Ktoś pomoże ?
A kto w ogóle umieszcza w pliku tekstowym znaki SUB... Mi się wydaje, że wcześniej zrobiłeś coś źle i teraz próbujesz to naprawić coś ala "reverse engineering".
Nie wiem czy Cie dobrze zrozumiałem.
Boosta zawsze możesz na coś zamienić.
#include <boost/iostreams/device/mapped_file.hpp>
#include <algorithm>
int main()
{
const uint8_t SUB = 0x1A;
boost::iostreams::mapped_file mmap( "input.txt", boost::iostreams::mapped_file::readwrite );
auto begin = mmap.data();
auto end = begin + mmap.size();
std::for_each( begin,
end,
[]( char &n )
{
if( n == SUB )
n = ' ';
} );
}
Mimo pobrania boosta, wrzucenia do odpowiedniej lokalizacji wyskakuje błąd, że nie widzi tego pliku (chodzi o pierwsze #include)..
Czyżbym coś źle zrobił ?
Tak. Najprawdopodobniej wrzucłeś to do złej "odpowiedniej lokalizacji". To znaczy gdzie konkretnie? =_=. Wiesz, my się nie domyślimy. Następnym razem jak zapytasz o coś to pamiętaj o podaniu jakiś szczegółów.
Boosta możesz wrzucić gdziekolwiek, tylko folder z includem musisz zaincludować.
Dla g++ jest to parametr -I
http://stackoverflow.com/questions/12654013/how-to-make-g-search-for-header-files-in-a-specific-directory
PS. korzystasz z iostreama, więc dodatkowo oprócz plików nagłówkowych musisz również zlinkować tą konkretną biblioteke.
Dla visual studio masz tu gdzie ustawić http://stackoverflow.com/a/2676429
Spróbuj tak.
#include <vector>
#include <iterator>
#include <iostream>
#include <algorithm>
// troche szumu + znaki
// echo -e `seq 0 50` '\x1a' '\x1a' `seq 0 15` > test.txt
// hexdump test.txt | grep 1a
//
// Jak widać, znaki są...
//0000080 3634 3420 2037 3834 3420 2039 3035 **1a**20
//0000090 **1a**20 3020 3120 3220 3320 3420 3520 3620
int main()
{
std::ifstream file("test.txt", std::ifstream::in);
std::vector<char> bytes((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
std::cout << "Przed:" << std::count(bytes.begin(), bytes.end(), '\x1a') << std::endl;
std::replace(bytes.begin(), bytes.end(), '\x1a', 'C');
std::cout << "Po:" << std::count(bytes.begin(), bytes.end(), '\x1a') << std::endl;
std::ofstream fileout("swap.txt", std::ofstream::out);
std::copy(bytes.begin(), bytes.end(), std::ostream_iterator<char>(fileout));
return 0;
}
Litości, ile razy można mówić że SUB nie jest normalną sytuacją w czytaniu pliku?
Zamiast leczyć objawy proponuję najpierw poszukać przyczyny.
@Kremius: możliwe przyczyny:
- czytasz plik binarny w trybie tekstowym
- czytasz plik tekstowy UTF8 w trybie... tekstowym (w zasadzie w takim przypadku powinno działać dobrze)
- nie sprawdzasz żadnych flag I/O poza eof
- nie zamykasz pliku
Przeczytaj:
http://www.cplusplus.com/doc/tutorial/files/
Jeśli nie pomoże dołącz kod programu i przede wszystkim plik testowy.
test.txtZawartość pliku wejściowego:
ul. Sk[SUB]odowskiej - Curie 73D 87-10Toru[SUB]
Al. Jana Paw[SUB]a II 11a 81-34Gdynia
[SUB] -tutaj pokazuje się znak, który chce usunąć, a więc podmieniany jest za niektóre polskie znaki. Co ciekawe nie każde, gdyż 'ć' wczytuje normalnie
Proxima napisał(a):
Spróbuj tak.
#include <vector>
#include <iterator>
#include <iostream>
#include <algorithm>
// troche szumu + znaki
// echo -e `seq 0 50` '\x1a' '\x1a' `seq 0 15` > test.txt
// hexdump test.txt | grep 1a
//
// Jak widać, znaki są...
//0000080 3634 3420 2037 3834 3420 2039 3035 **1a**20
//0000090 **1a**20 3020 3120 3220 3320 3420 3520 3620
int main()
{
std::ifstream file("test.txt", std::ifstream::in);
std::vector<char> bytes((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
std::cout << "Przed:" << std::count(bytes.begin(), bytes.end(), '\x1a') << std::endl;
std::replace(bytes.begin(), bytes.end(), '\x1a', 'C');
std::cout << "Po:" << std::count(bytes.begin(), bytes.end(), '\x1a') << std::endl;
std::ofstream fileout("swap.txt", std::ofstream::out);
std::copy(bytes.begin(), bytes.end(), std::ostream_iterator<char>(fileout));
return 0;
}
Wynik pokazuje się taki:
Przed: 0
Po: 0
Tak powinno być ?
Jeśli std::count
zwraca 0 to jest na 99 % pewne że to nie jest żaden sub i ci się tylko tak wydaje.
Daj hexdumpa (albo upnij plik + twój kod).
// edit
@Kremius pobierznie przejrzałem wątek i nigdzie nie piszesz jakobyś sprawdził to hexedytorem, więc właściwie mam pytanie, na jakiej podstawie przez 3 strony twierdzisz że to jest akurat znak SUB? :D
Twierdzę, że Notepad++ pokazuje ten znak jako SUB, natomiast program na właśnie tym znaku kończy pracę.
Ten plik jest zepsuty. Przeczytany złym narzędziem a potem zapisany.
Każda polska litera zapisana jest jako 1A.
Możesz poprawić hex-edytorem na polskie znaki (np. Win1250) i zamknąć wątek.
Plik wypakowaniu z pliku *.gz (przez 7zip) ma jakby postać (nazwa i format): 00557.OUT.10519.150828_164518
jak taki jakby format .150828_164518 zamienić na txt nie niszcząc zawartości jeśli faktycznie jest to powód nie działania ?
Coś partaczysz, to jest pewne. Jeśli twoim problemem jest 7zip czy format archiwum, proponuje odpuść kombinacje co tam nie gra bo to może być wiele rzeczy. Ewentualnie przekopiuj zawartość pliku/ów ręcznie, i popraw hexedytorem lub tym notepadem++.
Nie ja tworzę pliki, które program ma wczytywać. Każdy polski znak poza 'ć' jest w hex zapisany jako 1A więc nie wiem co tu jest źle robione ??
Edit
Po wczytaniu plik poprzez ios::in | ios::binary mam coś takiego jak w załączniku.
Znaki, które zamykają program to te strzałki, zamiast polskich znaków...
Poza tym ktoś może wytłumaczyć co to za znaki na początku linii (takie jakby wcięcie) ??
OK. Postanowiłem wytężyć swój tępy łeb i mam coś takiego (pewnie niezbyt wydaje, źle napisane, itp (ale działa :P ):
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
string zmienna;
fstream plik ("test.txt", ios::in | ios::binary);
do
{
getline(plik,zmienna);
int a=zmienna.find('\x1a');
if(a>=0){
zmienna.erase(a,1);
zmienna.insert(a,1,' ');
}
cout<<zmienna;
}while(!plik.eof());
return 0;
}
Jak mogę coś takiego przerobić, aby wykonywało tego erase - insert dopóki nie odszuka żadnego '/x1a', oraz string wynikowy, a więc zamienione '/x1a' (wredny znak) zamieniało na ' ' (magiczną spacje) w pliku wyjściowym ?
Pomożecie z tym ?