C/Visual C - Problemas al crear fichero con nombre XXX

 
Vista:

Problemas al crear fichero con nombre XXX

Publicado por Nelek (816 intervenciones) el 21/03/2007 15:03:22
Hola,

Estoy intentando crear un fichero de "Codigo Portable" para mi aplicacion y estoy teniendo problemas que no puedo explicarme a la hora de crearlo. El codigo lo he puesto para clarificar, el problema y la duda que planteo estan despues del codigo, detras de las dos lineas de ///////////////// (por si preferis leerlo antes de mirar el codigo)

Por un lado tengo esta funcion para crear el nombre del fichero segun el nombre del proyecto del que se crea:

char* CPCodeTool::SetFileName ()
{
extern CMyDoc* m_pFirstDoc;

CString szTitle = m_pFirstDoc->GetTitle ();
//CString szBug = "PC"; //OPCION 3:
CString szHelp = ".pc";
int i = 0;
bool bTotal = false;
char cName [256] = {0};

//cName[0] = szBug[0]; //OPCION 3:
//cName[1] = szBug[1]; //OPCION 3:

for (i = 0; i < szTitle.GetLenght(); i++)
//for (i = 2; i < szTitle.GetLength () + 2; i++) //OPCION 3:
{
cName[i] = szTitle[i];
//cName[i] = szTitle[i-2]; //OPCION 3:
CString cLetter = szTitle.GetAt (i);
//CString cLetter = szTitle.GetAt (i-2); //OPCION 3:
if (cLetter == ".")
{
cName[i+1] = szHelp[1];
cName[i+2] = szHelp[2];
bTotal = true;
break;
}
}

if (bTotal == false)
{
cName[i] = szHelp[0];
cName[i+1] = szHelp[1];
cName[i+2] = szHelp[2];
}

return &cName[0];
}

Donde las lineas donde pongo el comentario OPCION 3: normalmente no estan y en caso de estar sustituyen a la linea equivalente que esta inmediatamente encima de ellas (en caso de sustituir algo)

Por otro lado creo y relleno el fichero con la funcion:

void CFPSView::ProbandoPC ()
{
CPCodeTool pcTool;
char* pFile = "TestingVeryLongMyDocumentName.pc"; //OPCION 1:
//char* pcName = pcTool.SetFileName (); //OPCION 2:

TRY
{
CFile f (pFile, CFile::modeCreate | CFile::modeWrite); //OPCION 1:
//CFile f (pcName CFile::modeCreate | CFile::modeWrite); //OPCION 2A:
//CFile f (pcTool.SetFileName (), CFile::modeCreate | CFile::modeWrite); //OPCION 2B:

DWORD dwActualPos = NOTHING;

pcTool.WritePCHeader (&f);
dwActualPos = f.SeekToEnd ();

pcTool.WritePCCode (&f);
dwActualPos = f.SeekToEnd ();

}
CATCH( CFileException, e )
{
#ifdef _DEBUG
afxDump << "File could not be opened " << e->m_cause << "\n";
#endif
}
END_CATCH
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Espero que se entienda lo de las "OPCION X" de los comentarios, es por no repetir 3 veces el mismo codigo y hacer esas pequenyas modificaciones.

El problema es:

Con la OPCION 1, es decir...
//...
char* pFile = "TestingVeryLongMyDocumentName.pc"
//...
CFile f (pFile, CFile::modeCreate | CFile::modeWrite);
//...

Sale de perlas, crea el fichero en C:\Dokumente und Einstellungen\Diaz-Villanueva\Eigene Dateien\TestingVeryLongMyDocumentName.pc (Mi windows esta en aleman) y lo rellena con los datos como toca (el contenido no es la duda de este mensaje)

Con la OPCION 2, es decir...
//...
char* pcName = pcTool.SetFileName ();
//...
CFile f (pcName CFile::modeCreate | CFile::modeWrite);
o bien
CFile f (pcTool.SetFileName (), CFile::modeCreate | CFile::modeWrite);
//...

El fichero se crea y es rellenado como toca, PERO EL NOMBRE PIERDE LAS DOS PRIMERAS LETRAS, es decir, si mi proyecto se llama "ProyectoPrueba.fs", el fichero creado se llama "oyectoPrueba.pc", si se llama "Test.fs" sale "st.pc"

Lo que mas gracia me hace es que cuando pongo un punto de interrupcion justo antes de la creacion del fichero con la opcion 2 o 2A, la ventana de observacion del DEBUG tiene:

pcName = 0x0012f930 ("ProyectoPrueba.pc")
//pero JUSTO despues de crear el fichero queda
pcName = 0x0012f930 ("oyectoPrueba.pc")

lo que mas me mosquea es que el fichero en si, si que contiene el nombre que toca:
f = {hFile=3000 name = "C:\Dokumente und Einstellungen\Diaz-Villanueva\Eigene Dateien\ProyectoPrueba.pc"}

Pero aun asi lo sigue creando con las dos letras menos...


Y con la OPCION 3, es decir...
Con las modificaciones esas en la funcion SetTitle (CString szBug y los + o - 2 donde son necesarios)
//...
CFile f (pcName CFile::modeCreate | CFile::modeWrite);
o bien
CFile f (pcTool.SetFileName (), CFile::modeCreate | CFile::modeWrite);
//...

Directamente NO LO CREA, dumpeando el mensaje de error:
CFile exception: badPath, File n\PCProyectoPrueba.pc, OS error information = 3.
Excepcion no contemplada en FPSII.exe (KERNEL32.DLL): 0xE06D7363: Microsoft C++ Exception.


Alguien me podria explicar que demonios esta pasando y como podria solucionarlo???
Yo, sencillamente, no lo entiendo.

Gracias y perdon por la extension.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

RE:Problemas al crear fichero con nombre XXX

Publicado por Tom (27 intervenciones) el 22/03/2007 09:44:54
No lo he examinado en profundidad, pero ...
En SetFileName() retornas la dirección de una variable local al procedimiento:

char cName[256] = {0};
...
return cName;
}

