¿Cuál sería la mejor manera de obtener el número de línea de la línea actual en un archivo que he abierto con un ifstream
? Así que estoy leyendo los datos y necesito guardar el número de línea en el que está para que pueda mostrarlo más tarde si los datos no coinciden con las especificaciones.¿Cómo obtener el número de línea de un archivo en C++?
Respuesta
Desde un punto de vista ifstream, no hay un número de línea. Si lee el archivo línea por línea, solo tiene que hacer un seguimiento de ello usted mismo.
Use std::getline
para leer cada línea en una por una. Mantenga un número entero que indica el número de líneas que ha leído: inicialícelo a cero y cada vez que llame al std::getline
y lo logre, increméntelo.
Si no quieren limitarse a std::getline
, entonces se podría utilizar clase derivada de std::streambuf
, y que realiza un seguimiento del número de línea actual:
class CountingStreamBuffer : public std::streambuf { /* see below */ };
// open file
std::ifstream file("somefile.txt");
// "pipe" through counting stream buffer
CountingStreamBuffer cntstreambuf(file.rdbuf());
std::istream is(&cntstreambuf);
// sample usage
is >> x >> y >> z;
cout << "At line " << cntstreambuf.lineNumber();
std::getline(is, str);
cout << "At line " << cntstreambuf.lineNumber();
Aquí es una implementación de ejemplo de CountingStreamBuffer
:
#include <streambuf>
class CountingStreamBuffer : public std::streambuf
{
public:
// constructor
CountingStreamBuffer(std::streambuf* sbuf) :
streamBuf_(sbuf),
lineNumber_(1),
lastLineNumber_(1),
column_(0),
prevColumn_(static_cast<unsigned int>(-1)),
filePos_(0)
{
}
// Get current line number
unsigned int lineNumber() const { return lineNumber_; }
// Get line number of previously read character
unsigned int prevLineNumber() const { return lastLineNumber_; }
// Get current column
unsigned int column() const { return column_; }
// Get file position
std::streamsize filepos() const { return filePos_; }
protected:
CountingStreamBuffer(const CountingStreamBuffer&);
CountingStreamBuffer& operator=(const CountingStreamBuffer&);
// extract next character from stream w/o advancing read pos
std::streambuf::int_type underflow()
{
return streamBuf_->sgetc();
}
// extract next character from stream
std::streambuf::int_type uflow()
{
int_type rc = streamBuf_->sbumpc();
lastLineNumber_ = lineNumber_;
if (traits_type::eq_int_type(rc, traits_type::to_int_type('\n')))
{
++lineNumber_;
prevColumn_ = column_ + 1;
column_ = static_cast<unsigned int>(-1);
}
++column_;
++filePos_;
return rc;
}
// put back last character
std::streambuf::int_type pbackfail(std::streambuf::int_type c)
{
if (traits_type::eq_int_type(c, traits_type::to_int_type('\n')))
{
--lineNumber_;
lastLineNumber_ = lineNumber_;
column_ = prevColumn_;
prevColumn_ = 0;
}
--column_;
--filePos_;
if (c != traits_type::eof())
return streamBuf_->sputbackc(traits_type::to_char_type(c));
else
return streamBuf_->sungetc();
}
// change position by offset, according to way and mode
virtual std::ios::pos_type seekoff(std::ios::off_type pos,
std::ios_base::seekdir dir,
std::ios_base::openmode mode)
{
if (dir == std::ios_base::beg
&& pos == static_cast<std::ios::off_type>(0))
{
lastLineNumber_ = 1;
lineNumber_ = 1;
column_ = 0;
prevColumn_ = static_cast<unsigned int>(-1);
filePos_ = 0;
return streamBuf_->pubseekoff(pos, dir, mode);
}
else
return std::streambuf::seekoff(pos, dir, mode);
}
// change to specified position, according to mode
virtual std::ios::pos_type seekpos(std::ios::pos_type pos,
std::ios_base::openmode mode)
{
if (pos == static_cast<std::ios::pos_type>(0))
{
lastLineNumber_ = 1;
lineNumber_ = 1;
column_ = 0;
prevColumn_ = static_cast<unsigned int>(-1);
filePos_ = 0;
return streamBuf_->pubseekpos(pos, mode);
}
else
return std::streambuf::seekpos(pos, mode);
}
private:
std::streambuf* streamBuf_; // hosted streambuffer
unsigned int lineNumber_; // current line number
unsigned int lastLineNumber_;// line number of last read character
unsigned int column_; // current column
unsigned int prevColumn_; // previous column
std::streamsize filePos_; // file position
};
Una manera simple pero ineficiente muertos es tiene una función que, dada una secuencia, cuenta los nuevos caracteres de línea desde el comienzo de la secuencia hasta la posición actual. Es ineficiente porque si desea conocer la línea para varias posiciones de transmisión, debe llamarla varias veces, comenzando a contar desde el principio de la secuencia cada vez. En algunos códigos en los que estoy trabajando, solo me interesa saber el número de línea si se encuentra una entrada no válida, en ese caso la importación se cancela inmediatamente. Como la función se llama solo una vez, la ineficiencia no es realmente un problema.
Aquí está mi código para hacer esto:
int getCurrentLine(std::istream& is)
{
int lineCount = 1;
is.clear(); // need to clear error bits otherwise tellg returns -1.
auto originalPos = is.tellg();
if (originalPos < 0)
return -1;
is.seekg(0);
char c;
while ((is.tellg() < originalPos) && is.get(c))
{
if (c == '\n') ++lineCount;
}
return lineCount;
}
Una ventaja del método es que no se necesitan cambios en el lugar donde se construye la corriente, sólo tiene que llamar a la función donde lo necesite . El siguiente es un ejemplo completo:
#include <iostream>
#include <sstream>
int getCurrentLine(std::istream& is)
{
int lineCount = 1;
is.clear(); // need to clear error bits otherwise tellg returns -1.
auto originalPos = is.tellg();
if (originalPos < 0)
return -1;
is.seekg(0);
char c;
while ((is.tellg() < originalPos) && is.get(c))
{
if (c == '\n') ++lineCount;
}
return lineCount;
}
void ReadDataFromStream(std::istream& s)
{
double x, y, z;
while (!s.fail() && !s.eof())
{
s >> x >> y >> z;
if (!s.fail())
std::cout << x << "," << y << "," << z << "\n";
}
if (s.fail())
std::cout << "Error at line: " << getCurrentLine(s) << "\n";
else
std::cout << "Read until line: " << getCurrentLine(s) << "\n";
}
int main(int argc, char* argv[])
{
std::stringstream s;
s << "0.0 0.0 0.0\n";
s << "1.0 ??? 0.0\n";
s << "0.0 1.0 0.0\n";
ReadDataFromStream(s);
std::stringstream s2;
s2 << "0.0 0.0 0.0\n";
s2 << "1.0 0.0 0.0\n";
s2 << "0.0 1.0 0.0";
ReadDataFromStream(s2);
return 0;
}
- 1. Obtener línea Número de cierta frase en el archivo Python
- 2. ¿Cómo obtener el número de línea actual?
- 3. Cómo obtener el método circundante en el archivo fuente Java para un número de línea dado
- 4. Obtener el número de línea de preg_match_all()
- 5. ¿Cómo determino el archivo y el número de línea de un método C# de un archivo de símbolos (.pdb)?
- 6. Número de línea actual de un System.Xml.XmlReader (C# & .Net)
- 7. cómo obtener el número de línea de error en el programa C++
- 8. cómo obtener el número mágico de un archivo binario
- 9. Cómo obtener el número de línea mediante escáner
- 10. ¿Cómo obtener el nombre del archivo de origen y el número de línea de un miembro de tipo?
- 11. obtener el número de línea para el error en XCode
- 12. Obteniendo el número de línea jsp real de un número de línea de rastreo de pila?
- 13. Cómo obtener una línea particular de un archivo
- 14. obtener el número de línea para el patrón emparejado
- 15. Obtener número de línea en el área de texto
- 16. ¿Cómo puedo obtener el número de columna del cursor en un cuadro de texto en C#?
- 17. comando unix para leer la línea de un archivo pasando el número de línea
- 18. powershell obtener el número de líneas del archivo grande (grande)
- 19. ¿Cómo obtener el número de línea de función (con/sin decorador) en un módulo de python?
- 20. Cómo obtener el número de filas con SqlDataReader en C#
- 21. Cómo obtener el número de línea del error al validar un archivo XML en un esquema XML
- 22. ¿Cómo puedo reemplazar una línea específica por número de línea en un archivo de texto?
- 23. ¿Cómo leer un archivo .gz línea por línea en C++?
- 24. ¿Cómo encontrar el número de línea del cursor en Python?
- 25. Contar el número de apariciones de token en un archivo
- 26. Cómo imprimir el número de caracteres en cada línea de un archivo de texto
- 27. ¿Cómo obtener el número total de iteraciones en un foreach
- 28. La lectura de un archivo línea por línea en C#
- 29. Recuperar el número total de líneas en un archivo
- 30. ¿Cómo obtener el número de columnas de un ResultSet JDBC?
Nota: puede leer línea por línea ('std :: getline') o simplemente contar el número de caracteres' \ n' que pasan. –
@ Matthieu: suponiendo que cada '\ n' significa una nueva línea en su plataforma. Me parece mejor hacer un seguimiento de las llamadas a nueva línea (un simple contenedor hará ...) – rubenvb
@rubenvb: en el modo de texto '\ n' representa una nueva línea,' iostream' usa la configuración regional para que sea así (ambas leyendo y escribiendo). Si lee en modo binario, por supuesto, no se produce ninguna conversión ... –