这是我的功能:
void Gladiator::display()
{
cout << name << ":\nHealth: " << curHealth << '/' << maxHealth <<
"\nEvasion: " << evasion << "\nCritical: " << critical <<
"\nDamage: " << dmgMin << '-' << dmgMin + dmgRange + 1 << "\n\n";
}
我需要语法帮助来显示上述函数的统计信息,并且我为蓝队和红队创建角斗士向量的语法是否正确?非常感谢。
cout << "A battle will soon commence... First the Teams must be created." << endl;
vector<Gladiator> redTeam; // is the syntax correct for this one too?
vector<Gladiator> blueTeam;
cout << "Red Team's Stats: " << endl;
Gladiator.display(redTeam); //this is the part where I don't know the syntax of displaying the stats for redTeam vector.
cout << "Blue Team's Stats: " << endl;
blueTeam.display(); //syntax for this is wrong too.
答案 0 :(得分:1)
您有一个误解。函数from ibapi.wrapper import EWrapper
from ibapi.client import EClient
from ibapi.contract import Contract as IBcontract
from threading import Thread
import queue
import datetime
DEFAULT_HISTORIC_DATA_ID=50
DEFAULT_GET_CONTRACT_ID=43
## marker for when queue is finished
FINISHED = object()
STARTED = object()
TIME_OUT = object()
class finishableQueue(object):
def __init__(self, queue_to_finish):
self._queue = queue_to_finish
self.status = STARTED
def get(self, timeout):
"""
Returns a list of queue elements once timeout is finished, or a FINISHED flag is received in the queue
:param timeout: how long to wait before giving up
:return: list of queue elements
"""
contents_of_queue=[]
finished=False
while not finished:
try:
current_element = self._queue.get(timeout=timeout)
if current_element is FINISHED:
finished = True
self.status = FINISHED
else:
contents_of_queue.append(current_element)
## keep going and try and get more data
except queue.Empty:
## If we hit a time out it's most probable we're not getting a finished element any time soon
## give up and return what we have
finished = True
self.status = TIME_OUT
return contents_of_queue
def timed_out(self):
return self.status is TIME_OUT
class TestWrapper(EWrapper):
"""
The wrapper deals with the action coming back from the IB gateway or TWS instance
We override methods in EWrapper that will get called when this action happens, like currentTime
Extra methods are added as we need to store the results in this object
"""
def __init__(self):
self._my_contract_details = {}
self._my_historic_data_dict = {}
self._my_errors = queue.Queue()
## error handling code
def init_error(self):
error_queue=queue.Queue()
self._my_errors = error_queue
def get_error(self, timeout=5):
if self.is_error():
try:
return self._my_errors.get(timeout=timeout)
except queue.Empty:
return None
return None
def is_error(self):
an_error_if=not self._my_errors.empty()
return an_error_if
def error(self, id, errorCode, errorString):
## Overriden method
errormsg = "IB error id %d errorcode %d string %s" % (id, errorCode, errorString)
self._my_errors.put(errormsg)
## get contract details code
def init_contractdetails(self, reqId):
contract_details_queue = self._my_contract_details[reqId] = queue.Queue()
return contract_details_queue
def contractDetails(self, reqId, contractDetails):
## overridden method
if reqId not in self._my_contract_details.keys():
self.init_contractdetails(reqId)
self._my_contract_details[reqId].put(contractDetails)
def contractDetailsEnd(self, reqId):
## overriden method
if reqId not in self._my_contract_details.keys():
self.init_contractdetails(reqId)
self._my_contract_details[reqId].put(FINISHED)
## Historic data code
def init_historicprices(self, tickerid):
historic_data_queue = self._my_historic_data_dict[tickerid] = queue.Queue()
return historic_data_queue
def historicalData(self, tickerid , bar):
## Overriden method
## Note I'm choosing to ignore barCount, WAP and hasGaps but you could use them if you like
bardata=(bar.date, bar.open, bar.high, bar.low, bar.close, bar.volume)
historic_data_dict=self._my_historic_data_dict
## Add on to the current data
if tickerid not in historic_data_dict.keys():
self.init_historicprices(tickerid)
historic_data_dict[tickerid].put(bardata)
def historicalDataEnd(self, tickerid, start:str, end:str):
## overriden method
if tickerid not in self._my_historic_data_dict.keys():
self.init_historicprices(tickerid)
self._my_historic_data_dict[tickerid].put(FINISHED)
class TestClient(EClient):
"""
The client method
We don't override native methods, but instead call them from our own wrappers
"""
def __init__(self, wrapper):
## Set up with a wrapper inside
EClient.__init__(self, wrapper)
def resolve_ib_contract(self, ibcontract, reqId=DEFAULT_GET_CONTRACT_ID):
"""
From a partially formed contract, returns a fully fledged version
:returns fully resolved IB contract
"""
## Make a place to store the data we're going to return
contract_details_queue = finishableQueue(self.init_contractdetails(reqId))
print("Getting full contract details from the server... ")
self.reqContractDetails(reqId, ibcontract)
## Run until we get a valid contract(s) or get bored waiting
MAX_WAIT_SECONDS = 10
new_contract_details = contract_details_queue.get(timeout = MAX_WAIT_SECONDS)
while self.wrapper.is_error():
print(self.get_error())
if contract_details_queue.timed_out():
print("Exceeded maximum wait for wrapper to confirm finished - seems to be normal behaviour")
if len(new_contract_details)==0:
print("Failed to get additional contract details: returning unresolved contract")
return ibcontract
if len(new_contract_details)>1:
print("got multiple contracts using first one")
new_contract_details=new_contract_details[0]
resolved_ibcontract=new_contract_details.contract
return resolved_ibcontract
def get_IB_historical_data(self, ibcontract, durationStr="1 Y", barSizeSetting="1 day",
tickerid=DEFAULT_HISTORIC_DATA_ID):
"""
Returns historical prices for a contract, up to today
ibcontract is a Contract
:returns list of prices in 4 tuples: Open high low close volume
"""
## Make a place to store the data we're going to return
historic_data_queue = finishableQueue(self.init_historicprices(tickerid))
# Request some historical data. Native method in EClient
self.reqHistoricalData(
tickerid, # tickerId,
ibcontract, # contract,
datetime.datetime.today().strftime("%Y%m%d %H:%M:%S %Z"), # endDateTime,
durationStr, # durationStr,
barSizeSetting, # barSizeSetting,
"TRADES", # whatToShow,
1, # useRTH,
1, # formatDate
False, # KeepUpToDate <<==== added for api 9.73.2
[] ## chartoptions not used
)
## Wait until we get a completed data, an error, or get bored waiting
MAX_WAIT_SECONDS = 10
print("Getting historical data from the server... could take %d seconds to complete " % MAX_WAIT_SECONDS)
historic_data = historic_data_queue.get(timeout = MAX_WAIT_SECONDS)
while self.wrapper.is_error():
print(self.get_error())
if historic_data_queue.timed_out():
print("Exceeded maximum wait for wrapper to confirm finished - seems to be normal behaviour")
self.cancelHistoricalData(tickerid)
return historic_data
class TestApp(TestWrapper, TestClient):
def __init__(self, ipaddress, portid, clientid):
TestWrapper.__init__(self)
TestClient.__init__(self, wrapper=self)
self.connect(ipaddress, portid, clientid)
thread = Thread(target = self.run)
thread.start()
setattr(self, "_thread", thread)
self.init_error()
#if __name__ == '__main__':
app = TestApp("127.0.0.1", 4001, 1)
ibcontract = IBcontract()
ibcontract.secType = "FUT"
ibcontract.lastTradeDateOrContractMonth="201901"
ibcontract.symbol="GE"
ibcontract.exchange="GLOBEX"
resolved_ibcontract=app.resolve_ib_contract(ibcontract)
historic_data = app.get_IB_historical_data(resolved_ibcontract)
print(historic_data)
app.disconnect()
是类Gladiator::Display()
的成员函数。该函数不接受任何参数,因此您不能按原样调用它。
我建议您寻找Gladiator
和function overloading
函数,因为它们将帮助您了解需要做什么。
我将添加一个static
函数static
,如下所示:
Gladiator.h
Galdiator::Display(const std::vector<Gladiator>& team)
Gladiator.cpp
class Gladiator{
public:
//.. your functions
void Display() const; // PLEASE ADD TRAILING const TO ALLOW THIS FUNCTION TO BE CALLED ON const Gladiator objects.
static void Display(const std::vector<Gladiator>& team);
private:
// data
}
然后您可以将其称为:
static void Gladiator::Display(const std::vector<Gladiator>& team){
for(auto& glad : team)
glad.Display();
}
请注意,不可能像在 Gladiator::Display(redTeam); // or blueTeam
中那样拥有extension methods
,在那里您可以使用静态类扩展现有的类。因此,无法调用:
C#
由于blueTeam.Display();
是blueTeam
,不包含函数std::vector
。
但是,您可以使用流操作符重载和重载Display()
来使其变通,使其接受std::ostream
并显示它,以解决此问题。我不建议您对此进行深入研究,因为问题表明某些基础知识不足。
无论如何,
std::vector<Gladiator>
如果存在vector<Gladiator> redTeam;
的默认构造函数,则完全有效。如果您想给它一个尺寸,可以使用:
Gladiator
这将创建一个带有int n = 10; // number of gladiators per team
vector<Gladiator> redTeam(n);
角斗士的向量。请注意,仅当类10
具有默认构造函数Gladiator
时,这才有效。如果您创建了另一个构造函数,则默认构造函数将不会由编译器自动生成。
希望这会有所帮助。
答案 1 :(得分:0)
首先,尽管语法有效,但此处的向量为空:
vector<Gladiator> redTeam;
因此,您需要在显示任何内容之前向该矢量添加元素。
有关该主题的更多信息,请参见std::vector::push_back。
语法错误:
Gladiator.display(redTeam);
display
函数不接受任何参数。您打算做的是(假设您向向量添加了一些元素):
for (const auto& elm : redTeam) {
elm.display();
}
在这里,我们在向量中的每个元素上调用display
方法。
有关该主题的更多信息,请参见Range-based for loop。
答案 2 :(得分:0)
关于Gladiator.display(redTeam);
:否,display
不接受参数,也不接受参数。该功能可以显示一个Gladiator
的统计信息,并且理想情况下,对于角斗士要战斗的团队应该是不可知的。
相反,创建一个Team
类来保存角斗士的向量,并向其中添加一个display
成员函数,该成员函数将循环所有角斗士并调用其display
函数。
struct Team {
void display() const {
for(const Gladiator& g : gladiators) {
g.display();
}
}
};
Team
类也将在您以后想要添加与另一个团队战斗的功能时派上用场。然后,Fight
类中的Team
函数将在其所包含的角斗士中调用Fight
函数。
display
的两个函数都可以做成流运算符,以使与标准流的集成变得不明显,因此您可以这样做:
std::cout << a_gladiator; // print stats for one gladiator
std::cout << redteam; // print stats for all gladiators in a team
这是一个示例,其中我用流运算符替换了display
函数,并且由于随机性可能是战斗中的很大一部分,因此我还添加了<random>
库的示例用法,在两个类中如何实现Fight
函数的示例。
#include <iostream>
#include <vector>
#include <random>
// "prng" will be the pseudo random number generator when fighting
// https://en.cppreference.com/w/cpp/header/random
std::random_device rd;
std::mt19937 prng(rd());
enum Result { r_loss=-1, r_draw=0, r_win=1};
Result win_or_loss(int h, int a) {
int r = h-a;
return (r==0) ? r_draw : (r>0?r_win:r_loss);
}
//-----------------------------------------------------------------------------
struct Gladiator {
std::string name;
int maxHealth;
int curHealth;
int evasion;
int critical;
// "damage" will hold the min and max values of damage
// and can be used with a pseudo random number generator
// to get the value of one strike that the Gladiator
// delivers
std::uniform_int_distribution<int> damage;
Gladiator(const std::string& Name, int MaxHealth, int Evasion,
int Critical, int DmgMin, int DmgRange) :
name(Name),
maxHealth(MaxHealth),
curHealth(maxHealth),
evasion(Evasion),
critical(Critical),
damage(DmgMin, DmgMin+DmgRange) // initialize with DmgMin and DmgRange
{}
// return r_win if this gladiator wins or r_loss if the opponent wins
// or r_draw if it's a draw
Result Fight(Gladiator& opponent) {
// perhaps reset health here, or at the end of the fight
curHealth = maxHealth;
opponent.curHealth = opponent.maxHealth;
std::cout << " The fight between " << name << " and " << opponent.name << " begins!\n";
// fight loop
while( curHealth>0 && opponent.curHealth>0 ) {
// use of evasion & critical must be added
// use the "damage" uniform int distributions with the
// random number generator to get the values for the hits
int my_hit = damage(prng);
int opponents_hit = opponent.damage(prng);
// add cool fight messages
std::cout << " " << name << " hit " << opponent.name << ", doing " << my_hit << " hp damage.\n";
std::cout << " " << opponent.name << " hit " << name << ", doing " << opponents_hit << " hp damage.\n";
curHealth -= opponents_hit;
opponent.curHealth -= my_hit;
}
// figure out who won
Result r = win_or_loss(curHealth, opponent.curHealth);
if(r==r_win) std::cout << " Gladiator " << name << " won!\n";
else if(r==r_loss) std::cout << " Gladiator " << opponent.name << " won!\n";
else std::cout << " It was a draw!\n";
return r;
}
// declare a function (in the form of a stream operator) for streaming
// a gladiator to an output stream, like std::cout
friend std::ostream& operator<<(std::ostream&, const Gladiator&);
};
// definition of the output stream operator for a Gladiator
std::ostream& operator<<(std::ostream& os, const Gladiator& g) {
os << " " << g.name << ":\n Health: " << g.curHealth << '/' << g.maxHealth <<
"\n Evasion: " << g.evasion << "\n Critical: " << g.critical <<
"\n Damage: " << g.damage.min() << '-' << g.damage.max() << "\n\n";
return os;
}
//-----------------------------------------------------------------------------
struct Team {
std::string name;
std::vector<Gladiator> m_gladiators;
Team(const std::string& Name) : Team(Name, {}) {}
Team(const std::string& Name, std::vector<Gladiator>&& gv) :
name(Name),
m_gladiators(std::move(gv))
{}
// return r_win if this team wins or r_loss if the opponent team wins
// or r_draw if it's a draw
Result Fight(Team& opponent) {
unsigned wins=0, losses=0;
std::cout << "Team " << name << " vs. " << opponent.name << "\n";
for(Gladiator& my_gladiator : m_gladiators) {
for(Gladiator& opponent_gladiator : opponent.m_gladiators) {
Result result = my_gladiator.Fight(opponent_gladiator);
if(result>0) {
++wins;
} else if(result<0) {
++losses;
}
}
}
Result r = win_or_loss(wins, losses);
if(r==r_win) std::cout << "Team " << name << " won!\n";
else if(r==r_loss) std::cout << "Team " << opponent.name << " won!\n";
else std::cout << "It was a draw\n";
return r;
}
// Just like for an individal Gladiator, declare a stream operator.
friend std::ostream& operator<<(std::ostream&, const Team&);
};
// stream all gladiators in a Team
std::ostream& operator<<(std::ostream& os, const Team& t) {
os << "Team " << t.name << " stats:\n";
for(const auto& g : t.m_gladiators) {
std::cout << g; // this uses the Gladiator output stream operator
}
return os;
}
//-----------------------------------------------------------------------------
int main() {
std::cout << "A battle will soon commence... First the Teams must be created.\n";
// if you'd like a dynamic amount of teams, you can make a Team vector like this:
std::vector <Team> teams = {
{"Red",
{
{"Spartacus", 100, 25, 27, 10, 17},
{"Crixus", 99, 24, 26, 12, 13}
}
},
{"Blue",
{
{"Commodus", 101, 30, 28, 11, 16},
{"Tetraites", 98, 31, 29, 10, 15}
}
}
};
// print info about all teams
for(const auto& team : teams) std::cout << team;
// let all teams fight
for(auto it_a=teams.begin(); it_a<(teams.end()-1); ++it_a) {
for(auto it_b=it_a+1; it_b<teams.end(); ++it_b) {
(*it_a).Fight(*it_b);
}
}
/*
std::cout << "------\n";
// or if you'd like to treat them separately, you can create
// referenses to the teams:
Team& redTeam = teams[0];
Team& blueTeam = teams[1];
// and use them individually
std::cout << redTeam;
std::cout << blueTeam;
redTeam.Fight(blueTeam);
*/
}
答案 3 :(得分:-1)
std::vector<Gladiator> v = {};
v.push_back(Gladiator());
// Iterate and print values of vector
for(Gladiator g : v) {
g.Display();
}
https://en.cppreference.com/w/cpp/container/vector
有关更多信息,请参见以下内容。