OOP文件读取问题



我在用c++做oop项目时遇到了一个问题。我在下面提到了代码。我得到的坏结果是:

  • 如果我列出了我添加了一些联系人的现有文件,它将正确列出文件的所有内容。但是,如果我尝试以管理员身份登录来添加新联系人(如果您只需要,pass=12345(,现在,如果我试图打开我添加新联系人的文件。问题就出现在这里
  • name应该列为name:Samir Chapagain
  • 地址本应列为Adress:Nepal
    ,依此类推,但它跳过了行,在地址的位置显示名称为Adress:Samir Chapagain

如何克服它??带我出去。我是编码的初学者
提前感谢!!。

源代码

#include <cstring>
#include <fstream>
#include <iostream>
using namespace std;
class Contact
{
public:
string details[5] = {"Name", "Phone(Mobile)", "Address", "Email", ""};
void adding()
{
ofstream fout;
fout.open("ContactBook.txt", ios::app);
char inpt[30];
fout << "n";
for (int i = 0; i < 4; i++)
{
cin.getline(inpt, 30);
cout << details[i] << ": ";
fout << inpt << "n";
}
cin.getline(inpt, 30);
fout << inpt;
}
void listing()
{
ifstream fin;
fin.open("ContactBook.txt", ios::in);
char inpt[30];
int i = 0;
while (fin)
{
fin.getline(inpt, 30);
if (i != 4)
cout << details[i] << " : " << inpt << endl;
else
cout << details[i] << inpt << endl;
i++;
if (i == 5)
i = 0;
}
}
void searching()
{
string name;
cout << "Enter name whose contact is to be searched: ";
getline(cin >> ws, name);
ifstream fin;
fin.open("ContactBook.txt", ios::in);
string inpt;
int c = 0;
while (fin)
{
getline(fin >> ws, inpt);
if (inpt == name)
{
c++;
for (int i = 0; i < 4; i++)
{
cout << details[i] << ": " << inpt << endl;
getline(fin >> ws, inpt);
}
}
if (c > 0)
break;
}
}
void editing()
{
string name;
cout << "Enter name whose contact is to be Edited: ";
getline(cin >> ws, name);
ifstream fin;
ofstream fout;
fin.open("ContactBook.txt", ios::in);
fout.open("ContactBookTemporary.txt", ios::out | ios::trunc);
string inpt;
int b = 0;
int c = 0;
while (!fin.eof())
{
getline(fin >> ws, inpt);
b++;
if (inpt == name)
{
c++;
cout << "Enter new details: n";
for (int i = 0; i < 4; i++)
{
string newdetail;
cout << "New " << details[i] << ": ";
getline(cin >> ws, newdetail);
b++;
fout << newdetail << "n";
}
for (int i = 0; i <= 3; i++, b++)
getline(fin >> ws, inpt);
fout << "n"
<< inpt << "n";
}
else
{
if (fin.eof() != 1)
fout << inpt << "n";
else
fout << inpt;
if (b % 4 == 0 && fin.eof() != 1)
fout << "n";
}
}
}
void deleting()
{
string name;
cout << "Enter name whose contact is to be Deleted: ";
getline(cin >> ws, name);
ifstream fin;
ofstream fout;
fin.open("ContactBook.txt", ios::in);
fout.open("ContactBookTemporary.txt", ios::out | ios::trunc);
string inpt;
int b = 0;
int c = 0;
while (!fin.eof())
{
getline(fin >> ws, inpt);
b++;
if (inpt == name)
c++;
else
{
if (c >= 1 && c <= 3)
c++;
else
{
if (fin.eof() != 1)
fout << inpt << "n";
else
fout << inpt;
if (b % 4 == 0 && fin.eof() != 1)
fout << "n";
}
}
}
}
void temporary_to_original()
{
ofstream fout1;
ifstream fin1;
fout1.open("ContactBook.txt", ios::out | ios::trunc);
fin1.open("ContactBookTemporary.txt", ios::in);
char reading[30];
while (!fin1.eof())
{
fin1.getline(reading, 30);
if (fin1.eof() == 0)
fout1 << reading << "n";
else
fout1 << reading;
}
}
void exiting()
{
cout << "nnThank You For Using Contact Management Systemnn";
exit(0);
}
};
int main()
{
Contact object;
cout << "nttttt**** Welcome to Contacts Manager Application ****" << endl;
cout << "INSTRUCTION: YOU CAN ONLY VIEW/SEARCH FOR A CONTACT IF YOU ARE A USER. TO EDIT, DELETE AN EXISTING CONTACT OR ADD ANY NEW CONTACT, SIGN IN AS ADMINISTRATOR." << endl;
block:
cout << "nSelect your identity(1/2)n[1]USERn[2]ADMINnEnter the choice:";
int identity;
int flag = 0;
int flag1 = 0;
cin >> identity;
if (identity == 2)
{
char pass[5];
cout << "nnEnter Admin 5 digits Passcode: ";
for (int i = 0; i < 5; i++)
{
cin >> pass[i];
}
ifstream fin_pass("password.txt");
char corr_pass;
for (int i = 0; i < 5; i++)
{
fin_pass.get(corr_pass);
if (pass[i] != corr_pass)
flag1++;
}
if (flag1 == 0)
cout << "nnWELCOME ADMINnn";
else
{
identity = 1;
cout << "WRONG PASSCODE, YOU ARE SIGNED IN AS USER ONLYnnnWELCOME USERnn";
}
}
else
cout << "nnWELCOME USERnn";
while (1)
{
cout << "nnttttttMAIN MENUnttttt=====================nttttt[1] Add a new Contactnttttt[2] List all Contactsnttttt[3] Search for contactnttttt[4] Edit a Contactnttttt[5] Delete a Contactnttttt[0] Exitnttttt=================ntt";
cout << "tttEnter the choice:";
int op;
cin >> op;
switch (op)
{
case 1:
{
if (identity == 1)
{
cout << "nnSign in as Admin to add a new contact.nn";
flag++;
}
else
{
object.adding();
cout << "nSuccessfully Added.n";
}
break;
}
case 2:
{
object.listing();
break;
}
case 3:
{
object.searching();
break;
}
case 4:
{
if (identity == 1)
{
cout << "nnSign in as Admin to add a new contact.nn";
flag++;
}
else
{
object.editing();
object.temporary_to_original();
cout << "nSuccessfully Edited.n";
}
break;
}
case 5:
{
if (identity == 1)
{
cout << "nnSign in as Admin to add a new contact.nn";
flag++;
}
else
{
object.deleting();
object.temporary_to_original();
cout << "nSuccessfully Deleted.n";
}
break;
}
case 0:
{
object.exiting();
}
default:
cout << "nnInvalid choice. Try againnn";
}
if (flag == 1)
{
flag = 0;
goto block;
}
}
return 0;
}

问题来自于您输入密码的方式。

您使用以下代码:

for (int i = 0; i < 5; i++)
{
cin >> pass[i];
}

这将读取12345,但不会吸收按enter键提交的换行符。它仍然留在输入流中。

因此,如果您下一次在adding函数中添加联系人,您会遇到以下代码。。。

for (int i = 0; i < 4; i++)
{
cin.getline(inpt, 30);
cout << details[i] << ": ";
fout << inpt << "n";
}

发生的第一件事是第一个cin.getline将返回空输入,因为输入流中剩下的下一件事是读取密码时留下的换行符。

要修复此问题,我建议您使用getline命令读取密码,就像您在其他地方所做的那样。

编辑:进一步澄清

这是一个可怕的模式:

getline(cin >> ws, name);

当您将字符串读入变量时,控制台会等待,直到您按下回车键,然后开始处理流。不过,换行符保留在流中。

要修复

我强烈建议您编写用户输入函数并在任何地方使用它们。

string getUserEnteredString();
int getUserEnteredInt();

以下是实现。(两者都一样。稍后,您将了解C++模板,只需编写一次,但对于您来说,由于您是初学者,我将复制它们。(

string getUserEnteredString() {
string result;
cin >> result;
cin.ignore(1000, 'n');
return result;
}
int getUserEnteredInt() {
int result;
cin >> result;
cin.ignore(1000, 'n');
return result;
}

然后,无论你在哪里都有这种模式:

string name;
cout << "Prompt: ";
getline(cin >> ws, name);

替换为:

cout << "Prompt: ";
string name = getUserEnteredName();

类似地,在菜单中输入一个数字:

cout << "tttEnter the choice:";
int op;
cin >> op;

改为写入:

cout << "tttEnter the choice:";
int op = getUserEnteredInt();

对于密码,您有一段危险的代码,其中您只将5个字符分配给名为pass的密码字符数组。我可以考虑做出的仍然适合你能力水平的最小改变是:

cout << "nnEnter Admin 5 digits Passcode: ";
string pass = getUserEnteredString();
ifstream fin_pass("password.txt");
string corr_pass;
getline(fin_pass, corr_pass);
if (pass != corr_pass) flag1 = 1;

它并不完美,但它更好。

最新更新