Error C++ ficheros y tildes

Iniciado por Desiresportal, 10 Marzo 2015, 18:37 PM

0 Miembros y 1 Visitante están viendo este tema.

Desiresportal

Pues eso, que tengo un problema con un programilla que estaba haciendo en C++.

La idea es un programa que elimina todos los comentarios de un codigo .js y los saltos de linea vacios. Se que estas cosas no afectan al rendimiento del juego o programa que contiene el codigo, pero a la hora de descargarlo tardará menos, serán menos megas en la tasa mensual y será un poquito mas rapida la carga del juego cuando se descarga la web.

Ademas, los comentarios solo me interesan a mi, no a los jugadores. Y los saltos de linea igual.

Ya que estaba haciendo el programa para suprimir parte del codigo me pregunté... ya que javascript tiene problemas para reconocer las tildes, eñes y caracteres "especiales"... ¿por que no hacer que los vaya sustituyendo según los encuentre? Al fin y al cabo una palabra con tilde solo se encuentra en el dialogo de personajes o en los comentarios y es un rollo cambiarlos manualmente todos. Y los comentarios serán borrados.

Pues aqui empieza el problemón.

Teniendo un archivo.js de referencia para pruebas:

apertura de exclamacion "¡"

a con tilde "á"
e con tilde "é"
i con tilde "í"
o con tilde "ó"
u con tilde "ú"

A con tilde "Á"
E con tilde "É"
I con tilde "Í"
O con tilde "Ó"
U con tilde "Ú"

ny "ñ"

NY "Ñ"


Y el siguiente codigo para el "depurador.cpp":

#include <iostream>
#include <windows.h>
#include<fstream>
using namespace std;

void buscar_y_reemplazar_todos(string& frase, string buscar, string reemplazar) {
int pos=frase.find(buscar);
while (pos!=string::npos) {
frase.replace(pos, buscar.size(), reemplazar);
pos=frase.find(buscar, pos + reemplazar.size());
}
}

void eliminar_desde(string& frase, string buscar) {
int pos=frase.find(buscar);
frase.replace(pos, (frase.size() - pos), "\n");
}

void eliminar_hasta(string& frase, string buscar) {
int pos=frase.find(buscar);
frase.replace(0, (pos + buscar.size()), "");
}

void eliminar_punto_punto(string& frase, string buscar_principio, string buscar_final) {
int pos_ini = frase.find(buscar_principio);
int pos_fin = frase.find(buscar_final);
frase.replace(pos_ini, ((pos_fin - pos_ini) +  buscar_final.size()), "");
}

