即使使用 ios::app 在 C++ 中覆盖 Fstream
Posted
技术标签:
【中文标题】即使使用 ios::app 在 C++ 中覆盖 Fstream【英文标题】:Fstream overwriting in C++ even with ios::app 【发布时间】:2014-04-12 15:24:46 【问题描述】:我有问题。 我开始了一个 porgram,它将保存数据(姓名、姓氏等)并将它们保存到 .txt 文件中。问题是它覆盖了文件中的数据。我已经在 fstream 文件中写了 ios::app ,但没有任何区别。 你们能帮帮我吗?
我会给你代码,但它是西班牙语的,所以我想我不会帮忙。
提前致谢;)
#include <iostream>
#include <windows.h>
#include <fstream>
#include <string.h>
using namespace std;
const int salario_minimo = 550;
fstream userdata;
int i;
struct FUNCIONARIO
char horario;
char categria;
int salario_inicial;
string nombre;
string apellido;
int id;
int salario_final;
;
FUNCIONARIO func[18];
int empleados;
int op;
int registrar()
userdata.open("FUNCIONARIOS.txt");
cout << "Escriba el nombre del nuevo funcionario" << endl;
cin >> func[empleados].nombre;
cout <<"Escriba el apellido del nuevo funcionario"<<endl;
cin >> func[empleados].apellido;
cout<< "Especifique su puesto -Operario(O) o Gerente(G)"<<endl;
cin >> func[empleados].categria;
cout << "Especifique su horario -Manana(M), tarde(T) o noche(N)"<<endl;
cin >> func[empleados].horario;
i = empleados;
empleados++;
for(int o = 0; o < 18; o++)
int p = o++;
userdata << i << endl << empleados << endl << func[o].nombre << endl
<< func[o].apellido << endl << func[o].categria << endl
<< func[o].horario << endl << func[o].salario_inicial << endl
<< func[o].salario_final << endl;
userdata.close();
//RESOLVER OVERWRITING URGENTE!!!!!
cout << "EMPLEADO NUMERO: " << empleados << endl;
cout << "NOMBRE: " << func[i].nombre << endl;
cout << "Apellido: " << func[i].apellido << endl;
cout << "EMPLEO: ";
switch (func[i].categria)
case 'G': cout << "GERENTE" << endl; break;
case 'O': cout << "OPERARIO" << endl; break;
default: break;
cout << "HORARIO: ";
switch(func[i].horario)
case 'M':
cout << "MANANA" << endl;
break;
case 'T':
cout << "TARDE" << endl;
break;
case 'N':
cout << "NOCHE" << endl;
break;
default:
break;
cout << "SALARIO INICIAL: " <<func[i].salario_inicial << endl;
cout << "SALARIO FINAL: " <<func[i].salario_final << endl;
system("PAUSE");
return 0;
int main()
ifstream comprobador;
comprobador.open("FUNCIONARIOS.txt");
if (comprobador.fail())
cout << "FILE NOT FOUND" << endl;
userdata.open("FUNCIONARIOS.txt", fstream::in | fstream::out | ios_base::app);
empleados = 0;
else
userdata.open("FUNCIONARIOS.txt",fstream::in | fstream::out | ios_base::app);
userdata >> i >> empleados;
userdata.close();
cout << "Numero Actual De Empleados:" << empleados << endl;
cout << "Bienvenido a BUSINESS MANAGEMENT SOFTWARE 1.0\n Por favor, seleccione una de estas opciones" << endl;
cout << "1.Registrar Un Nuevo Funcionario\n2.Ver Hojas De Pago\n3.Salir" << endl;
cin >> op;
switch (op)
case (1):
registrar();
break;
/*case 2:
mostrar();
break;*/
default:
cerr << "Please, Choose A Valid Option" << endl;
main();
break;
userdata.close();
return 0;
【问题讨论】:
好吧,我们需要查看代码以确定问题所在... 西班牙语很流行。 @pasztorpisti - 特别是在墨西哥和西班牙 @EdHeal :-) :-) :-) 来自***:“西班牙语是美国英语为母语的人学习的最流行的第二语言。” en.wikipedia.org/wiki/Spanish_language @Aleeo -- 你的母语是什么并不重要。无论您说西班牙语还是英语,C++ 关键字都是相同的。你不会说char *p = nuevo char[10];
吧?
【参考方案1】:
您的代码中有各种可能的错误。我会尽量强调最重要的。
局部变量优于全局变量
i
、userdata
、empleados
或 op
不需要是全局的。这是 C++,而不是 C,范围非常重要。在这种情况下,应该不需要在fstream
上调用close
。
不要递归调用main
这没有错,也不是很危险,但肯定是不好的做法。 main 方法应该从运行时调用,并且应该只调用一次。此外,递归不是这里的方法,根本没有必要。只需编写一个无限循环并使用continue
或break
/return
即可跳出。
例子:
while (true)
int op = 0;
cin >> op;
switch (op)
case 1:
registrar();
return 0; // Note that break would only break switch, not the while-loop
default:
cerr << "Please, Choose A Valid Option" << endl;
continue;
你在 for 循环中调用 close
这个循环应该如何工作?它在第一次迭代后关闭userdata
,然后尝试再写入文件 17 次(由于文件已关闭,这将失败):
for(int o = 0; o < 18; o++)
int p = o++;
userdata << /* ... */ endl;
userdata.close();
//RESOLVER OVERWRITING URGENTE!!!!!
为什么文件会被覆盖
您在多个位置打开文件,但只有两次指定app
。
看看这部分代码,注意 cmets:
ifstream comprobador;
comprobador.open("FUNCIONARIOS.txt"); // Open the file for input, no app
if (comprobador.fail())
cout << "FILE NOT FOUND" << endl;
// Ok, file not found, open with append (no need here, it's empty anyway!)
userdata.open("FUNCIONARIOS.txt", fstream::in | fstream::out | ios_base::app);
empleados = 0;
else
// File already found and still open for input, reopen with new fstream
// and specify append
userdata.open("FUNCIONARIOS.txt",fstream::in | fstream::out | ios_base::app);
// app places the filecursor at the end, the next statement will not work!
userdata >> i >> empleados;
// Now you close the file again!
userdata.close();
所以基本上在第一种情况下,文件是空的并且是打开的,在第二种情况下,文件很快就被打开了,但之后马上就关闭了。这不好,if
应该让userdata
保持一致状态。现在假设文件已关闭 (else
-statement),而您调用 registrar
。在registrar
的第一行是这样的声明:
userdata.open("FUNCIONARIOS.txt");
您再次打开文件,这次没有指定app
。
我建议在您的程序中使用ifstream
打开文件一次作为输入,将所有条目(如果有)读入内存,添加新条目然后写入文件一次 使用ofstream
并指定ios::trunc
来重写文件的所有条目,或者使用ofstream
打开文件并指定ios::app
并只添加一个条目。您必须先解析文件,因为您需要最后一行的 empleados
的编号。如果您在 ...
范围内打开文件,它会在最后自行关闭,无需调用 close。如果您直接使用指定的文件名和标志构造 fstream,您也不需要调用 open
。一个例子:
void registrar()
// ...
ofstream file("FUNCIONARIOS.txt", ios::app);
if (file)
file << /* ... */ endl;
// file will be closed here because ofstreams destructor is called
【讨论】:
谢谢!!!完美运行!现在您知道如何在文件中获取未定义数量的数据了吗?我的意思是,我看到我不能像int l = 0; int k = empleados - 1; do datain >>func[l].nombre>>func[l].apellido >>func[l].categria>>func[l].horario>>func[l].salario_inicial >>func[l].salario_final; l++; while(l != k);
那样做那我该怎么做呢?
为了将值赋给显示数据的变量,一个变量 = 一行。
如果我理解正确,您可以使用类似这样的内容:while (datain && k < empleados) datain >> func[l].nombre >> func[l].appelido /*...*/; ++l This will read data into the
func[l]` 直到文件流达到 eof 或达到 empleados
的计数。如果从流中读取时发生错误,它也会停止循环。
如果这个数字真的不知道你不应该使用静态数组。而是使用std::vector
来存储项目。
但是如何根据写入的行数来评估变量的值?不知道你懂没。以上是关于即使使用 ios::app 在 C++ 中覆盖 Fstream的主要内容,如果未能解决你的问题,请参考以下文章