Was wondering if you guys could provide/assist me with concise solutions to determine whether a BTree underflows, and whether or not you could complete a right rotation on it. Bit confused as to the process of arriving at it. Don think it's as easy as just comparing the two unsigned values (particularly for underflow).
BTreeNode.h:
#ifndef BTREENODE_H
#define BTREENODE_H
#include <string>
#include <vector>
struct BTreeNode {
bool is_leaf_ = true;
std::vector<int> elements_;
std::vector<BTreeNode*> children_;
BTreeNode() {}
BTreeNode(std::vector<int> v) {
this->elements_ = v;
}
/**
* Fix the underflow child node at idx by rotating right
* (borrowing a node from left sibling).
* #param idx The underflow child to be fixed is at children_[idx].
* #return If the rotation can be done.
*/
bool rotateRight(unsigned idx, unsigned order);
};
/**
* Check if the given number of elements in a BTree node underflows.
* #param numElem Number of elements in this node.
* #param order The order of the BTree.
* #return True if it underflows, False otherwise.
*/
bool underflows(unsigned numElem, unsigned order);
/**
* A special case for removing an element from BTree. Assume elem
exists in leaf.
* #param item The element to be removed.
* #param parent The parent node that contains the leaf node as a
child.
* #param leaf_idx The leaf BTreeNode idx that contains the element to
be removed.
* #return If the removal is successful.
*/
bool removeFromLeaf(int item, BTreeNode* parent, unsigned leaf_idx,
unsigned order);
#endif
BTreeNode.cpp:
#include "BTreeNode.h"
#include <assert.h>
#include <algorithm>
#include <iostream>
/**
* Check if the given number of elements in a BTree node underflows.
* #param numElem Number of elements in this node.
* #param order The order of the BTree.
* #return True if it underflows, False otherwise.
*/
bool underflows(unsigned numElem, unsigned order) {
return false;
}
/**
* Fix the underflow child node at idx by rotating right
* (borrowing a node from left sibling).
* #param idx The underflow child to be fixed is at children_[idx].
* #return If the rotation can be done.
*/
bool BTreeNode::rotateRight(unsigned idx, unsigned order) {
/**
* First check if there is a left sibling.
* If there is not, simply return false because rotateRight cannot
be done.
*/
if (idx <= 0) return false;
/**
* Then check if the left sibling leaf contains enough elements
after one being borrowed.
*/
BTreeNode* prev = children_[idx - 1];
if (underflows(prev->elements_.size() - 1, order)) {
/**
* If it's not enough, this case cannot be handled by
rotateRight.
* Simply return false.
*/
return false;
}
/**
* Do the right rotation by stealing one element from left sibling
* and fixing the parent key.
*
* Example: Assume we are doing rotateRight around (40) to fix
right child
* (we are in BTreeNode(40), idx = 1 (the second child)),
* | 40 |
* / \
* | 10 | 20 | 30 | | 60 |
*
* after rotation, the tree should look like
* | 30 |
* / \
* | 10 | 20 | | 40 | 50 |
*
*/
// TODO: do the right rotation here
return true;
}
bool removeFromLeaf(int item, BTreeNode* parent, unsigned leaf_idx,
unsigned order) {
// sanity checks
assert(!parent->is_leaf_);
assert(leaf_idx < parent->children_.size());
BTreeNode* leaf = parent->children_[leaf_idx];
assert(leaf->is_leaf_);
std::vector<int>& elems = leaf->elements_;
std::vector<int>::iterator pos = std::find(elems.begin(),
elems.end(), item);
assert(pos != elems.end());
std::cout << "removing " << item << "..." << std::endl;
// delete item, shift other items, shrink the size
elems.erase(pos);
std::cout << "Does the node underflow? ";
// call rotateRight if current leaf node underflows
if (underflows(elems.size(), order)) {
std::cout << "Yes!" << std::endl;
return parent->rotateRight(leaf_idx, order);
}
std::cout << "No!" << std::endl;
return true;
}
Related
I'm trying to use the add method to add elements to a LinkedList. This is what the code looks like:
/**
* A singly linked list.
*
* #author
* #version
*/
public class LinkedList<T> {
private ListElement<T> first; // First element in list.
private ListElement<T> last; // Last element in list.
public LinkedList<T> asd;
private int size; // Number of elements in list.
/**
* A list element.
*/
private static class ListElement<T> {
public T data;
public ListElement<T> next;
public ListElement(T data) {
this.data = data;
this.next = null;
}
}
/**
* This TEST METHOD returns true if the following invariants hold:
* <ul>
* <li> size equals the number of list elements, </li>
* <li> if size == 0, first == null and last == null, </li>
* <li> if size > 0, first != null and last != null, </li>
* <li> if size == 1, first == last, </li>
* <li> last.next == null. </li>
* </ul>
*/
public boolean isHealthy() {
return false;
}
/**
* Creates an empty list.
*/
public LinkedList() {
asd = new LinkedList<T>();
}
/**
* Inserts the given element at the beginning of this list.
*/
public void addFirst(T element) {
asd.add(element);
}
/**
* Inserts the given element at the end of this list.
*/
public void addLast(T element) {
}
/**
* Returns the first element of this list.
* Returns <code>null</code> if the list is empty.
*/
public T getFirst() {
// TODO
return null;
}
/**
* Returns the last element of this list.
* Returns <code>null</code> if the list is empty.
*/
public T getLast() {
return null;
}
/**
* Returns the element at the specified position in this list.
* Returns <code>null</code> if <code>index</code> is out of bounds.
*/
public T get(int index) {
return null;
}
/**
* Removes and returns the first element from this list.
* Returns <code>null</code> if the list is empty.
*/
public T removeFirst() {
return null;
}
/**
* Removes all of the elements from this list.
*/
public void clear() {
}
/**
* Returns the number of elements in this list.
*/
public int size() {
return 0;
}
/**
* Returns <code>true</code> if this list contains no elements.
*/
public boolean isEmpty() {
return false;
}
/**
* Returns a string representation of this list. The string
* representation consists of a list of the elements enclosed in
* square brackets ("[]"). Adjacent elements are separated by the
* characters ", " (comma and space). Elements are converted to
* strings by the method toString() inherited from Object.
*/
public String toString() {
return null;
}
}
The problem is that when I try to compile, it generates a "cannot find symbol - method add(T)" error message. I can't see why it wouldn't work, but I'm new to Java so I'd like some help on this.
Yes, LinkedList has add method but the problem is you are not importing java.util.LinkedList. You are implementing your own LinkedList. So either implement a add method for your class, or you can easily use import java.util.LinkedList without implementation.
i'm trying to compare all leafs to return the lowest value of a tree, I don't have main function just a script to insert values so unfortunately I can't debug it.
tpNoArvore * findLowest(tpNoArvore * pNo){
tpNoArvore * left;
tpNoArvore * right;
tpNoArvore * res;
if (!pNo) return NULL; /* if */
left = findLowest(pNo->pNoL);
right = findLowest(pNo->pNoR);
if(isLeaf(pNo))
return pNo;
} /* if */
if(!left){
return right;
} /* if */
if(!right){
return left;
} /* if */
return (left->Valor < right->Valor) ? left : right ;
}
So, basically what i'm trying to achieve here is to compare the two sides of each node to find the lowest.
It seems strange that your code returns a pointer. I would expect something like:
// Assume valor is int
int findLowest(tpNoArvore * pNo){
if (!pNo) exit(1); /* fatal error */
// If this is a leaf just return its value
if(isLeaf(pNo)) return pNo->Valor;
// Not a leaf
// Find the lowest value in left part of tree
int leftValor = findLowest(pNo->pNoL);
// Find the lowest value in right part of tree
int rightValor = findLowest(pNo->pNoR);
// Return the lowest of leftValue ans rightValue
return (leftValor < rightValor) ? leftValor : rightValor ;
}
But maybe I have misundetstood your question.
I'm trying to get the content between a double-quote to count as one token for an assignment.
For example:
"hello world" = 1 token
"hello" "world" = 3 tokens (because space counts as 1 token)
I created main.cpp and I added "scanQuotesAsString" code to 3 modules given:
scanner.cpp
scanner.h
scanpriv.h
Right now, "hello world" scans a 2 tokens, not skipping the space. If I add (or skipspace, then regular input such as |hello world| without quotes skips spaces as well.
I think my issue is in scanner.cpp, where the last couple functions are:
/*
* Private method: scanToEndOfIdentifier
* Usage: finish = scanToEndOfIdentifier();
* ----------------------------------------
* This function advances the position of the scanner until it
* reaches the end of a sequence of letters or digits that make
* up an identifier. The return value is the index of the last
* character in the identifier; the value of the stored index
* cp is the first character after that.
*/
int Scanner::scanToEndOfIdentifier() {
while (cp < len && isalnum(buffer[cp])) {
if ((stringOption == ScanQuotesAsStrings) && (buffer[cp] == '"'))
break;
cp++;
}
return cp - 1;
}
/* Private functions */
/*
* Private method: scanQuotedString
* Usage: scanQuotedString();
* -------------------
* This function advances the position of the scanner until the
* current character is a double quotation mark
*/
void Scanner::scanQuotedString() {
while ((cp < len && (buffer[cp] == '"')) || (cp < len && (buffer[cp] == '"'))){
cp++;
}
Here is main.cc
#include "genlib.h"
#include "simpio.h"
#include "scanner.h"
#include <iostream>
/* Private function prototypes */
int CountTokens(string str);
int main() {
cout << "Please enter a sentence: ";
string str = GetLine();
int num = CountTokens(str);
cout << "You entered " << num << " tokens." << endl;
return 0;
}
int CountTokens(string str) {
int count = 0;
Scanner scanner; // create new scanner object
scanner.setInput(str); // initialize the input to be scanned
//scanner.setSpaceOption(Scanner::PreserveSpaces);
scanner.setStringOption(Scanner::ScanQuotesAsStrings);
while (scanner.hasMoreTokens()) { // read tokens from the scanner
scanner.nextToken();
count++;
}
return count;
}
Here's scanner.cpp
/*
* File: scanner.cpp
* -----------------
* Implementation for the simplified Scanner class.
*/
#include "genlib.h"
#include "scanner.h"
#include <cctype>
#include <iostream>
/*
* The details of the representation are inaccessible to the client,
* but consist of the following fields:
*
* buffer -- String passed to setInput
* len -- Length of buffer, saved for efficiency
* cp -- Current character position in the buffer
* spaceOption -- Setting of the space option extension
*/
Scanner::Scanner() {
buffer = "";
spaceOption = PreserveSpaces;
}
Scanner::~Scanner() {
/* Empty */
}
void Scanner::setInput(string str) {
buffer = str;
len = buffer.length();
cp = 0;
}
/*
* Implementation notes: nextToken
* -------------------------------
* The code for nextToken follows from the definition of a token.
*/
string Scanner::nextToken() {
if (cp == -1) {
Error("setInput has not been called");
}
if (stringOption == ScanQuotesAsStrings) scanQuotedString();
if (spaceOption == IgnoreSpaces) skipSpaces();
int start = cp;
if (start >= len) return "";
if (isalnum(buffer[cp])) {
int finish = scanToEndOfIdentifier();
return buffer.substr(start, finish - start + 1);
}
cp++;
return buffer.substr(start, 1);
}
bool Scanner::hasMoreTokens() {
if (cp == -1) {
Error("setInput has not been called");
}
if (stringOption == ScanQuotesAsStrings) scanQuotedString();
if (spaceOption == IgnoreSpaces) skipSpaces();
return (cp < len);
}
void Scanner::setSpaceOption(spaceOptionT option) {
spaceOption = option;
}
Scanner::spaceOptionT Scanner::getSpaceOption() {
return spaceOption;
}
void Scanner::setStringOption(stringOptionT option) {
stringOption = option;
}
Scanner::stringOptionT Scanner::getStringOption() {
return stringOption;
}
/* Private functions */
/*
* Private method: skipSpaces
* Usage: skipSpaces();
* -------------------
* This function advances the position of the scanner until the
* current character is not a whitespace character.
*/
void Scanner::skipSpaces() {
while (cp < len && isspace(buffer[cp])) {
cp++;
}
}
/*
* Private method: scanToEndOfIdentifier
* Usage: finish = scanToEndOfIdentifier();
* ----------------------------------------
* This function advances the position of the scanner until it
* reaches the end of a sequence of letters or digits that make
* up an identifier. The return value is the index of the last
* character in the identifier; the value of the stored index
* cp is the first character after that.
*/
int Scanner::scanToEndOfIdentifier() {
while (cp < len && isalnum(buffer[cp])) {
if ((stringOption == ScanQuotesAsStrings) && (buffer[cp] == '"'))
break;
cp++;
}
return cp - 1;
}
/* Private functions */
/*
* Private method: scanQuotedString
* Usage: scanQuotedString();
* -------------------
* This function advances the position of the scanner until the
* current character is a double quotation mark
*/
void Scanner::scanQuotedString() {
while ((cp < len && (buffer[cp] == '"')) || (cp < len && (buffer[cp] == '"'))){
cp++;
}
scanner.h
/*
* File: scanner.h
* ---------------
* This file is the interface for a class that facilitates dividing
* a string into logical units called "tokens", which are either
*
* 1. Strings of consecutive letters and digits representing words
* 2. One-character strings representing punctuation or separators
*
* To use this class, you must first create an instance of a
* Scanner object by declaring
*
* Scanner scanner;
*
* You initialize the scanner's input stream by calling
*
* scanner.setInput(str);
*
* where str is the string from which tokens should be read.
* Once you have done so, you can then retrieve the next token
* by making the following call:
*
* token = scanner.nextToken();
*
* To determine whether any tokens remain to be read, you can call
* the predicate method scanner.hasMoreTokens(). The nextToken
* method returns the empty string after the last token is read.
*
* The following code fragment serves as an idiom for processing
* each token in the string inputString:
*
* Scanner scanner;
* scanner.setInput(inputString);
* while (scanner.hasMoreTokens()) {
* string token = scanner.nextToken();
* . . . process the token . . .
* }
*
* This version of the Scanner class includes an option for skipping
* whitespace characters, which is described in the comments for the
* setSpaceOption method.
*/
#ifndef _scanner_h
#define _scanner_h
#include "genlib.h"
/*
* Class: Scanner
* --------------
* This class is used to represent a single instance of a scanner.
*/
class Scanner {
public:
/*
* Constructor: Scanner
* Usage: Scanner scanner;
* -----------------------
* The constructor initializes a new scanner object. The scanner
* starts empty, with no input to scan.
*/
Scanner();
/*
* Destructor: ~Scanner
* Usage: usually implicit
* -----------------------
* The destructor deallocates any memory associated with this scanner.
*/
~Scanner();
/*
* Method: setInput
* Usage: scanner.setInput(str);
* -----------------------------
* This method configures this scanner to start extracting
* tokens from the input string str. Any previous input string is
* discarded.
*/
void setInput(string str);
/*
* Method: nextToken
* Usage: token = scanner.nextToken();
* -----------------------------------
* This method returns the next token from this scanner. If
* nextToken is called when no tokens are available, it returns the
* empty string.
*/
string nextToken();
/*
* Method: hasMoreTokens
* Usage: if (scanner.hasMoreTokens()) . . .
* ------------------------------------------
* This method returns true as long as there are additional
* tokens for this scanner to read.
*/
bool hasMoreTokens();
/*
* Methods: setSpaceOption, getSpaceOption
* Usage: scanner.setSpaceOption(option);
* option = scanner.getSpaceOption();
* ------------------------------------------
* This method controls whether this scanner
* ignores whitespace characters or treats them as valid tokens.
* By default, the nextToken function treats whitespace characters,
* such as spaces and tabs, just like any other punctuation mark.
* If, however, you call
*
* scanner.setSpaceOption(Scanner::IgnoreSpaces);
*
* the scanner will skip over any white space before reading a
* token. You can restore the original behavior by calling
*
* scanner.setSpaceOption(Scanner::PreserveSpaces);
*
* The getSpaceOption function returns the current setting
* of this option.
*/
enum spaceOptionT { PreserveSpaces, IgnoreSpaces };
void setSpaceOption(spaceOptionT option);
spaceOptionT getSpaceOption();
/*
* Methods: setStringOption, getStringOption
* Usage: scanner.setStringOption(option);
* option = scanner.getStringOption();
* --------------------------------------------------
* This method controls how the scanner reads double quotation marks
* as input. The default is set to treat quotes just like any other
* punctuation character:
* scanner.setStringOption(Scanner::ScanQuotesAsPunctuation);
*
* Otherwise, the option:
* scanner.setStringOption(Scanner::ScanQuotesAsStrings);
*
* the token starting with a quotation mark will be scanned until
* another quotation mark is found (closing quotation). Therefore
* the entire string within the quotation, including both quotation
* marks counts as 1 token.
*/
enum stringOptionT { ScanQuotesAsPunctuation, ScanQuotesAsStrings };
void setStringOption(stringOptionT option);
stringOptionT getStringOption();
private:
#include "scanpriv.h"
};
#endif
** and finally scanpriv.h **
/*
* File: scanpriv.h
* ----------------
* This file contains the private data for the simplified version
* of the Scanner class.
*/
/* Instance variables */
string buffer; /* The string containing the tokens */
int len; /* The buffer length, for efficiency */
int cp; /* The current index in the buffer */
spaceOptionT spaceOption; /* Setting of the space option */
stringOptionT stringOption;
/* Private method prototypes */
void skipSpaces();
int scanToEndOfIdentifier();
void scanQuotedString();
To long to read.
Two ways of parsing quoted text:
0) State
A simple switch that tells whether you are in quotes right now, and which activates some special quotation handling. This would basically be equivalent to #1), just inline.
1) Sub-Rule in Recursive Descent Scanner
Put the state away and write a separate rule for scanning quoted text. The code would actually be quite simple (C++ inspired p-code):
// assume we are one behind the opening quotation mark
for (c : text) {
if (is_escape (*c)) { // to support stuff like "foo's name is \"bar\""
p = peek(c);
if (!is_valid_escape_character (peek (c))) error;
else {
make the peeked character (*p) part of the result;
++c;
}
}
else if (is_quotation_mark (*c))
{
return the result; // we approached the end of the string
}
else if (!is_valid_character (*c))
{
error; // maybe you want to forbid literal control characters
}
else
{
make *c part of the result
}
}
error; // reached end of input before closing quotation mark
If you do not want so support escape characters, the code gets simpler:
// assume we are one behind the opening quotation mark
for (c : text) {
if (is_quotation_mark (*c))
return the result;
else if (!is_valid_character (*c))
error;
else
make *c part of the result
}
error; // reached end of input before closing quotation mark
You should not omit the check whether its an invalid character, as this would invite users to exploit your code and possibly make use of undefined behavior of your program.
From a quick glance over the code: If you are in ScanQuotesAsStrings mode, you expect no other tokens than quoted strings; rather, the difference should be that when you see a token that begins with '"', you then go to a separate sub-scanner.
In pseudocode (using the C++ "end iterator is one-past-the-end" idiom):
current_token.begin = cursor;
current_token.end = current_token.begin + 1;
if(scan_quotes_as_strings && *current_token.begin == '"') {
while(*current_token.end && *current_token.end != '"')
++current_token.end;
return;
}
while(*current_token.end && *current_token.end != ' ')
++current_token.end;
You can combine these two loops to a single one by introducing a state variable rather than expressing the scanner state with different code paths.
Also,
while ((cp < len && (buffer[cp] == '"')) || (cp < len && (buffer[cp] == '"'))) ...
just looks fishy.
I've been using this site for a while and so far never needed to ask a new question (found all answers I've needed until now).
I need to push_back multiple objects into a vector but VS throws an error (This may be due to a corruption of the heap, which indicates a bug in PVSS00DataGate.exe or any of the DLLs it has loaded) that I cannot seem to work out for myself.
Here is what I am trying to do, it works to push_back the first object into the vector but when I try to push_back a second object that is when the error occurs.
class HWObject{}
void DataLogger::WriteNewMessages()
{
unsigned int iBattery = 0;
unsigned int iSignal = 0;
TimeVar tTimeStamp;
// I want to store all HWObjects in a temporary vector (loggerData)
std::vector<HWObject> loggerData;
CharString strElement;
strElement.format( "batteryCondition.value" );
SendOneValuePVSS( (const char *)strElement, iBattery, tTimeStamp );
strElement.format( "signalStrength.value" );
SendOneValuePVSS( (const char *)strElement, iSignal, tTimeStamp );
}
void DataLogger::SendOneValuePVSS(const char *szElementName, double dValue, TimeVar, &tValue)
{
HWObject obj;
obj.setOrgTime(tValue); // Current time
obj.setTimeOfPeriphFlag();
CharString address;
address = strID;
address += ".";
address += szElementName;
obj.setAddress(address);
loggerData.reserve( loggerData.size() + 1 );
loggerData.push_back( obj );
obj.cutData();
}
dataLogger is declared in
class DataLogger
{
public:
std::vector<HWObject> loggerData;
...
}
Here is the class HWObject, I didn't want to overwhelm you with code.
public:
/** Default constructor*/
HWObject();
/** Constructor, which sets the periphAddr and transformationType.
* #param addressString address of the HW object
* #param trans type of transformation
*/
HWObject(const char* addressString, TransformationType trans);
/** Destructor. If the date pointer is not NULL, it is deleted.
*/
virtual ~HWObject();
/** Creates a new HWObject
* This function returns an empty HWObject, no properties are duplicated or copied!
* #classification public use, overload, call base
*/
virtual HWObject * clone() const;
/** Reset all pvss2 relevant parts of the HWObject. when overloading this member
* don't forget to call the basic function!
* #classification public use, overload, call base
*/
virtual void clear();
/** Gets pointer to data
* #return pointer to data
*/
const PVSSchar * getDataPtr() const { return dataPtr; }
/** Gets the data buffer pointer
* #return data buffer pointer
*/
PVSSchar * getData() { return dataPtr; }
/** Cut the data buffer out of the HWObject.
* This function is used to avoid the deletion
* of the data buffer, when a new pointer is set using
* setData() or the HWObject is deleted.
* #return pointer to the data of the HWObject
*/
PVSSchar * cutData();
/** Get the data buffer lenght
* #return length of the data buffer
*/
PVSSushort getDlen() const { return dataLen; }
/** Set ptr to the data buffer, pointer is captured.
* The actual data pointer in the HWObject is deleted,
* if it is not NULL. To avoid the deletion use cutData()
* in order to cut out the pointer.
* #param ptr pointer to new data
*/
void setData(PVSSchar *ptr);
/** Set the data length
* #param len length to be set
*/
void setDlen(const PVSSushort len) { dataLen = len; }
/** Get the periph address
* #return periph address string
*/
const CharString & getAddress() const { return address; }
/** Get the transformation type
* #return type of transformation
*/
TransformationType getType() const { return transType; }
/** Set the transformation type
* #param typ type of transformation for setting
*/
void setType(const TransformationType typ) { transType = typ; }
/** Get the subindex
* #return subindex
*/
PVSSushort getSubindex() const { return subindex; }
/** Set the subindex
* #param sx subindex to be set
*/
void setSubindex( const PVSSushort sx) { subindex = sx; }
/** Get the origin time
* #return origin time
*/
const TimeVar& getOrgTime() const { return originTime; }
/** Get the origin time
* #return oriin time
*/
TimeVar& getOrgTime() { return originTime; }
/** Set the origin time
* #param tm origin time to be set
*/
void setOrgTime(const TimeVar& tm) { originTime = tm; }
/** Get HWObject purpose
* #return objSrcType
*/
ObjectSourceType getObjSrcType() const { return objSrcType; }
/** Set HWObject purpose
* #param tp objSrcType
*/
void setObjSrcType(const ObjectSourceType tp) { objSrcType = tp; }
/** Get number of elements in data buffer
* #return number of elements in data buffer
*/
PVSSushort getNumberOfElements() const { return number_of_elements; }
/** Set number of elements in data buffer
* #param var number of elements in data buffer
*/
void setNumberOfElements(const PVSSushort var) { number_of_elements = var; }
/** Prints the basic HWObject information on stderr.
* in case of overloading don't forget to call the base function!
* #classification public use, overload, call base
*/
virtual void debugPrint() const;
/** Prints th basic HWObject info in one CharString for internal debug DP.
* in case of overloading call base function first, then append specific info
* #classification public use, overload, call base
*/
virtual CharString getInfo() const;
/** Set the periph address
* #param adrStr pointer to address string
*/
virtual void setAddress(const char *adrStr);
/** Set the additional data (flag, orig time, valid user byte,etc)
* #param data aditional flags that be set
* #param subix subindex, use subix 0 for setting values by default
*/
virtual void setAdditionalData(const RecVar &data, PVSSushort subix);
/** Set the 'origin time comes from periph' flag
*/
void setTimeOfPeriphFlag()
{
setSbit(DRV_TIME_OF_PERIPH);
}
/** Check whether time comes from periph
* #return PVSS_TRUE if the time is from perip
*/
PVSSboolean isTimeFromPeriph() const
{
// If isTimeOfPeriph is set, it must be valid
return getSbit(DRV_TIME_OF_PERIPH);
}
/** Set the flag if you want to receive callback if event has answered the value change
*/
void setWantAnswerFlag()
{
setSbit(DRV_WANT_ANSWER);
}
/** Get the status of the 'want answer, flag
*/
PVSSboolean getWantAnswerFlag() const
{
// If isTimeOfPeriph is set, it must be valid
return getSbit(DRV_WANT_ANSWER);
}
/** Set the user bit given by input parameter.
* Status bits defined by the enum DriverBits
* #param bitno bit number
* #return PVSS_TRUE if bit was set
*/
PVSSboolean setSbit(PVSSushort bitno)
{
return (status.set(bitno) && status.set(bitno + (PVSSushort)DRV_VALID_INVALID - (PVSSushort)DRV_INVALID));
}
/** Clear the user bit given by input parameter
* #param bitno bit number
* #return PVSS_TRUE if bit was cleared
*/
PVSSboolean clearSbit(PVSSushort bitno)
{
return (status.clear(bitno) && status.set(bitno + (PVSSushort)DRV_VALID_INVALID - (PVSSushort)DRV_INVALID));
}
PVSSboolean isValidSbit(PVSSushort bitno) const
{
return status.get(bitno + (PVSSushort)DRV_VALID_INVALID - (PVSSushort)DRV_INVALID);
}
/** Check any bit
* #param bitno bit number
* #return status of the bit on bitno position
*/
PVSSboolean getSbit(PVSSushort bitno) const {return status.get(bitno);}
/** Clear all status bits
* return status of clear all
*/
PVSSboolean clearStatus() {return status.clearAll();}
/** Get the status of this object
* #return bit vector status
*/
const BitVec & getStatus() const {return status;}
/** Set status of the bit vector
* #param bv deference to bit vector to be set as status
*/
void setStatus(const BitVec &bv) {status = bv;}
/** Set a user byte in the status.
* #param userByteNo number of user byte range 0..3
* #param val value to set
* #return PVSS_TRUE execution OK
* PVSS_FALSE in case of error
*/
PVSSboolean setUserByte (PVSSushort userByteNo, PVSSuchar val);
/** Reads a user byte from the status.
* #param userByteNo number of user byte range 0..3
* #return the requested user byte
*/
PVSSuchar getUserByte (PVSSushort userByteNo) const;
/** Check validity of user byte.
* #param userByteNo number of user byte range 0..3
* #return PVSS_TRUE user byte is valid
* PVSS_FALSE user byte is not valid
*/
PVSSboolean isValidUserByte(PVSSushort userByteNo) const;
/** Format status bits into a string
* #param str status bits converted to string
*/
void formatStatus (CharString & str) const ;
// ------------------------------------------------------------------
// internal ones
/** Read data from bin file
* #param fp file handle
*/
virtual int inFromBinFile( FILE *fp );
/** Write data to bin file
* #param fp file handle
*/
virtual int outToBinFile( FILE *fp );
/** Set data length
* #param dlen data length
*/
void setDlenLlc (PVSSushort dlen) {dataLenLlc = dlen;}
virtual void updateBufferLlc (HWObject * hwo, int offset1 = 0);
virtual int compareLlc (HWObject * hwo, int offset1 = 0, int offset2 = 0, int len = -1);
/** Get dataLenLlc
* #return dataLenLlc
*/
PVSSushort getDlenLlc () const {return dataLenLlc;}
/** Function to delete the data buffer; overload if special deletion must be done
*/
virtual void deleteData ();
/** Set HW identifier
* #param id hw identifier to be set
*/
void setHwoId(PVSSulong id) {hwoId = id;}
/** Get HW identifier
* #return hw identifier
*/
PVSSulong getHwoId() const {return hwoId;}
protected:
/// the dynamic data buffer
PVSSchar* dataPtr;
/// the data buffer len
PVSSushort dataLen;
/// the pvss2 periph address string
CharString address;
/// the start subix for the data buffer
PVSSushort subindex;
/// the datatype of the data in the buffer (i.e. transformationtype)
TransformationType transType;
/// the time of income, normally set by the constructor
TimeVar originTime;
/// the purpose of this HWObject
ObjectSourceType objSrcType;
/// the number of elements in the data buffer, used for arrays and records
PVSSushort number_of_elements; // fuer array!!!
/// the user bits of the original config
BitVec status;
private:
PVSSushort dataLenLlc;
PVSSulong hwoId;
};
You're not showing the important parts. I'd guess that HWObject has
dynamically allocated memory, and doesn't implement the rule of three
(copy constructor, assignment operator and destructor). But it's only a
guess. (Unless you're using special techniques like reference counting
or smart pointers, copy must do a deep copy, and assignment should
probably use the swap idiom.)
Also, there's no point in reserving size() + 1 just before
push_back.
Hi all
I need to declare a variable in Node to keep position of that node so I declare it in node.h
like: std::vector<double> exPosition;(public)
then I defined a simple function for getting this variable like:virtual Vector
GetmyPosition (void) const=0;
then in node.cc I wrote this simple function:
node::GetmyPosition (void) const
{
return exPosition;
}
but when i run it it has this error:
cannot allocate an object of abstract type 'ns3::Node'
note: because the following virtual functions are pure within 'ns3::Node';
here is the complete code for node.h:
#ifndef NODE_H
#define NODE_H
#include <vector>
#include "ns3/object.h"
#include "ns3/callback.h"
#include "ns3/ptr.h"
#include "ns3/net-device.h"
namespace ns3 {
class Application;
class Packet;
class Address;
/**
* \ingroup node
*
* \brief A network Node.
*
* This class holds together:
* - a list of NetDevice objects which represent the network interfaces
* of this node which are connected to other Node instances through
* Channel instances.
* - a list of Application objects which represent the userspace
* traffic generation applications which interact with the Node
* through the Socket API.
* - a node Id: a unique per-node identifier.
* - a system Id: a unique Id used for parallel simulations.
*
* Every Node created is added to the NodeList automatically.
*/
class Node : public Object
{
public:
/// exposition of the node
//std::vector<Ptr<Node> > exPosition;
std::vector<double> exPosition;
/// current position of the node
//std::vector<double> cPosition;
static TypeId GetTypeId (void);
/**
* Must be invoked by subclasses only.
*/
Node();
/**
* \param systemId a unique integer used for parallel simulations.
*
* Must be invoked by subclasses only.
*/
Node(uint32_t systemId);
virtual ~Node();
/**
* \returns the unique id of this node.
*
* This unique id happens to be also the index of the Node into
* the NodeList.
*/
uint32_t GetId (void) const;
/**
* \returns the system id for parallel simulations associated
* to this node.
*/
uint32_t GetSystemId (void) const;
/**
* \param device NetDevice to associate to this node.
* \returns the index of the NetDevice into the Node's list of
* NetDevice.
*
* Associate this device to this node.
*/
uint32_t AddDevice (Ptr<NetDevice> device);
/**
* \param index the index of the requested NetDevice
* \returns the requested NetDevice associated to this Node.
*
* The indexes used by the GetDevice method start at one and
* end at GetNDevices ()
*/
Ptr<NetDevice> GetDevice (uint32_t index) const;
/**
* \returns the number of NetDevice instances associated
* to this Node.
*/
uint32_t GetNDevices (void) const;
/**
* \param application Application to associate to this node.
* \returns the index of the Application within the Node's list
* of Application.
*
* Associated this Application to this Node. This method is called
* automatically from Application::Application so the user
* has little reasons to call this method directly.
*/
uint32_t AddApplication (Ptr<Application> application);
/**
* \param index
* \returns the application associated to this requested index
* within this Node.
*/
Ptr<Application> GetApplication (uint32_t index) const;
/**
* \returns the number of applications associated to this Node.
*/
uint32_t GetNApplications (void) const;
/**
* A protocol handler
*
* \param device a pointer to the net device which received the packet
* \param packet the packet received
* \param protocol the 16 bit protocol number associated with this packet.
* This protocol number is expected to be the same protocol number
* given to the Send method by the user on the sender side.
* \param sender the address of the sender
* \param receiver the address of the receiver; Note: this value is
* only valid for promiscuous mode protocol
* handlers. Note: If the L2 protocol does not use L2
* addresses, the address reported here is the value of
* device->GetAddress().
* \param packetType type of packet received
* (broadcast/multicast/unicast/otherhost); Note:
* this value is only valid for promiscuous mode
* protocol handlers.
*/
typedef Callback<void,Ptr<NetDevice>, Ptr<const Packet>,uint16_t,const Address &,
const Address &, NetDevice::PacketType> ProtocolHandler;
/**
* \param handler the handler to register
* \param protocolType the type of protocol this handler is
* interested in. This protocol type is a so-called
* EtherType, as registered here:
* http://standards.ieee.org/regauth/ethertype/eth.txt
* the value zero is interpreted as matching all
* protocols.
* \param device the device attached to this handler. If the
* value is zero, the handler is attached to all
* devices on this node.
* \param promiscuous whether to register a promiscuous mode handler
*/
void RegisterProtocolHandler (ProtocolHandler handler,
uint16_t protocolType,
Ptr<NetDevice> device,
bool promiscuous=false);
/**
* \param handler the handler to unregister
*
* After this call returns, the input handler will never
* be invoked anymore.
*/
void UnregisterProtocolHandler (ProtocolHandler handler);
/**
* \returns true if checksums are enabled, false otherwise.
*/
static bool ChecksumEnabled (void);
protected:
/**
* The dispose method. Subclasses must override this method
* and must chain up to it by calling Node::DoDispose at the
* end of their own DoDispose method.
*/
virtual void DoDispose (void);
virtual void DoStart (void);
private:
/**
* \param device the device added to this Node.
*
* This method is invoked whenever a user calls Node::AddDevice.
*/
virtual void NotifyDeviceAdded (Ptr<NetDevice> device);
bool NonPromiscReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet>, uint16_t protocol, const Address &from);
bool PromiscReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet>, uint16_t protocol,
const Address &from, const Address &to, NetDevice::PacketType packetType);
bool ReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet>, uint16_t protocol,
const Address &from, const Address &to, NetDevice::PacketType packetType, bool promisc);
void Construct (void);
struct ProtocolHandlerEntry {
ProtocolHandler handler;
Ptr<NetDevice> device;
uint16_t protocol;
bool promiscuous;
};
typedef std::vector<struct Node::ProtocolHandlerEntry> ProtocolHandlerList;
uint32_t m_id; // Node id for this node
uint32_t m_sid; // System id for this node
std::vector<Ptr<NetDevice> > m_devices;
std::vector<Ptr<Application> > m_applications;
ProtocolHandlerList m_handlers;
};
} //namespace ns3
#endif /* NODE_H */
and also the complete code for node.cc
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 Georgia Tech Research Corporation, INRIA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Authors: George F. Riley<riley#ece.gatech.edu>
* Mathieu Lacage <mathieu.lacage#sophia.inria.fr>
*/
#include "node.h"
#include "node-list.h"
#include "net-device.h"
#include "application.h"
#include "ns3/packet.h"
#include "ns3/simulator.h"
#include "ns3/object-vector.h"
#include "ns3/uinteger.h"
#include "ns3/log.h"
#include "ns3/assert.h"
#include "ns3/global-value.h"
#include "ns3/boolean.h"
#include "ns3/simulator.h"
#include "ns3/vector.h"
NS_LOG_COMPONENT_DEFINE ("Node");
namespace ns3{
NS_OBJECT_ENSURE_REGISTERED (Node);
GlobalValue g_checksumEnabled = GlobalValue ("ChecksumEnabled",
"A global switch to enable all checksums for all protocols",
BooleanValue (false),
MakeBooleanChecker ());
//Vector exposition = (0.0, 0.0, 0.0);
/*.AddAttribute ("exPosition", "The previous position of this node.",
TypeId::ATTR_GET,
VectorValue (Vector (0.0, 0.0, 0.0)), // ignored initial value.
MakeVectorAccessor (&Node::m_exposition),
MakeVectorChecker ())
.AddAttribute ("cPosition", "The current position of this node.",
TypeId::ATTR_GET,
VectorValue (Vector (0.0, 0.0, 0.0)), // ignored initial value.
MakeVectorAccessor (&Node::m_cposition),
MakeVectorChecker ())*/
TypeId
Node::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::Node")
.SetParent<Object> ()
.AddConstructor<Node> ()
.AddAttribute ("DeviceList", "The list of devices associated to this Node.",
ObjectVectorValue (),
MakeObjectVectorAccessor (&Node::m_devices),
MakeObjectVectorChecker<NetDevice> ())
.AddAttribute ("ApplicationList", "The list of applications associated to this Node.",
ObjectVectorValue (),
MakeObjectVectorAccessor (&Node::m_applications),
MakeObjectVectorChecker<Application> ())
.AddAttribute ("Id", "The id (unique integer) of this Node.",
TypeId::ATTR_GET, // allow only getting it.
UintegerValue (0),
MakeUintegerAccessor (&Node::m_id),
MakeUintegerChecker<uint32_t> ())
;
return tid;
}
Node::Node()
: m_id(0),
m_sid(0)
{
exPosition.at(1)= 0;
exPosition.at(2)= 0;
exPosition.at(3)= 0;
Construct ();
}
Node::Node(uint32_t sid)
: m_id(0),
m_sid(sid)
{
exPosition.at(1)= 0;
exPosition.at(2)= 0;
exPosition.at(3)= 0;
Construct ();
}
void
Node::Construct (void)
{
m_id = NodeList::Add (this);
//exPosition =(0.0,0.0,0.0);
}
Node::~Node ()
{}
uint32_t
Node::GetId (void) const
{
return m_id;
}
uint32_t
Node::GetSystemId (void) const
{
return m_sid;
}
uint32_t
Node::AddDevice (Ptr<NetDevice> device)
{
uint32_t index = m_devices.size ();
m_devices.push_back (device);
device->SetNode (this);
device->SetIfIndex(index);
device->SetReceiveCallback (MakeCallback (&Node::NonPromiscReceiveFromDevice, this));
Simulator::ScheduleWithContext (GetId (), Seconds (0.0),
&NetDevice::Start, device);
NotifyDeviceAdded (device);
return index;
}
Ptr<NetDevice>
Node::GetDevice (uint32_t index) const
{
NS_ASSERT_MSG (index < m_devices.size (), "Device index " << index <<
" is out of range (only have " << m_devices.size () << " devices).");
return m_devices[index];
}
uint32_t
Node::GetNDevices (void) const
{
return m_devices.size ();
}
uint32_t
Node::AddApplication (Ptr<Application> application)
{
uint32_t index = m_applications.size ();
m_applications.push_back (application);
application->SetNode (this);
Simulator::ScheduleWithContext (GetId (), Seconds (0.0),
&Application::Start, application);
return index;
}
Ptr<Application>
Node::GetApplication (uint32_t index) const
{
NS_ASSERT_MSG (index < m_applications.size (), "Application index " << index <<
" is out of range (only have " << m_applications.size () << " applications).");
return m_applications[index];
}
uint32_t
Node::GetNApplications (void) const
{
return m_applications.size ();
}
void
Node::DoDispose()
{
m_handlers.clear ();
for (std::vector<Ptr<NetDevice> >::iterator i = m_devices.begin ();
i != m_devices.end (); i++)
{
Ptr<NetDevice> device = *i;
device->Dispose ();
*i = 0;
}
m_devices.clear ();
for (std::vector<Ptr<Application> >::iterator i = m_applications.begin ();
i != m_applications.end (); i++)
{
Ptr<Application> application = *i;
application->Dispose ();
*i = 0;
}
m_applications.clear ();
Object::DoDispose ();
}
void
Node::DoStart (void)
{
for (std::vector<Ptr<NetDevice> >::iterator i = m_devices.begin ();
i != m_devices.end (); i++)
{
Ptr<NetDevice> device = *i;
device->Start ();
}
for (std::vector<Ptr<Application> >::iterator i = m_applications.begin ();
i != m_applications.end (); i++)
{
Ptr<Application> application = *i;
application->Start ();
}
Object::DoStart ();
}
void
Node::NotifyDeviceAdded (Ptr<NetDevice> device)
{}
void
Node::RegisterProtocolHandler (ProtocolHandler handler,
uint16_t protocolType,
Ptr<NetDevice> device,
bool promiscuous)
{
struct Node::ProtocolHandlerEntry entry;
entry.handler = handler;
entry.protocol = protocolType;
entry.device = device;
entry.promiscuous = promiscuous;
// On demand enable promiscuous mode in netdevices
if (promiscuous)
{
if (device == 0)
{
for (std::vector<Ptr<NetDevice> >::iterator i = m_devices.begin ();
i != m_devices.end (); i++)
{
Ptr<NetDevice> dev = *i;
dev->SetPromiscReceiveCallback (MakeCallback (&Node::PromiscReceiveFromDevice, this));
}
}
else
{
device->SetPromiscReceiveCallback (MakeCallback (&Node::PromiscReceiveFromDevice, this));
}
}
m_handlers.push_back (entry);
}
void
Node::UnregisterProtocolHandler (ProtocolHandler handler)
{
for (ProtocolHandlerList::iterator i = m_handlers.begin ();
i != m_handlers.end (); i++)
{
if (i->handler.IsEqual (handler))
{
m_handlers.erase (i);
break;
}
}
}
bool
Node::ChecksumEnabled (void)
{
BooleanValue val;
g_checksumEnabled.GetValue (val);
return val.Get ();
}
bool
Node::PromiscReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
const Address &from, const Address &to, NetDevice::PacketType packetType)
{
NS_LOG_FUNCTION(this);
return ReceiveFromDevice (device, packet, protocol, from, to, packetType, true);
}
bool
Node::NonPromiscReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
const Address &from)
{
NS_LOG_FUNCTION(this);
return ReceiveFromDevice (device, packet, protocol, from, from, NetDevice::PacketType (0), false);
}
bool
Node::ReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
const Address &from, const Address &to, NetDevice::PacketType packetType, bool promiscuous)
{
NS_ASSERT_MSG (Simulator::GetContext () == GetId (), "Received packet with erroneous context ; " <<
"make sure the channels in use are correctly updating events context " <<
"when transfering events from one node to another.");
NS_LOG_DEBUG("Node " << GetId () << " ReceiveFromDevice: dev "
<< device->GetIfIndex () << " (type=" << device->GetInstanceTypeId ().GetName ()
<< ") Packet UID " << packet->GetUid ());
bool found = false;
for (ProtocolHandlerList::iterator i = m_handlers.begin ();
i != m_handlers.end (); i++)
{
if (i->device == 0 ||
(i->device != 0 && i->device == device))
{
if (i->protocol == 0 ||
i->protocol == protocol)
{
if (promiscuous == i->promiscuous)
{
i->handler (device, packet, protocol, from, to, packetType);
found = true;
}
}
}
}
return found;
}
}//namespace ns3
I'll be thankful if someone help me about it.
Bests
Bahar
You cannot instantiate an object that has a virtual function declared as =0.
You can have pointers to them, but the pointed elements will actually have a type that inherits from your base class.
GetMyPosition is defined, does it need to be pure virtual? Have you tried removing =0 from function declaration?