I am currently experiencing a problem that I just can't seem to wrap my head around why it would be occurring.
In my (Unsplit)program I've created a class that defines an entity object and is able to handle its creation and variables just fine (as I've tested before adding
std::string getName(Entity)const;
std::string getType(Entity)const;
int getDamage(Entity)const;
int getHealth(Entity)const;
But when I do... Even though they are already declared publicly in the class and I am fully able to call Initialize(); Attack(); and PrintStats(); just fine, it doesn't see the other four and therefor are not able to be called.
#include <iostream>
#include <string>
#include <math.h>
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
using namespace std;
class Entity
{
public:
Entity() { // default constructor
name = "Human";
type = "Normal";
damage = 1;
health = 100;
}
void printStats();
void Initialize(string, string, int, int); //transformer or setting function
void Attack(Entity&); //observer or getter function
std::string getName(Entity)const;
std::string getType(Entity)const;
int getDamage(Entity)const;
int getHealth(Entity)const;
private://data members and special function prototypes
std::string name;
std::string type;
int damage;
int health;
};
void summonEnemy(Entity&);
int main () {
/* initialize random seed: */
srand (time(NULL));
Entity Player;//declaring new class objects
Entity Enemy;//declaring new class objects
Player.Initialize("Player", "Normal", 10, 90);
summonEnemy(Enemy);
return 0;
}
void summonEnemy(Entity &target) {
target.Initialize("Enemy", "Normal", floor(rand() % 20 + 1), floor(rand() % 100));
cout << "An " << getType(target) << " type " << getName(target) << " has appeared with " <<
getHealth(target) << "HP and can do " << getDamage(target) << " damage.";
}
Error message:
error:'getType' Was not defined in this scope.
error:'getName' Was not defined in this scope.
error:'getHealth' Was not defined in this scope.
error:'getDamage' Was not defined in this scope.
Cut off some code to narrow it down such that only what could be the cause of the problem is showing... But honestly its probably something simple that I am not seeing. Any help appreciated.
You are not calling them correctly. They are members of the Entity class, not standalone functions. Remove the Entity parameters from them, as they already have an implicit Entity *this parameter, and then call them like this:
class Entity
{
public:
Entity(); // default constructor
...
std::string getName() const;
std::string getType() const;
int getDamage() const;
int getHealth() const;
...
};
Entity::Entity()
{
Initialize("Human", "Normal", 1, 100);
}
std::string Entity::getName() const
{
return name;
}
std::string Entity::getType() const
{
return type;
}
int getDamage() const
{
return damage;
}
int getHealth() const
{
return health;
}
void summonEnemy(Entity &target)
{
target.Initialize("Enemy", "Normal", floor(rand() % 20 + 1), floor(rand() % 100));
cout << "An " << target.getType() << " type " << target.getName() << " has appeared with " <<
target.getHealth() << "HP and can do " << target.getDamage() << " damage.";
}
getType is a member function of Entity, so you need to call it on an Entity object:
target.getType();
In the class, you could implement it as:
class Entity {
...
std::string getType() const { return type; }
...
};
The same is true for your other three setters.
Related
In the Test Driver.cpp file, I cannot get the getName, getStockNo, or getNoInStock to output the correct information. The set functions and the get functions for classifications and price work. I do not know how to get char from the getName function. I have attached both the CPP file and the header file. I am only having issues with the Test Driver.cpp file
//Test Driver.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
#include <string>
#include "GameRecord.h"
using namespace std;
int main()
{
// Creating the object of the GameRecord class
GameRecord gr1;
// Setting the values in the GameRecord object gr1 as per the given question
gr1.setName("VideoGame");
gr1.setStockNo(200);
gr1.setClassification(10);
gr1.setPrice(250.0);
gr1.setNoInStock(5);
//problem here
char video;
int size = 0;
gr1.getName(&video, size);
cout << "Getting Name: " << video << endl;
//problem here
long stkNo = 0;
gr1.getStockNo();
cout << "Getting Stock Number: " << stkNo << endl;
int classification;
gr1.getClassification(classification);
cout << "Getting Classification: " << classification << endl;
double price;
gr1.getPrice(price);
cout << "Getting Price: $" << price << endl;
//problem here
int NoInStock = 0;
gr1.getNoInStock();
cout << "Getting Number in Stock: " << NoInStock << endl;
// Creating another object of the GameRecord class
GameRecord gr2("VideoGame2", 100, 5, 150.0);
// To print the Gamerecord object values, call the printRecord() function
gr2.printRecord();
}
//GameRecord.cpp file
#include <iostream>
#include <string.h>
#include "GameRecord.h"
using namespace std;
// Default Constructor used to initialize the data members of the class
GameRecord::GameRecord()
{
strcpy_s(m_sName, "");
m_lStockNo = 0;
m_iClassification = 0;
m_dPrice = 0.0;
m_iCount = 0;
}
// Argumented Constructor is used to initializing the data members of the class with the
respective values GameRecord::GameRecord(const char* name, long sn, int cl, double or)
{
strcpy_s(m_sName, sizeof(m_sName), name);
m_lStockNo = sn;
m_iClassification = cl;
m_dPrice = or ;
m_iCount = 1;
}
// Destructor of the class
GameRecord::~GameRecord()
{
}
/* Getter Setter Method of the GameRecord class, Getter method is used to
get the respective values and setter is used to set the values*/
void GameRecord::getName(char* name, int nameSize)
{
strcpy_s(name, nameSize, m_sName);
}
void GameRecord::setName(const char* name)
{
strcpy_s(m_sName, sizeof(m_sName), name);
}
long GameRecord::getStockNo()
{
return m_lStockNo;
}
void GameRecord::setStockNo(long sn)
{
m_lStockNo = sn;
}
void GameRecord::getClassification(int& cl)
{
cl = m_iClassification;
}
void GameRecord::setClassification(int cl)
{
m_iClassification = cl;
}
void GameRecord::getPrice(double& c)
{
c = m_dPrice;
}
void GameRecord::setPrice(double c)
{
m_dPrice = c;
}
int GameRecord::getNoInStock()
{
return m_iCount;
}
void GameRecord::setNoInStock(int count)
{
m_iCount = count;
}
void GameRecord::printRecord()
{
cout << m_sName << " " << m_lStockNo << " " << m_iClassification << " " << m_dPrice << " "
<< m_iCount << endl;
}
//GameRecord.h file
#pragma once
#include <iostream>
#include <string.h>
using namespace std;
class GameRecord
{
private:
char m_sName[128]; // used to store the name of a videogame or videogame system.
long m_lStockNo; // used to store a unique stock number for the videogame or videogame
system int m_iClassification; // used to code specific information about the videogame or
videogame system
.double m_dPrice; // used to store the price of this videogame or videogame system
int m_iCount; // used to store the number of copies of this item currently in the
inventory.
public
: GameRecord(); // constructor set the member variables to the following initial values.
// set the member variables to the values passed into the function and initialize the
m_iCount variable to one(1).GameRecord(const char* name, long sn, int cl, double price);
~GameRecord(); //The destructor shall be an empty, place - holder function.
// copy the member variable m_sName into the character array pointed to by the function argument.
void getName(char* name, int nameSize);
// function will copy the function argument into the member variable m_sName.
void setName(const char* name);
// function shall return the value stored in the member variable m_lStockNo.
long getStockNo();
// function will copy the function argument into the member variable m_lStockNo.
void setStockNo(long sn);
// function will copy the member variable m_iClassification into the interger variable referenced by the function argument.
void getClassification(int& cl);
// function will copy the function argument into the member variable m_iClassification.
void setClassification(int cl);
// function will copy the member variable m_dPrice into the double variable pointed to by the function argument.
void getPrice(double& c);
// function will copy the function argument into the member variable m_dPrice.
void setPrice(double c);
int getNoInStock(); // function shall return the value stored in the member variable
m_iCount.
void
setNoInStock(int count); // function will copy the function argument into the member
variable m_iCount.
void
printRecord(); // shall print to the screen all data found in the record
};
the function getName should be used as
int size=...;
char*name=new char[size];
c.gerName(name,size);
because it works by copying the name to the pointer got in the input
I'm trying to use a setter function inside of a constructor, which I've never done before. It's giving me the following error:
[Error] no match for call to '(Laptop) (const char [5], const char [3], int, int)'
well do i need to write the setter function too ? i mean outside the constructor ? i mean like this
void Laptop::setBrand(char a[])
{
brand=a;}
I think the error is in the second constructor, that takes four arguments, but I'm not able to find it.
Here is the code:
#include <iostream>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
using namespace std;
class Laptop{
private:
char brand[10];
char processor[10];
int ram;
int hardDrive;
public:
void setBrand(char Bra[]);
void setProcessor(char Pro[]);
void setRam(int Ram);
void setHardDrive(int HDrive);
char *getBrand();
char *getProcessor();
int getRam();
int getHardDrive();
Laptop();
Laptop(char [],char [],int ,int );
};
Laptop::Laptop(){
cout<<"Default constructor called...\n";
strcpy(brand,"None");
strcpy(processor,"None);
ram=0;
hardDrive=0;
}
i think the error is in the constructor
Laptop::Laptop(char Bra[],char Pro[],int Ram,int HDrive)
{
cout<<"Parameterized constructor called...\n";
setBrand(Bra );
setProcessor(Pro );
setRam(Ram);
setHardDrive(HDrive);
}
char *Laptop::getBrand()
{
return brand;
}
char *Laptop::getProcessor()
{
return processor;
}
int Laptop::getRam()
{
return ram;
}
int Laptop::getHardDrive()
{
return hardDrive;
}
int main()
{
Laptop laptopObj1;
Laptop laptopobj1("Dell","i5",4,500);
cout<<"Brand :"<<laptopObj1.getBrand()<<"\n";
cout<<"Processor :"<<laptopObj1.getProcessor()<<"\n";
cout<<"Ram :"<<laptopObj1.getRam()<<"\n";
cout<<"HardDrive :"<<laptopObj1.getHardDrive()<<"\n";
cout<<"Brand :"<<laptopObj2.getBrand()<<"\n";
cout<<"Processor :"<<laptopObj2.getProcessor()<<"\n";
cout<<"Ram :"<<laptopObj2.getRam()<<"\n";
cout<<"HardDrive :"<<laptopObj2.getHardDrive()<<"\n";
}
You have alot of errors here..
Laptop laptopObj1,laptopObj2;
...
laptopObj2("Dell","i5", 4, 500);
You cant use the constructor twice. You used the constructor Laptop() in the first line for both of the object, and then tried to use the second constructor for laptopObj2.
You can change the second line to:
laptopObj2 = Laptop("Dell","i5", 4, 500);
Or even better to define it there:
Laptop laptopObj1;
....
Laptop laptopObj2("Dell","i5", 4, 500);
Another problem is inside your Laptop() constructor definition:
Laptop::Laptop(char Bra[],char Pro[],int Ram,int HDrive)
{
.....
setBrand(Bra []); // Remove the []
setProcessor(Pro []); // Remove the []
....
}
And one more problem: You have no definitions for some functions of the class:
void setBrand(char Bra[]);
void setProcessor(char Pro[]);
void setRam(int Ram);
void setHardDrive(int HDrive);
void display();
EDIT:
One of the objects of c++ is std::string (#include <string>). You can use it instead of char str[]- just simpler way to declare strings in c++. For example, in your case:
/* Replace this: */
char brand[10];
char processor[10];
void setBrand(char Bra[]);
void setProcessor(char Pro[]);
char *getBrand();
char *getProcessor();
/* With this: */
string brand;
string processor;
void setBrand(const string &Bra);
void setProcessor(const string &Pro);
string getBrand();
string getProcessor();
You are passing two const char* as parameter, so you should change this :
Laptop::Laptop(char Bra[],char Pro[],int Ram,int HDrive)
to this:
Laptop::Laptop(const char* ,const char* ,int Ram,int HDrive)
You really should use std::string rather than char[].
On the question of constructors, there is no need to call setters, as the following code demonstrates. C++ has a shortcut for that capability. I have used std::string and fixed all typos.
#include <iostream>
#include <string>
using namespace std;
class Laptop
{
private:
string brand;
string processor;
int ram;
int hardDrive;
public:
void setBrand(string Bra);
void setProcessor(string Pro);
void setRam(int Ram);
void setHardDrive(int HDrive);
string getBrand();
string getProcessor();
int getRam();
int getHardDrive();
Laptop();
Laptop(string, string, int, int);
};
Laptop::Laptop()
: brand("None")
, processor("None")
, ram(0)
, hardDrive(0)
{
cout << "Default constructor called...\n";
}
Laptop::Laptop(string Bra, string Pro, int Ram, int HDrive)
: brand(Bra)
, processor(Pro)
, ram(Ram)
, hardDrive(HDrive)
{
cout << "Parameterized constructor called...\n";
}
string Laptop::getBrand()
{
return brand;
}
string Laptop::getProcessor()
{
return processor;
}
int Laptop::getRam()
{
return ram;
}
int Laptop::getHardDrive()
{
return hardDrive;
}
int main()
{
Laptop laptopObj1;
Laptop laptopObj2("Dell", "i5", 4, 500);
cout << "Brand :" << laptopObj1.getBrand() << "\n";
cout << "Processor :" << laptopObj1.getProcessor() << "\n";
cout << "Ram :" << laptopObj1.getRam() << "\n";
cout << "HardDrive :" << laptopObj1.getHardDrive() << "\n";
cout << "Brand :" << laptopObj2.getBrand() << "\n";
cout << "Processor :" << laptopObj2.getProcessor() << "\n";
cout << "Ram :" << laptopObj2.getRam() << "\n";
cout << "HardDrive :" << laptopObj2.getHardDrive() << "\n";
}
Mike
im trying to create a object called player in class player.
#include <string>
#ifndef PLAYER_HH
#define PLAYER_HH
using namespace std;
class Player
{
public:
Player(string name, int points);
const string get_name();
int get_points();
void add_points(int pts);
bool has_won();
private:
string _name;
};
#endif // PLAYER_HH
from player.cpp:
#include <string>
using namespace std;
Player::Player(string name):
_name(name), _points(0){
}
Now, the problem is, in the main function i get this error:
error: no matching function for call to ‘Player::Player(const char [6])’
Player player1 = Player("Matti");
^
Shouldn't the compiler be able to convert it to a string?
edit: Here is the full main.cpp that i'm not supposed to be changing:
#include <cstdlib>
#include <iostream>
#include <string>
#include "player.hh"
int main()
{
Player player1 = Player("Matti");
Player player2 = Player("Teppo");
Player* in_turn = 0;
int turn = 1;
while (true)
{
if (turn % 2 != 0)
{
in_turn = &player1;
}
else
{
in_turn = &player2;
}
std::cout << "Enter the score of player " << in_turn->get_name()
<< " of turn " << turn << ": ";
int pts = 0;
std::cin >> pts;
in_turn->add_points(pts);
if (in_turn->has_won())
{
std::cout << "Game over! The winner is " << in_turn->get_name() << "!" << std::endl;
return EXIT_SUCCESS;
}
std::cout << std::endl;
std::cout << "Scoreboard after turn " << turn << ":" << std::endl;
std::cout << player1.get_name() << ": " << player1.get_points() << "p" << std::endl;
std::cout << player2.get_name() << ": " << player2.get_points() << "p" << std::endl;
std::cout << std::endl;
turn += 1;
}
return EXIT_SUCCESS;
}
You guys are awesome with your fast answers :-)
You declared the constructor of player as Player(string name, int points);.
If you define a function with two parameters you have to use both.
Create your object with
Player player1 = Player("Matti", 0);
If you still want to call it with just one parameter you have to set a default value like this.
class Player
{
public:
...
Player(string name, int points = 0); // replace 0 with whatever you want to be default.
...
}
Then you can use both variants. The one above and the one you attempted
Player player1 = Player("Matti");
Of course the function header of your definition has to match the one in the declaration:
Player::Player(string name, int points):
_name(name), _points(points){
}
It's important not to write the default value inside dhe definition because this will most likely produce an compiler error.
The conversion from const char[6] to std::string will work and is not the issue here.
Your constructor has two parameters, you cannot simply omit the second one. If you like to create Player objects with a default score, declare your constructor as:
Player(string name, int points = 0);
First of all, you declare your constructor having two parameters:
Player(string name, int points);
but define it as having only one:
Player::Player(string name):
_name(name), _points(0){
}
That should give you compilation error. Either remove the second param from the declaration in class body and keep main.cpp as it is or add second param to the definition in player.cpp:
Player::Player(string name, int points):
_name(name), _points(points){
}
and then specify value for 'points' explicitly:
Player("Matti", 0);
You can also have both - just add default value for points:
class Player
{
...
Player(string name, int points = 0);
};
Then, both of these lines will work:
Player player1 ("Matti");
Player player2 ("Matti", 0);
I am in what seems to be a never ending quest to understand pointers. I finally have a working code using pointers to create a quick character and enemy, then mock an overly simple battle. It works 100% as it seems, but I'm not 100% sure it's correct or what I did to make it right. I have read 13 chapters so far in my C++ book (2 being over pointers specifically), but I'm still not sure it's clicked. If this looks like a valid use and proper utilization of them, I think I'm getting there, just wanted some clarification if it is. Thanks in advance!
#include <iostream>
#include <string>
#ifndef CLASS_H
#define CLASS_H
class Unit
{
public:
Unit(const std::string name, int hp, int power);
~Unit();
void printHP();
void attack(Unit* unit);
bool isDead();
private:
std::string mName;
int mHP;
int mPower;
};
Unit::Unit(const std::string name, int hp, int power)
{
mName = name;
mHP = hp;
mPower = power;
}
void Unit::printHP()
{
std::cout << std::endl;
std::cout << mName << "'s HP: " << mHP << std::endl;
}
void Unit::attack(Unit* unit)
{
std::cout << std::endl;
std::cout << unit->mName << " takes " << this->mPower << " damage! " << std::endl;
unit->mHP -= this->mPower;
}
bool Unit::isDead()
{
return this->mHP < 1;
}
Unit::~Unit()
{
}
#endif
int main()
{
Unit player1("GoodFellow", 20, 5);
Unit Enemy("ABadMan", 10, 2);
while (!Enemy.isDead())
{
player1.printHP();
Enemy.printHP();
player1.attack(&Enemy);
Enemy.attack(&player1);
}
}
Modified it to this... I think I get the reason for only using a reference, just trying to get the concept of pointers....
#include <iostream>
#include <string>
#ifndef CLASS_H
#define CLASS_H
class Unit
{
public:
Unit(const std::string name, int hp, int power);
~Unit();
void printHP();
void attack(Unit& unit);
bool isDead();
void setHP(int hp);
private:
std::string mName;
int mHP;
int mPower;
};
Unit::Unit(const std::string name, int hp, int power)
{
mName = name;
mHP = hp;
mPower = power;
}
void Unit::printHP()
{
std::cout << std::endl;
std::cout << mName << "'s HP: " << mHP << std::endl;
}
void Unit::attack(Unit& unit)
{
std::cout << std::endl;
std::cout << unit.mName << " takes " << this->mPower << " damage! " << std::endl;
unit.mHP -= this->mPower;
}
bool Unit::isDead()
{
return this->mHP < 1;
}
void Unit::setHP(int hp)
{
this->mHP = hp;
}
Unit::~Unit()
{
}
#endif
int main()
{
Unit player1("GoodFellow", 20, 5);
Unit Enemy("ABadMan", 10, 2);
while (true)
{
while (!Enemy.isDead())
{
player1.printHP();
Enemy.printHP();
player1.attack(Enemy);
Enemy.attack(player1);
}
char playAgain;
std::cout << "Fight again? (y)/(n)" << std::endl;
std::cin >> playAgain;
if (playAgain == 'n')
{
break;
}
else
{
Enemy.setHP(10);
}
}
}
Yes, that's a reasonable use of pointers. I was actually glad to see that you used them very little. I was half expecting to see Unit* player1 = new Unit ... and such all over the place. But no, you used automatic storage duration all over (rather than dynamic), which was very appropriate.
So the main reason for passing Unit*s to the attack functions is to that inside the function you can modify the Unit that you're attacking and have the effect seen outside. If you were to pass the Units directly, they would be copied into the function and then the unit->mHP -= this->mPower; would only affect the copy.
However, there is a more appropriate tool at your disposal here. You can use references. A reference also allows you to pass an object without copying it, so that modifications inside the function can be seen outside. Your attack function signature would change to:
void Unit::attack(Unit& unit)
The type Unit& is a "reference to Unit". Don't confuse the use of & with taking the address of an object - it means something completely different here. You would then call it like so:
player1.attack(Enemy);
The point is you should try to avoid pointers as much as possible. Since you can use references here, which are safer (you do not need to check for null), you should use them.
It's fine to learn about how pointers to work, but in doing so, you should learn how to use other more appropriate tools for the job.
I am creating a vector that contains pointers to a base class. In this vector I'm dynamically storing pointers to derived classes which contain some member variables, one of them being a string variable name.
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
bool hasDirection = false;
bool hasDiameter = false;
int direction;
float diameter;
int starDimension = 0;
int animalDimension = 0;
int fishDimension = 0;
class MovingObject
{
protected:
std::string name;
int direction;
float diameter;
int dimension;
float movingSpeed;
public:
std::string getName(){ return name;};
int getDirection(){ return direction;};
float getDiameter(){ return diameter;};
float getMovingSpeed(){ return movingSpeed;};
int getDimension(){ return dimension;};
void setName(std::string v){ name = v;};
void setDirection(int d){ direction = d;};
void setDiameter(float f){ diameter = f;};
void setMovingSpeed(float s){ movingSpeed = s;};
void setDimension (int d){ dimension = d;};
virtual void PrintContents()=0;
};
static std::vector<MovingObject*> data;
class starObject : public MovingObject
{
public:
void PrintContents()
{
std::cout << "(" << getName() << "," << getDiameter() << "," << getDirection() << ")";
}
};
class animalObject : public MovingObject
{
public:
void PrintContents()
{
std::cout << "(" << getName() << "," << getDiameter() << "," << getDirection() << ")";
}
};
class fishObject : public MovingObject
{
public:
void PrintContents()
{
std::cout << "(" << getName() << "," << getDiameter() << "," << getDirection() << ", [" << getDimension() << "], " << getMovingSpeed() << ")";
}
};
I later set all these member variables inside a main function. The problem is when I try to output the contents of the member variables, all of them show up except for the string name.
Now, I've checked to make sure that the string gets set before calling the PrintContent() method, and it shows that the value is in the vector. However, when I debug through the code, the value is no longer there, instead containing an empty string.
Could someone with better c++ knowledge explain to me why this is happening? This is the main class:
int main()
{
std::string type;
Reader reader;
while (!std::cin.eof())
{
try
{
std::string type;
std::cin >> type;
if (type =="int")
{
reader.ReadDirection();
}
else if (type =="float")
{
reader.ReadDiameter();
}
else if (type == "string")
{
std::string name;
std::cin >> name;
if (hasDirection && hasDiameter)
{
int dimension;
if (diameter > 0 && diameter < 10)
{
//fish
fishObject fish;
fish.setName(name);
fish.setDiameter(diameter);
fish.setDirection(direction);
dimension = fishDimension;
fishDimension += 50;
fish.setDimension(dimension);
fish.setMovingSpeed(0.1);
data.push_back(&fish);
}
else if (diameter >= 10 < 500)
{
//animal
animalObject animal;
animal.setName(name);
animal.setDiameter(diameter);
animal.setDirection(direction);
dimension = animalDimension;
animalDimension += 800;
animal.setDimension(dimension);
animal.setMovingSpeed(5.0);
data.push_back(&animal);
}
else if (diameter >=500)
{
//star
starObject star;
star.setName(name);
star.setDiameter(diameter);
star.setDirection(direction);
dimension = starDimension;
starDimension += 5000;
star.setDimension(dimension);
star.setMovingSpeed(30.0);
data.push_back(&star);
}
}
else
{
throw (IncompleteData(name));
}
}
}
catch (IncompleteData e)
{
std::cerr << "No diameter or direction given for object " << e.objectName << "\n";
}
}
The objects you push to the data vector are local because they are declared inside if/else blocks (see the declarations of fish and animal).
When you push the address of such an object to the vector, it will continue to point to the local object, which ceases to exist at the end of the local scope. You need to create objects that live beyond the local scope. One way of doing this is to create copies of the local objects on the heap and push those to the vector:
data.push_back(new fishObject(fish));
Of course this means that you get a memory leak unless you make sure you explicitly delete the elements of the vector some time before the end of the program. The usual recommendation to avoid having to think of this is to use a vector of std::unique_ptr<MovingObject> instead of a vector of naked pointers.