即使使用 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】:

您的代码中有各种可能的错误。我会尽量强调最重要的。

局部变量优于全局变量

iuserdataempleadosop 不需要是全局的。这是 C++,而不是 C,范围非常重要。在这种情况下,应该不需要在fstream 上调用close

不要递归调用main

这没有错,也不是很危险,但肯定是不好的做法。 main 方法应该从运行时调用,并且应该只调用一次。此外,递归不是这里的方法,根本没有必要。只需编写一个无限循环并使用continuebreak/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 &gt;&gt;func[l].nombre&gt;&gt;func[l].apellido &gt;&gt;func[l].categria&gt;&gt;func[l].horario&gt;&gt;func[l].salario_inicial &gt;&gt;func[l].salario_final; l++; while(l != k);那样做那我该怎么做呢? 为了将值赋给显示数据的变量,一个变量 = 一行。 如果我理解正确,您可以使用类似这样的内容:while (datain &amp;&amp; k &lt; empleados) datain &gt;&gt; func[l].nombre &gt;&gt; func[l].appelido /*...*/; ++l This will read data into the func[l]` 直到文件流达到 eof 或达到 empleados 的计数。如果从流中读取时发生错误,它也会停止循环。 如果这个数字真的不知道你不应该使用静态数组。而是使用std::vector 来存储项目。 但是如何根据写入的行数来评估变量的值?不知道你懂没。

以上是关于即使使用 ios::app 在 C++ 中覆盖 Fstream的主要内容,如果未能解决你的问题,请参考以下文章

C++ 中的动态绑定

c ++如何创建一个即使在对象被覆盖时也会持续的指针?

c++文件流fstream中的函数

C++ Builder使用FMX多平台框架(FireMonkey)移动(安卓iOS)APP开发参考书籍

c++中if语句的替代

解决Linux CentOS中cp -f 复制强制覆盖的命令无效的方法