int main() {
bool comentando=false, todo_correcto=false;
string linea, out_text, nombre_fichero;
ifstream archivo;
getline(cin, nombre_fichero);
buscar_y_reemplazar_todos(nombre_fichero, "\n", "");
while (!todo_correcto) {
archivo.open(nombre_fichero.c_str());
if (archivo.is_open()) {
getline(archivo, linea);
while (!archivo.eof()) {
//Añado el final de linea para no tener errores.
linea = linea + "\n";
//Eliminar tabulaciones
buscar_y_reemplazar_todos(linea, "\t", "");
//Sustituir las letras especiales por sus correcciones para javascript
buscar_y_reemplazar_todos(linea, "á", "\\xE1");
buscar_y_reemplazar_todos(linea, "é", "\\xE9");
buscar_y_reemplazar_todos(linea, "í", "\\xED");
buscar_y_reemplazar_todos(linea, "ó", "\\xF3");
buscar_y_reemplazar_todos(linea, "ú", "\\xFA");
buscar_y_reemplazar_todos(linea, "ñ", "\\xF1");
buscar_y_reemplazar_todos(linea, "Á", "\\xC1");
buscar_y_reemplazar_todos(linea, "É", "\\xC9");
buscar_y_reemplazar_todos(linea, "Í", "\\xCD");
buscar_y_reemplazar_todos(linea, "Ó", "\\xD3");
buscar_y_reemplazar_todos(linea, "Ú", "\\xDA");
buscar_y_reemplazar_todos(linea, "Ñ", "\\xD1");
buscar_y_reemplazar_todos(linea, "¿", "\\xBF");
buscar_y_reemplazar_todos(linea, "¡", "\\xA1");

//Si no existe "function" ni "else if" en la linea actual, eliminar espacios (en python no hay nada al respecto, pero puede ayudar)
/*if (linea.find("function") == string::npos && linea.find("else if") == string::npos && linea.find("var ") == string::npos) {
buscar_y_reemplazar_todos(linea, " ", "");
}*/
if ((linea!="\n") && (linea.find("/*")==string::npos) && (comentando==false) && (linea.find("*/")==string::npos)) {
if (linea.find("//")!=string::npos) {
//Parto la cadena en dos en la subcadena "//"
eliminar_desde(linea, "//");
//Sumo "\n" a la primera parte de la cadena recien partida
}
if (linea!="\n") {
//Se aplica el contenido de la linea a la salida
out_text = out_text + linea;
}
}
if (linea.find("/*")!=string::npos && linea.find("*/")!=string::npos) {
//Quedaria especificar el caso pero aqui habria un comentario que eliminar. En python se dejaba y se advertía de la linea en la que estaba para eliminarlo manualmente.
//Las posibilidades son:
// - Principio-Final
// - Medio-Final
// - Principio-Medio
while (!(linea.find("/*")!=string::npos && linea.find("*/")!=string::npos)) {
eliminar_punto_punto(linea, "/*", "*/");
}
}
else if (linea.find("/*")!=string::npos) {
//Habría que ver si tiene codigo antes (por si acaso)
if (linea.find("/*")!= 0) {
eliminar_desde(linea, "/*");
out_text = out_text + linea;
}
comentando=true;
}
else if (linea.find("*/")!=string::npos) {
//Habría que ver si tiene codigo despues (por si acaso)
eliminar_hasta(linea, "*/");
out_text = out_text + linea;
comentando=false;
}
getline(archivo, linea);
}
out_text = out_text + linea;

//buscar_y_reemplazar_todos(linea, "¡", "\\xA1");
archivo.close();

if (out_text.find("") == string::npos && out_text.find("Ã") == string::npos && out_text.find("š") == string::npos && out_text.find("‰") == string::npos) {
ofstream archivo2;
//if (archivo2.is_open()) {
archivo2.open(nombre_fichero.c_str());
archivo2 << out_text;
archivo2.close();
cout << "Parece que todo ha salido bien." << endl;
todo_correcto = true;
system("pause");
//}
//else {
//cout << "Ha habido un error al escribir el archivo." << endl;
//system("pause");
//}
}
else {
cout << "Error de traduccion. Volviendo a intentarlo..." << endl;
out_text="";
}
}
else {
system("color 0c");
cout << "Ha habido un error." << endl;
todo_correcto = true;
system("pause");
}
}
return 0;
}



Me encuentro con algunos errores un poco inquietantes. Si ejecuto una vez el depurador puede que lo haga bien. Pero la siguiente ejecucion aparecen caracteres erroneos en el archivo.js. Sustituye bien los caracteres y no hay problema a la hora de escribirlo en el fichero. El problema es que en la orden string.replace("blablabla"); pone por delante algo como "Ã", "", "‰" o "š". Pero no siempre.

Lo que me deja perplejo es que a diferentes ejecuciones, diferentes resultados. Y es como si llevase la cuenta. Si no le dejo escribirlo en el archivo.js, como que no esta contento por que a la proxima ejecucion sigue haciendolo mal. (en este codigo se queda clavado en errores, de hay que sepa que lo hace mal y no vuelve a hacerlo bien nunca. [aúnque reinicie el equipo, sigue hacendolo mal.])

En fin. ¿Alguien que pueda revisar el codigo y aclararme la equivocacion?

Por si tiene algo que ver... uso windows 7 64bit, CodeBlocks 13.12 y el codigo tal cual lo veis.

Un saludo y gracias.

Agradecería tambien que quien responda, se suscriba o siga este tema por si me surgen mas dudas. (ha habido veces que alguien responde y no vuelve a pasar nunca para ver si existen mas cuestiones o ver si realmente ha servido de algo.)

PD: También lo hice en python, pero como que las "\" no deja meterlas bien en los strings.

Orubatosu

C++ en modo consola no maneja los acentos muy bien (mas bien nada), peor es posible usarlos.

Intentalo con esto a ver si te funciona

Añade la librería clocale

Código (cpp) [Seleccionar]
#include <clocale>

En tras el main, añade esta línea

Código (cpp) [Seleccionar]
setlocale(LC_ALL, "");

Debería de aplicar el "locale" actual del sistema operativo para poder manejarlo.

Probablemente con eso te funcione, si no es así, nos dices que te sale
"When People called me freak, i close my eyes and laughed, because they are blinded to happiness"
Hideto Matsumoto 1964-1998

Desiresportal

Uff. Me sigue dando el mismo error.

El problema es en la orden "string.replace()". A partir de hay el codigo comprueba si se ha echo bien, de lo contrario vuelve a empezar. Y ahí es donde entra en bucle. Vuelve a empezar, no lo hace bien, ve que no lo ha echo bien, vuelve a empezar, no lo hace bien, ve que no lo ha echo bien, vuelve a empezar, no lo hace bien, ve que no lo ha echo bien, vuelve a empezar...

No se trata de mostrar en consola, se trata de reescribir el fichero. Pero aún así el error se produce en la sentencia "string.replace()".

Gracias de todos modos. Seguro que en el futuro esta parte tambien me sirve.

eferion

Si alguna vez has echado un vistazo a una tabla ASCII (ahora es un buen momento), verás que no hay símbolos con acentos, que no existe la 'ñ' ni tampoco la apertura de interrogación '¿'. Esto se debe a que ASCII emplea como base la escritura inglesa... y en inglés ni hay acentos, ni existe la 'ñ' ni tampoco la apertura de interrogaciones.

¿Qué tiene que ver esto con tu problema? sencillo. "string" es una clase que codifica las cadenas usando "char". Además, sucede que char es un tipo de 8 bits con signo, es decir, únicamente utiliza 7 caracteres para codificar. Esto te da 127 combinaciones posibles... y, para rematar, la tabla ascii tiene 127 caracteres. ¿Coincidencia? va a ser que no. Vamos, que en un char no puedes, por defecto, incluir ninguno de estos caracteres.

Lo mismo ahora te preguntas ¿Y cómo es que yo si puedo usar estos caracteres en mi ordenador? bueno, esto es debido a que tu sistema utiliza una codificación un tanto más elaborada. Las codificaciones más comunes son UTF-8 , unicode o alguna de las infinitas ANSI. Estas codificaciones permiten mostrar un número significativamente más elevado de símbolos, y para conseguir esto acaban usando más de un char por símbolo.

Por supuesto, estas codificaciones no son compatibles entre sí. Y esto se puede observar en algunas páginas de Internet, donde, de repente, aparecen caracteres raros. La única parte compatible entre estas codificaciones suelen ser los primeros 127 caracteres, que se suelen corresponder con los enumerados en la tabla ascii

Lo que vengo a decirte con esta parrafada es que, para tu caso, "string" se te queda pequeña. Posiblemente tengas que usar "wstring".

Y, bueno, claro, interpretar los caracteres según la codificación que tenga el fichero ('á' tiene codificaciones diferentes según sea UTF-8 o unicode).

Un saludo.

Desiresportal

Aún no controlo mucho C++. Estoy aprendiendo. Gracias por la aclaración. Voy a intentar hacerlo con vectores (que acabo de aprender a usarlos en C++).

Haré lo siguiente:
- Voy a leer el fichero linea a linea.
- Deshacer las lineas letra a letra.
- Transformar las letras en enteros.
- Colocar los enteros en vectores.
- Si existen coincidencias: sustituir los enteros existentes por los enteros de los caracteres que quiero que salgan.
- Transformar los enteros en caracteres.
- Meter carácter por carácter en el fichero.

A ver si así lo consigo sacar... ya contaré. Si con el script anterior, una de cada dos salía correctamente como yo quería... esto tendrá que funcionar por huevos. Es pura lógica. Poder puede (por que alguna vez ha salido [insisto]), pero por alguna razón (seguro que la que tu decías) no hace lo siempre bien.


(Seguro que para el Lunes lo tengo comprobado) Ya contaré... Gracias de nuevo por la colaboración.

Desiresportal

El problema persiste.

Buscare acerca de "wstring"...