有一个二进制文件,其中包含这样的数据(这两个文件都有字符串数据类型);
Tyler Bred
Guus Hiddink
Didier Droggba
我想读取位于文件末尾的数据(在这种情况下,确切地说是Didier& Droggba)。所以我写了一个代码来处理它如下;
结构:
struct user
{
string id;
string pwd;
};
读取数据的代码:
void confirm(const char* f)
{
user u;
ifstream in;
in.open(f, ios::in | ios::binary);
if (!in)
{
cout << "failed to read file!" << endl;
exit(0);
}
while (in >> u.id >> u.pwd)
{
if (in.eof())
{
cout << "Registration Complete. " << endl;
cout << "Your user information: " << endl;
cout << "ID:" << u.id << " " << "Password: " << u.pwd << endl;
}
}
}
我运行上面的代码,但它没有用。我什么都没有。 所以我改变了这样的代码;
void confirm(const char* f,user* u)
{
user u1;
ifstream in;
in.open(f, ios::in | ios::binary);
while (in >> u1.id >> u1.pwd)
{
if (!in)
{
cout << "failed to open file" << endl;
exit(0);
}
if((u1.id == u->id)&& (u1.pwd == u->pwd))
{
cout << "Registration Complete." << endl;
cout << "You registered;" << endl;
cout << "ID:" << u1.id << "," << "Pwd: " << u1.pwd << endl;
}
delete u;
}
}
不幸的是,这不起作用。我有“访问冲突...”错误信息。
我尝试了许多其他代码来解决问题,但这些事情也没有用。我认为问题是:if(in.eof()) 但我不知道如何改变它来解决问题。 如果有人指出我的错误或给我一个提示,我会非常感激。
答案 0 :(得分:1)
在文件的每一行末尾通常都有换行符(或某些操作系统上的字符***)。你的代码......
ArrayList<String> listcountry_id,listcountry;
listcountry_id=new ArrayList<String>();
listcountry=new ArrayList<String>();
try {
JSONArray jarr=new JSONArray("your responce data here");
for(int i=0;i<jarr.length();i++){
JSONObject jobj=jarr.getJSONObject(i);
listcountry_id.add(jobj.getString("country_id"));
listcountry.add(jobj.getString("country"));
}
BindSpinnerData();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
spnData.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
// TODO Auto-generated method stub
String ids = String.valueOf(position);
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
private void BindSpinnerData() {
// TODO Auto-generated method stub
ArrayAdapter<String> spinnerLocation = new ArrayAdapter<String>(
getApplicationContext(), R.layout.spinneritem, listcountry);
spinnerLocation.setDropDownViewResource(R.layout.spinnerpopup);
spnData.setAdapter(spinnerLocation);
}
假设您在阅读完最后一个人的姓名后点击while (in >> u.id >> u.pwd)
{
if (in.eof())
{
cout << "Registration Complete. " << endl;
cout << "Your user information: " << endl;
cout << "ID:" << u.id << " " << "Password: " << u.pwd << endl;
}
}
,但是当您读到该姓氏时,如果该行有换行符,则您还没有点击eof
,那么下一个eof()
测试将失败并跳过while (in >>...
- 循环体,从不输入while
。
您可以修改代码的最小更改:
if (in.eof())
while (in >> u.id >> u.pwd >> std::skipws)
{
if (in.eof())
{
cout << "Registration Complete. " << endl;
cout << "Your user information: " << endl;
cout << "ID:" << u.id << " " << "Password: " << u.pwd << endl;
}
}
将前进到文件末尾或下一个名称,按照您的意愿设置>> std::skipws
标记。
答案 1 :(得分:1)
一种可能性是这样的:
void confirm(const char* f)
{
user u;
ifstream in(f, ios::in | ios::binary);
while (in >> u.id >> u.pwd)
;
cout << "Registration Complete.\n";
cout << "Your user information:\n";
cout << "ID:" << u.id << " " << "Password: " << u.pwd << "\n";
}
但是,如果我这样做,我会为operator>>
结构定义user
,如下所示:
struct user {
std::string id;
std::string pwd;
friend std::istream &operator>>(std::istream &is, user &u) {
return is >> u.id >> u.pwd;
}
};
这简化了主要代码,如下所示:
user u;
while (in >> u)
;
不可否认,在这种情况下(只有两个字段)只是一个小小的改进,但它仍然是一个很小的改进,当你有更多的字段需要处理时(特别是当代码读取时)对象变得更复杂)隔离代码以将对象读入其自己的函数可以简化代码的其余部分。
请注意,无论在最后一个数据之后文件中有多少或者很少的空白区域(尾随\ n或缺少空格都不会影响结果),这都可以正常工作。
答案 2 :(得分:1)
除了作为约定之外,二进制文件中不存在行,就像一行是一个字节序列(所有不同于'\0'
和来自'\n'
)终止通过换行符'\n'
(该约定可能因操作系统与下一个操作系统而异,某些操作系统使用"\r\n"
或"\n\r"
甚至'\r'
作为行结尾。)< / p>
您可以使用std::getline
循环读取行直到文件结尾,将行保留在某个std::string
中并解析最后一行字符串(使用std::istringstream,sscanf,等...)
或者,将行尾视为空格分隔符,如Tony D'answer所示。然后,带有Tyler Bred John Doe
的单行将被处理为两行Tyler Bred
和John Doe
。
答案 3 :(得分:0)
delete u
这将释放与user
结构相关的内存。如果文件中有多行,则会出现访问冲突,因为在下一次迭代中,您将再次触摸与user
结构相关联的内存。
还有:
in.open(f, ios::in | ios::binary);
if (!in)
{
cout << "failed to read file!" << endl;
exit(0);
}
是测试文件是否成功打开的正确方法。 此外,您还需要在每次阅读中处理换行符。
我假设您在找到第一场比赛后想要摆脱困境。你应该修改你的代码:
if((u1.id == u->id)&& (u1.pwd == u->pwd))
{
cout << "Registration Complete." << endl;
cout << "You registered;" << endl;
cout << "ID:" << u1.id << "," << "Pwd: " << u1.pwd << endl;
delete u;
break;
}
虽然我不喜欢这种模式,被调用者负责释放内存。我建议让调用者决定如何处理user
结构中传递的内存。
作为使用调试器的附加建议可以帮助您诊断此类问题。