It is very easy to read data from a file using ifstream
and std::getline
, what is not simple (and does not make much sense) is to read in char *
.
Having the text data in a pointer implies that the programmer must take charge of the management of said pointer, being this prone to errors.
Read a line in a pointer to character ... bad idea.
char *lee_de_archivo(const std::string nombre)
{
std::ifstream archivo(nombre);
std::string linea{};
if (std::getline(archivo, linea))
{
char *resultado = new char[linea.size() + 1];
std::copy(linea.begin(), linea.end(), resultado);
resultado[linea.size()] = 0;
return resultado;
}
return nullptr;
}
This function obtains the text of the file but the programmer must take charge of releasing the requested memory after its use:
char *palabra = lee_de_archivo("Hola.txt");
delete [] palabra;
Otherwise, there would be a memory leak , as in the following examples:
std::cout << lee_de_archivo("Hola.txt") << '\n';
std::string mensaje = std::string("Mensaje: ") + lee_de_archivo("Hola.txt");
std::copy(lee_de_archivo("Hola.txt"), lee_de_archivo("Hola.txt") + 10, ptr);
Especially the last line is ominous because in addition to memory leaks it would cause invalid access to memory since the return of lee_de_archivo
returns different pointers on each call.
Why not access the internal pointer of a std::string
?
The proposal for eLRuLL access the internal pointer of a std::string
object using the c_str
and this can also be problematic, we can see it adapting the function lee_de_archivo
:
char *lee_de_archivo(const std::string nombre)
{
std::ifstream archivo(nombre);
std::string linea{};
if (std::getline(archivo, linea))
{
return linea.c_str();
}
return nullptr;
}
By the time we exit the function lee_de_archivo
the linea
object that the pointer to the string gives us ceases to exist, and consequently the pointed data is no longer valid.
The eLRuLL code does not have that problem since the life cycle of std::string
and pointer the internal data match, but it is considered bad practice to break the encapsulation by saving pointers or references to internal data of an object.
I have to use char * and not string. - akko
It's a pointless limitation in modern C ++. The current trend is for low-end pointers to fall into disuse being replaced by smart pointers or other objects that handle the cycle. life of dynamic memory.
My advice is to forget that limitation and use std::string
that gives less problems:
std::string lee_de_archivo(const std::string nombre)
{
std::ifstream archivo(nombre);
std::string linea{};
std::getline(archivo, linea);
return linea;
}