从ifstream多次读取(Reading from ifstream multiple times)
抱歉,如果这是一个非常简单的问题,但我对C ++很新,而且我正在处理我正在研究的项目。
该项目的一部分涉及将对象的信息写入.txt文件,并能够读取该.txt文件以加载到对象中。 (在这种情况下,信息是写入而不是对象本身,以便有人可以轻松编辑.txt来更改对象)。
我正在调用从.txt文件中读取的函数如下:
void Room::load(ifstream& inFile) { string garbage; string str; inFile >> garbage >> garbage >> mId; inFile >> garbage; getline(inFile, mName); inFile >> garbage; getline(inFile, mDesc); loadVec(garbage, inFile, mExits); }
“垃圾”用于摆脱.txt中的描述符以帮助用户。
典型的房间对象应如下所示:
Room ID: 2 Name: Foyer Description: The player can enter here from the kitchen. Exits: 3 4
我尝试加载多个房间时出现问题。 第一个房间将完美加载,但任何后续房间将无法正确加载。
我至少会期望它以这样的方式失败,因为.txt文件中的第一个房间被重复加载但事实并非如此。
我非常感谢任何人可以提供的任何帮助,谢谢你提前。
编辑:现在我正在使用以下代码加载房间:
if (inFile) { //Assign data to objects room0.load(inFile); room1.load(inFile); }
在这种情况下,room0将使用.txt文件中第一个房间的数据结束,但room1保持不变,但出于某种原因清除其出口除外。
此刻测试程序给出以下内容:
BEFORE LOAD ID= -1 NAME= Nowhere DESC= There's nothing here. Exits= -1 ID= -1 NAME= Nowhere DESC= There's nothing here. Exits= -1 AFTER LOAD ID= 1 NAME= Kitchen DESC= This is the first room the player will see. Exits= 2 3 5 6 ID= -1 NAME= Nowhere DESC= There's nothing here. Exits= Press any key to continue . . .
这些房间分别在加载前后分别为room0和room1。
这是loadVec函数的样子:
//Loads consecutive integers from inFile, saving them to vec void loadVec(string& garbage, ifstream& inFile, vector<int>& vec) { int num; vec.clear(); inFile >> garbage >> num; vec.push_back(num); while (inFile) { inFile >> num; vec.push_back(num); } vec.erase(vec.begin() + vec.size() - 1); }
以及应该加载程序的未编辑的.txt文件:
Room ID: 1 Name: Kitchen Description: This is the first room the player will see. Exits: 2 3 5 6 Room ID: 2 Name: Foyer Description: The player can enter here from the kitchen, they can exit to the rooms with the IDs listed as 'Exits'. Exits: 3 4 Room ID: 3 Name: Bathroom Description: This is the third room. Exits: 4
Apologies if this is a really simple question but I'm fairly new to C++ and I'm having trouble with a project I'm working on.
Part of this project involves writing the information of an object to a .txt file and being able to read that .txt file to load in an object. (In this case the information is written rather than the object itself so that someone can easily edit the .txt to change an object).
The function I'm calling to read from the .txt file is as follows:
void Room::load(ifstream& inFile) { string garbage; string str; inFile >> garbage >> garbage >> mId; inFile >> garbage; getline(inFile, mName); inFile >> garbage; getline(inFile, mDesc); loadVec(garbage, inFile, mExits); }
"garbage" being used to get rid of descriptors in the .txt to help a user.
A typical room object should look something like the following:
Room ID: 2 Name: Foyer Description: The player can enter here from the kitchen. Exits: 3 4
My problem occurs when I try to load multiple Rooms. The first Room will load perfectly but any subsequent Room will fail to load properly.
I would have at least expected it to fail in such a way as the first room in the .txt file is loaded repeatedly but that isn't the case.
I'd be very grateful for any help anyone could offer, thanks in advance.
Edit: For now I'm loading rooms using the following code:
if (inFile) { //Assign data to objects room0.load(inFile); room1.load(inFile); }
In this case, room0 winds up with the data of the first room in the .txt file but room1 remains unchanged with the exception of having its exits cleared for some reason.
Testing the program at the moment gives the following:
BEFORE LOAD ID= -1 NAME= Nowhere DESC= There's nothing here. Exits= -1 ID= -1 NAME= Nowhere DESC= There's nothing here. Exits= -1 AFTER LOAD ID= 1 NAME= Kitchen DESC= This is the first room the player will see. Exits= 2 3 5 6 ID= -1 NAME= Nowhere DESC= There's nothing here. Exits= Press any key to continue . . .
Those rooms being room0 and room1 respectively both before and after load.
Here's what the loadVec function looks like:
//Loads consecutive integers from inFile, saving them to vec void loadVec(string& garbage, ifstream& inFile, vector<int>& vec) { int num; vec.clear(); inFile >> garbage >> num; vec.push_back(num); while (inFile) { inFile >> num; vec.push_back(num); } vec.erase(vec.begin() + vec.size() - 1); }
And the unedited .txt file from which the program should be loading:
Room ID: 1 Name: Kitchen Description: This is the first room the player will see. Exits: 2 3 5 6 Room ID: 2 Name: Foyer Description: The player can enter here from the kitchen, they can exit to the rooms with the IDs listed as 'Exits'. Exits: 3 4 Room ID: 3 Name: Bathroom Description: This is the third room. Exits: 4
原文:https://stackoverflow.com/questions/20237164
最满意答案
这里的问题正如其他解释的那样,int对象是不可变的
two[0][0] = 9
不会改变旧的两个[0] [0]对象,而是会创建新对象,并使两个[0] [0]引用这个新对象(旧对象是垃圾收集,如果没有其他参考它在这种情况下有)
并且在创建两个数组之后在这种情况下更清楚我们有以下( - >表示引用)
one[0][0] --> object(1) two[0][0] --> object(1)
然后当你出手
two[0][0] = 9
对象引用看起来像这样
one[0][0] --> object(1) two[0][0] --> object(9)
因此,为了解决这个问题,我们需要将数组中的值更改为可变
我创建了一个非常简单的类,它保存int并使数组从中解决,这解决了你的问题
这是工作代码
class IntHolder: def __init__(self,int_value): self.intvalue = int_value def set_value(self,int_value): self.intvalue = int_value def __str__(self): return str(self.intvalue) def __repr__(self): return str(self.intvalue) def __str__(self): return str(self.intvalue) one = [ [IntHolder(1), IntHolder(2), IntHolder(3), IntHolder(4)], [IntHolder(2), IntHolder(3), IntHolder(4), IntHolder(5)], [IntHolder(3), IntHolder(4), IntHolder(5), IntHolder(6)], [IntHolder(4), IntHolder(5), IntHolder(6), IntHolder(7)] ] two = [ [one[0][0], one[0][1], one[1][0], one[1][1]], [one[0][2], one[0][3], one[1][2], one[1][3]], [one[2][0], one[2][1], one[3][0], one[3][1]], [one[2][2], one[2][3], one[3][2], one[3][3]] ] two[0][0].set_value(9) print one print two
the issue here as other explained is that int objects are immutable So doing
two[0][0] = 9
wont change the old two[0][0] object instead it will create new object and make two[0][0] reference this new object (the old object is garbage collected if not other reference it in this case there is)
and to be more clear in this case after creating both arrays we have the following (--> means reference)
one[0][0] --> object(1) two[0][0] --> object(1)
then when you excuted
two[0][0] = 9
the object reference looks like this
one[0][0] --> object(1) two[0][0] --> object(9)
So to solve this we need to change the values that you have in the array to be mutable
I have created very simple class that hold the int and made the array out of it and that resolves your issue
here is working code
class IntHolder: def __init__(self,int_value): self.intvalue = int_value def set_value(self,int_value): self.intvalue = int_value def __str__(self): return str(self.intvalue) def __repr__(self): return str(self.intvalue) def __str__(self): return str(self.intvalue) one = [ [IntHolder(1), IntHolder(2), IntHolder(3), IntHolder(4)], [IntHolder(2), IntHolder(3), IntHolder(4), IntHolder(5)], [IntHolder(3), IntHolder(4), IntHolder(5), IntHolder(6)], [IntHolder(4), IntHolder(5), IntHolder(6), IntHolder(7)] ] two = [ [one[0][0], one[0][1], one[1][0], one[1][1]], [one[0][2], one[0][3], one[1][2], one[1][3]], [one[2][0], one[2][1], one[3][0], one[3][1]], [one[2][2], one[2][3], one[3][2], one[3][3]] ] two[0][0].set_value(9) print one print two
相关问答
更多-
下列中不属于面向对象的编程语言的是?[2022-05-30]
a -
它不漂亮,但它的工作原理: record = [['g1','g2','g3'],['g2','g4'],['g1','g3','g5'],['g2','g3','g5'],['g1','g4']] pattern = [('g1','g2'),('g1','g3'),('g1','g4'),('g1','g5'),('g2','g3'),('g2','g4'),('g2','g5'),('g3','g4'),('g3','g5'),('g4','g5')] res = {} for p in patte ...
-
哈桑在一般情况下是正确的,但如果你经常寻找这种切片我会建议你开始使用numpy,这是真的为这种事情做的。 特别: >>> import numpy as np >>> my_array = np.array([[2, 0.84], [2, 0.75], [2, 0.63], [2, 0.6]]) >>> my_array[:, 1] [0.84, 0.75, 0.63, 0.6] 就个人而言,我发现numpy切片更容易使用,它似乎与你对上述问题的直觉非常吻合。 而且,对于大型阵列,它可能会更快。 也就是 ...
-
something = min((x for x in list1 if isinstance(x[2], float)), key=lambda x: x[2]) 顺便说一句,恕我直言,这种情况下最适合的数据结构将是一个tuple list ,因为它们构成固定大小的异构集合(在这种情况下为三元组),如下所示: list1 = [(1, 0, 2.83), (3, 1, 1.0), (5, 4, 2.83), (7, 0, 4.47), (6, 5, 4.24), (3, 2, 'x')] someth ...
-
很多方法都可以做到这一点 这是一个简单的列表方式,没有明确的for循环。 tt = [[50.954818803035948, 55.49664787231189, 8007927.0, 0.0], [50.630482185654436, 55.133473852776916, 8547795.0, 0.0], [51.32738085400576, 55.118344981379266, 6600841.0, 0.0], [49.425931642638567, 55.312890225131163, ...
-
这里的问题正如其他解释的那样,int对象是不可变的 two[0][0] = 9 不会改变旧的两个[0] [0]对象,而是会创建新对象,并使两个[0] [0]引用这个新对象(旧对象是垃圾收集,如果没有其他参考它在这种情况下有) 并且在创建两个数组之后在这种情况下更清楚我们有以下( - >表示引用) one[0][0] --> object(1) two[0][0] --> object(1) 然后当你出手 two[0][0] = 9 对象引用看起来像这样 one[0][0] --> object(1) ...
-
import math squares = [pow(i,2) for i in range(1,6)] logs = map(math.log10,range(1,6)) mult = lambda x,y: x*y lmultl = map(mult,squares,logs) 我假设你的squares中的元素是i_1,i_2,i_3 ...... logs中的元素是j_1,j_2,j_3 ...... 并且您想要创建一个列表,将每个squares元素与每个logs元素相乘,其中包含[[i_1 * ...
-
这可能有所帮助。 a = [["a","b","c"],["d","e","f"]] b = [["g","h","i"],["k","l","m"],["n","o","c"]] check = [i[2] for i in a] print([i for i in b if i[2] not in check]) 输出 : [['g', 'h', 'i'], ['k', 'l', 'm']] This might help. a = [["a","b","c"],["d","e","f"]] ...
-
只需返回修改后的obj而不是重新创建列表。 standardize = function(obj){ obj$x <- obj$x / max(obj$x) obj } 额外奖励:现在保留了obj元素的名称。 Simply return the modified obj instead of re-creating a list. standardize = function(obj){ obj$x <- obj$x / max(obj$x) obj } Bonus: the names ...
-
由于这两个向量是 - 并且显然需要保留! - 分开,这是一个很好的旧DSU的案例 - 装饰,排序,undecorate。 result = [t for v, t in sorted(zip(value_vector, time_vector), key=lambda vt: vt[0][-1])] 在大多数情况下,添加key= arg几乎不需要理解DSU - 它为你做装饰(只要它只是每个项目的功能)和排序后的未装饰。 但是在这里,排序键不仅仅是项目的一个功能 - 它是项目在列表中的位 ...