Eso está mal, precisamente porque es una variable local, cuyo contenido puede ser sobreescrito en cualquier momento una vez que cName ha salido de ámbito(justo después del return :-))

Si no quieres hacer muchos cambios, esto funcionaría:

char *cName = malloc(256);
bzero(cname);
...
return cName;
}

o también, tal y como lo tienes, pero retornando una copia:

return strdup(cName);
}

malloc obtiene espacio de memoria en el 'heap' (espacio global) que no sale de ámbito, mientras que con "char cName[256]" reservas espacio (normalmente) en el 'stack' de la función, que se puede sobreescribir con una llamada a otra función.

¡¡ Si usas este método, recuerda liberar la memoria con free() !!

ProbandoPC() {
...
...
free(pcName);
}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Problemas al crear fichero con nombre XXX

Publicado por Nelek (816 intervenciones) el 22/03/2007 09:57:32
Hola Tom,

gracias por tu respuesta, nos hemos cruzado, al final lo he solucionado de otra manera. Ahora ya me crea el fichero sin faltar las dos letras iniciales. Creo que el problema era que la String tiene los dos primeros BYTEs con informacion en cuanto al largo y otra cosa, asi que al traspasar yo los caracteres de la String al char* [], no traspasaba esos dos BYTEs y por eso, el File.Create se rallaba y hacia desaparecer las dos primeras letras. Puede ser?
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Solucionado, pero sigo sin entender lo que pasaba

Publicado por Nelek (816 intervenciones) el 22/03/2007 09:54:31
He logrado solucionarlo a raiz de una idea de un companyero de trabajo. Aunque sigo sin entender el por que de lo de arriba. Bueno, el nuevo codigo es:

CString CPCodeTool::SetFileName ()
{
extern CFPSDoc* m_pFirstDoc;
CString szTitle = m_pFirstDoc->GetTitle ();

int nRepl = szTitle.Replace (".fs", ".pc");

if (nRepl == 0)
szTitle += ".pc";

return szTitle;
}

Y POR OTRO LADO:

void CFPSView::ProbandoPC ()
{
CPCodeTool pcTool;
CString pcName;

if (pcTool.CheckPCAvailability ())
{
pcTool.SetElementsID ();
pcName = (LPCTSTR) pcTool.SetFileName ();
}
else
return;

TRY
{
CFile f (pcName, CFile::modeCreate | CFile::modeWrite);
DWORD dwActualPos = NOTHING;

pcTool.WritePCHeader (&f);
dwActualPos = f.SeekToEnd ();

pcTool.WritePCCode (&f);
dwActualPos = f.SeekToEnd ();
}
CATCH( CFileException, e )
{
#ifdef _DEBUG
afxDump << "File could not be opened " << e->m_cause << "\n";
#endif
}
END_CATCH
}

Y como se suele decir... Si algo funciona... no lo toques mas ;) :P
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Solucionado, pero sigo sin entender lo que pasa

Publicado por Tom (27 intervenciones) el 22/03/2007 14:20:00
Pues funciona porque ya no haces lo mismo.
Ahora, aparentemente, utilizas una variable global (o estática, me da lo mismo).
Por cierto, no sé que importancia tendrá, pero, parece que estás cambiando el título de algo ...
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Solucionado, pero sigo sin entender lo que pasa

Publicado por Nelek (816 intervenciones) el 22/03/2007 15:40:26
Mas que cambiarle el titulo lo que estoy haciendo es coger el titulo del proyecto activo y cambiandole la extension para crear el fichero del codigo portatil con el mismo nombre que el proyecto del que viene.

Mi programa es un simulador para procesos regulados por Logica Fuzzy, el sistema se crea en el programa bajo la extension *.fs y ahi es donde se especifican las variables, sus atributos, las reglas que ha de seguir el regulador, como afectan las variaciones de las entradas a las salidas, etcetera.

Pero el objetivo final es el poder mandar ese sistema creado en el programa, en un fichero binario a un automata Siemens S7, el contenido del fichero portable lo he acabado hoy y por ahora parece que es correcto. Pero queria sincronizar los nombres del fichero portable y del proyecto del que viene para que luego sea mas facil identificar las cosas y poder hacer modificaciones.

Ahora solo me falta el paso inverso, leer el contenido de un fichero portable y transformarlo todo al formato de mi programa para hacer las modificaciones de modo sencillo con el interfaz grafico.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar