Wątek przeniesiony 2015-09-02 11:05 z C/C++ przez ŁF.

Zamiana znaku po kodzie ASCII

0

Witam.
Chciałbym się was zapytać, czy można zmieniać znaki na inne po danym kodzie ASCII?

0
char c = 'A';
c = static_cast<char>(51);
cout << c << endl;
1

Można.

0

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) ??

0

Wstaw tamten kod w pętlę po wszystkich znakach z pliku? o_O

0

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) ?

1

C++ nie ma problemu z żadnymi znakami.

0

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 ?

0
  1. pokaż kod
  2. co to są „znaki SUB”?
0

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.

0

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ę :(

0

Ponawiam pytanie. Jak uporać się z tymi znakami ?

0

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.

0

Ktoś pomoże ?

0

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".

0

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 = ' ';
                   } );
}
0

Mimo pobrania boosta, wrzucenia do odpowiedniej lokalizacji wyskakuje błąd, że nie widzi tego pliku (chodzi o pierwsze #include)..

Czyżbym coś źle zrobił ?

0

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.

0

Dla visual studio masz tu gdzie ustawić http://stackoverflow.com/a/2676429

1

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;
}
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.

0

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

0
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ć ?

0

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

0

Twierdzę, że Notepad++ pokazuje ten znak jako SUB, natomiast program na właśnie tym znaku kończy pracę.

0

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.

0

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 ?

0

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++.

0

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) ??

0

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 ?

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