I was trying to count the number of characters in a string class but for some reason the program is skipping over my function completely. This is just the test code from the main program, it still was giving me the same results. How come the counter function is skipped over?
#include <iostream>
#include <string>
using namespace std;
void prompt(string& dna)
{
cout << "Input: ";
getline(cin, dna);
}
void counter(const string DNA,
int* a_count, int* t_count, int* c_count, int* g_count)
{
for (int i = 0; i < DNA.size(); i++)
{
if (DNA.at(i) == 'a')
{
*a_count++;
}
else if (DNA.at(i) == 't')
{
*t_count++;
}
else if (DNA.at(i) == 'c')
{
*c_count++;
}
else if (DNA.at(i) == 'g')
{
*g_count++;
}
}
}
int main()
{
string dna;
int a = 0;
int t = 0;
int c = 0;
int g = 0;
prompt(dna);
if (! dna.empty())
{
cout << "Before:\n"
<< "A: " << a << endl
<< "T: " << t << endl
<< "C: " << c << endl
<< "G: " << g << endl;
counter(dna, &a, &t, &c, &g);
cout << "\n\nAfter:\n"
<< "A: " << a << endl
<< "T: " << t << endl
<< "C: " << c << endl
<< "G: " << g << endl;
}
system("pause");
return 0;
}
You're applying operator ++ the wrong way. It should be:
if (DNA.at(i) == 'a')
{
(*a_count)++;
}
else if (DNA.at(i) == 't')
{
(*t_count)++;
}
else if (DNA.at(i) == 'c')
{
(*c_count)++;
}
else if (DNA.at(i) == 'g')
{
(*g_count)++;
}
You've got a priority problem between the ++ and * operators. You are incrementing the pointer address, not the value. (*a_count)++; would be correct.
You may find it easier to use reference parameters for the counts instead, since you don't actually need to do any pointer arithetic. ie:
void counter(const string DNA, int& a_count, int& t_count, int& c_count, int& g_count)
And, yes a switch statement would be neater.
Related
This code is for recursive function practice. When I run the code, it stops at the "POWER" cout line, then my compiler shows a segmentation error. The function that follows the POWER line is supposed to recursively raise number "a" to the power of number "b". I'm not sure how to fix this, can anyone help?
#include <iostream>
#include <string>
#include <vector>
using namespace std;
/**** Recursive backwards print, prints a string starting from last index to first*****/
void printReverse(string s, int i)
{
if(i < s.size())
{
printReverse(s.substr(1), i);
cout<<s[i];
}
else
{
return;
}
}
/**** Recursive power function, computes a^b, where b can be positive or negative*****/
int recPower(double a, int b)
{
int i = b; //i = b, so int a can be multiplied int b times
if (i == 0) //base
return 1;
else //multiply A by B, B times
{
a *= b;
return recPower(a, b); //recursive
i--; //decrement i until it equals 0
}
}
/**** Recursive string replace, replaces all instances of a character in a string with another character*****/
string recReplace(string s2, int i, char old, char neW)
{
if(s2[i] == old) //search for old char
{
i = neW; //replace it
i++; //iterate i
}
recReplace(s2, i, old, neW); //call function
return s2;
}
/**** Recursive list find > Searches if x exists in list, returns true if found, false otherwise*****/
int recListFind(vector<int> v, int i, int x)
{
if(v[i] == x)
{
cout << x << " exists in the vector."<<endl;
i++;
recListFind(v, i, x);
}
return true;
}
int main()
{
cout << "PRINT REVERSE" << endl;
cout << "----------" << endl;
string s1 = "hello world";
cout << "String: " << s1 << endl;
cout << "Reversed: ";
printReverse(s1, 0);
cout << endl;
/* Computes a^b (power function) */
cout << "POWER" << endl;
cout << "----------" << endl;
int a = 2, b = -3;
cout << a << "^" << b << " = ";
cout << recPower(a, b) << endl;
cout << endl;
/* Replaces a character in a string with a new one */
cout << "REPLACE" << endl;
cout << "----------" << endl;
string s2 = "-h-e-l-l-o-";
char oldChar = '-';
char newChar = ' ';
cout << "String: " << s2 << endl;
cout << "> Replace '" << oldChar << "' with '" << newChar << endl;
recReplace(s2, 0, oldChar, newChar);
cout << "String: " << s2 << endl;
cout << endl;
/* Searches for value in vector */
cout << "FIND" << endl;
cout << "----------" << endl;
int x = 7;
cout << "Does " << x << " exist in the vector? "; vector<int> v = {5, 1, 6, 7, 9};
cout << recListFind(v, 0, 7) << endl;
cout << endl;
return 0;
}
The issue is quite straight forward, you are doing the recPower function with b. In the function, if b is not 0, you call recPower with an unmodified value of b (whilst ever modifying a). This will always end up with infinite recursion which is going to overflow your stack.
A solution could be:
int recPower(double a, int b, int times) {
if (times == 0)
return a;
else
return b * recPower(a, b, --times);
}
int recPower(double a, int b) {
return recPower(a, b, b);
}
Even if you fix this, you have another problem. b can be negative, which based on your logic will continue to recurse while decrementing until it overflows and goes back to 0. You will cause this case with your first test case. You should think about the types that are allowed in this function, consider making them unsigned, or dealing explicitly with the negative b case.
I asked this question a couple of hours ago; I want to see if someone can now explain the problem.
One code is about separating items in a grocery; in the end you'll have two(2) bags; a fragileBag and a normalBag.
Other code separates passengers depending on the office they go for pickup; in the end you'll have three(3) types of passengers; ones that go to rio, ones that go to maya, and ones that request elsewhere.
Both codes use the same logic but the passenger code gives an error on a line that works perfectly on the grocery code.
Just to be clear, BOTH CODES RETURN VALUES OF STRING.
ERROR FROM THE PASSENGER CODE:
Error (active) E0304 no instance of overloaded function "std::vector<_Ty,_Alloc>::push_back [with _Ty=trans, _Alloc=std::allocator<trans>]" matches the argument list dataPractice2 C:\Users\javye\source\repos\dataPractice2\dataPractice2\main.cpp 82
and also:
Error C2664 'void std::vector<trans,std::allocator<_Ty>>::push_back(_Ty &&)': cannot convert argument 1 from 'std::string' to 'const _Ty &' dataPractice2 c:\users\javye\source\repos\datapractice2\datapractice2\main.cpp 82
//GROCERY FUNCTION
//separate function
void separateItems(vector<myBag>& newMyVector) {
for (int x = newMyVector.size() - 1; x >= 0; --x) {
if (newMyVector[x].getItem() == "eggs" || newMyVector[x].getItem() == "bread") {
fragileBag.push_back(newMyVector[x].getItem()); //NO PROBLEM HERE
newMyVector.pop_back();
}
else {
normalBag.push_back(newMyVector[x].getItem()); //OR HERE
newMyVector.pop_back();
}
}
}
//PASSENGER FUNCTION
//separate function
void separateP(vector<trans>& newMyVector) {
for (int x = newMyVector.size() - 1; x >= 0; --x) {
if (newMyVector[x].getXoLoc() == "rio") {
rioLoc.push_back(newMyVector[x].getXoLoc()); //PROBLEM HERE
newMyVector.pop_back();
}
else
if (newMyVector[x].getXoLoc() == "maya") {
mayaLoc.push_back(newMyVector[x].getXoLoc()); //HERE
newMyVector.pop_back();
}
else
elseLoc.push_back(newMyVector[x].getXoLoc()); //HERE
newMyVector.pop_back();
}
}
//GROCERY FULL CODE
//HEADER
#pragma once
#include<iostream>
#include<vector>
#include<string>
using namespace std;
#ifndef BAG_H
#define BAG_H
class myBag {
public:
myBag(); //default constructor
myBag(string anItemName); //overload constructor
void addItem(string anItemName); //mutator
string getItem();//accessor
private:
string itemName;
};
#endif
//SOURCE
#include"bag.h"
myBag::myBag() {
addItem("");
}
myBag::myBag(string anItemName) {
addItem(anItemName);
}
void myBag::addItem(string anItemName) {
itemName = anItemName;
}
string myBag::getItem() {
return itemName;
}
//MAIN
#include"bag.h"
void inputItems(vector<myBag>&); //input data function prototype
void displayQuantity(vector<myBag>&); //display data function prototype
void separateItems(vector<myBag>&); //function that separates items; func prototype
void fragBag(vector<myBag>&); //fragile bag function prototype
void norBag(vector<myBag>&); //normal bag function prototype
vector<myBag> myVector; //main vector
vector<myBag> fragileBag, normalBag; //seconday vectors
string item; //global item variable
int main() {
int option;
try {
do {
cout << "\tMENU"
<< endl << "1) Input Items"
<< endl << "2) Display Quantity"
<< endl << "3) Separate (IMPORTANT)"
<< endl << "4) Display Items in Fragile Bag"
<< endl << "5) Display Items in Normal Bag"
<< endl << "6) Exit Program"
<< endl << endl << "Choose: ";
cin >> option;
if (option > 6) {
throw 404;
}
switch (option) {
case 1: //input
system("cls");
inputItems(myVector);
system("pause");
system("cls");
break;
case 2://display
system("cls");
displayQuantity(myVector);
system("pause");
system("cls");
break;
case 3: //separate
system("cls");
separateItems(myVector);
system("pause");
system("cls");
break;
case 4: //fragile
system("cls");
fragBag(myVector);
system("pause");
system("cls");
break;
case 5: //normal
system("cls");
norBag(myVector);
system("pause");
system("cls");
break;
case 6: //exit
exit(0);
}
} while (option != 6);
}
catch(int x){
cout << "ERROR, OPTION DOESN'T EXITS" << endl;
system("pause");
}
}
//input function
void inputItems(vector<myBag>& newMyVector) {
do {
cout << "Enter grocery items || enter letter X to stop: ";
cin >> item;
if (item != "x")
newMyVector.push_back(myBag(item));
} while (item != "x");
}
//display function
void displayQuantity(vector<myBag>& newMyVector) {
try {
for (int x = 0; x < newMyVector.size(); ++x) {
if (x == 0) {
cout << "Store bag has " << newMyVector.size() << " items in it. These are: " << endl;
}
cout << newMyVector[x].getItem() << endl;
}
if (newMyVector.empty())
throw 404;
}
catch (int x) {
cout << "ERROR " << x << " ,QUANTITY NOT FOUND" << endl;
}
}
//separate function
void separateItems(vector<myBag>& newMyVector) {
for (int x = newMyVector.size() - 1; x >= 0; --x) {
if (newMyVector[x].getItem() == "eggs" || newMyVector[x].getItem() == "bread") {
fragileBag.push_back(newMyVector[x].getItem()); //PROBLEM WOULD APPEAR HERE, BUT DOESN'T, UNLIKE THE OTHER CODE
newMyVector.pop_back();
}
else {
normalBag.push_back(newMyVector[x].getItem());
newMyVector.pop_back();
}
}
}
//fragile bag function
void fragBag(vector<myBag>& newMyVector) {
try {
for (int x = 0; x < fragileBag.size(); ++x) {
if (x == 0) {
cout << "The fragile bag has " << fragileBag.size() << " items in it. These are: " << endl;
}
cout << fragileBag[x].getItem() << endl;
}
if (fragileBag.empty()) {
throw 404;
}
}
catch (int x) {
cout << "ERROR " << x << " ,FRAGILE BAG EMPTY" << endl;
}
}
//normal bag function
void norBag(vector<myBag>& newMyVector) {
try {
for (int x = 0; x < normalBag.size(); ++x) {
if (x == 0) {
cout << "The normal bag has " << normalBag.size() << " items in it. These are: " << endl;
}
cout << normalBag[x].getItem() << endl;
}
if (normalBag.empty()) {
throw 404;
}
}
catch (int x) {
cout << "ERROR " << x <<" , NORMAL BAG EMPTY" << endl;
}
}
//PASSENGER FULL CODE
//HEADER
#pragma once
#include<iostream>
#include<vector>
#include<string>
using namespace std;
#ifndef TRANSPORT_H
#define TRANSPORT_H
class trans {
public:
trans();
trans(string aName, string anXoLoc, string anXfLoc, string aTime, string aCellNum);
void setName(string aName);
void setXoLoc(string anXoLoc);
void setXfLoc(string anXfLoc);
void setTime(string aTime);
void setCellNum(string aCellNum);
string getName();
string getXoLoc();
string getXfLoc();
string getTime();
string getCellNum();
private:
string name;
string xoLoc; //offices
string xfLoc; //destination
string time;
string cellNum;
};
//SOURCE
#include"transport.h"
trans::trans() {
setName("");
setXoLoc("");
setXfLoc("");
setTime("");
setCellNum("");
}
trans::trans(string aName, string anXoLoc, string anXfLoc, string aTime, string aCellNum) {
setName(aName);
setXoLoc(anXoLoc);
setXfLoc(anXfLoc);
setTime(aTime);
setCellNum(aCellNum);
}
void trans::setName(string aName) {
name = aName;
}
void trans::setXoLoc(string anXoLoc) {
xoLoc = anXoLoc;
}
void trans::setXfLoc(string anXfLoc) {
xfLoc = anXfLoc;
}
void trans::setTime(string aTime) {
time = aTime;
}
void trans::setCellNum(string aCellNum) {
cellNum = aCellNum;
}
string trans::getName() {
return name;
}
string trans::getXoLoc() {
return xoLoc;
}
string trans::getXfLoc() {
return xfLoc;
}
string trans::getTime() {
return time;
}
string trans::getCellNum() {
return cellNum;
}
#endif
//MAIN
#include"transport.h"
void inputInfo(vector<trans> &);
void displayInput(vector<trans>&);
void separateP(vector<trans>&);
void rio(vector<trans>&);
void maya(vector<trans>&);
void elsewhere(vector<trans>&);
vector<trans> myVector;
vector<trans> rioLoc, mayaLoc, elseLoc;
string newName;
string newXoLoc; //offices
string newXfLoc; //destination
string newTime;
string newCellNum;
//main not ready. Creating each function one by one to them make it look nice
int main() {
int option;
do {
cout << "MENU"
<< endl << "1) input "
<< endl << "2) output "
<< endl << "3) separate"
<< endl << "4) rio passengers"
<< endl << "5) maya passengers"
<< endl << "6) elsewhere passengers";
cin >> option;
switch(option){
case 1:
inputInfo(myVector);
break;
case 2:
displayInput(myVector);
break;
case 3:
separateP(myVector);
break;
case 4:
rio(myVector);
break;
case 5:
maya(myVector);
break;
case 6:
elsewhere(myVector);
break;
case 7:
exit(0);
}
} while (option != 7);
system("pause");
}
void inputInfo(vector<trans> &newMyVector) {
int charSize;
cout << "How many passangers to register: ";
cin >> charSize;
for (int x = 0; x < charSize; ++x) {
cout << "Name of passanger: ";
cin >> newName;
cout << "Office: ";
cin >> newXoLoc;
cout << "Destination: ";
cin >> newXfLoc;
cout << "Time of pickup: ";
cin >> newTime;
cout << "Cellphone: ";
cin >> newCellNum;
if (charSize != 0)
newMyVector.push_back(trans(newName, newXoLoc, newXfLoc, newTime, newCellNum));
}
}
void displayInput(vector<trans>& newMyVector) {
for (int x = 0; x < newMyVector.size(); ++x) {
if (x == 0) {
cout << "There are " << newMyVector.size() << " passengers. These are: " << endl;
}
cout << "-----------------------------Passenger #" << x + 1 << endl;
cout << newMyVector[x].getName() << endl;
cout << newMyVector[x].getXoLoc() << endl;
cout << newMyVector[x].getXfLoc() << endl;
cout << newMyVector[x].getTime() << endl;
cout << newMyVector[x].getCellNum() << endl;
}
}
void separateP(vector<trans>& newMyVector) {
for (int x = newMyVector.size() - 1; x >= 0; --x) {
if (newMyVector[x].getXoLoc() == "rio") {
rioLoc.push_back(newMyVector[x]);
newMyVector.pop_back();
}
else
if (newMyVector[x].getXoLoc() == "maya") {
mayaLoc.push_back(newMyVector[x]);
newMyVector.pop_back();
}
else
elseLoc.push_back(newMyVector[x]);
newMyVector.pop_back();
}
}
void rio(vector<trans>& newMyVector) {
for (int x = 0; x < rioLoc.size(); ++x) {
if (x == 0) {
cout << "Num. of passangers to pickup in Rio Piedras is " << rioLoc.size() << " , these are: " << endl;
}
cout << rioLoc[x].getName() << endl;
cout << rioLoc[x].getXoLoc() << endl;
cout << rioLoc[x].getXfLoc() << endl;
cout << rioLoc[x].getTime() << endl;
cout << rioLoc[x].getCellNum() << endl;
}
}
void maya(vector<trans>& newMyVector) {
for (int x = 0; x < mayaLoc.size(); ++x) {
if (x == 0) {
cout << "Num. of passangers to pickup in Mayaguez is " << mayaLoc.size() << " , these are: " << endl;
}
cout << mayaLoc[x].getName() << endl;
cout << mayaLoc[x].getXoLoc() << endl;
cout << mayaLoc[x].getXfLoc() << endl;
cout << mayaLoc[x].getTime() << endl;
cout << mayaLoc[x].getCellNum() << endl;
}
}
void elsewhere(vector<trans>& newMyVector) {
for (int x = 0; x < elseLoc.size(); ++x) {
if (x == 0) {
cout << "Num. of passangers to pickup in elsewhere is " << elseLoc.size() << " , these are: " << endl;
}
cout << elseLoc[x].getName() << endl;
cout << elseLoc[x].getXoLoc() << endl;
cout << elseLoc[x].getXfLoc() << endl;
cout << elseLoc[x].getTime() << endl;
cout << elseLoc[x].getCellNum() << endl;
}
}
To explain why the second code does not work I first have to explain why the first code appears to work.
myBag::myBag(string anItemName)
can make a bag out of a string. It is a Conversion Constructor. So when
fragileBag.push_back(newMyVector[x].getItem());
is compiled, the compiler quietly inserts a call to the myBag(string) constructor and you get something more like
fragileBag.push_back(myBag(newMyVector[x].getItem()));
which makes no sense logically. It says turn an item in a bag into a bag with one item and insert this new bag into still another bag, fragileBag.
When you look more closely at myBag, you see that it isn't a bag at all. It is a single item and should be renamed to myItem or discarded all together in favour of an all-new all-different myBag that is a wrapper around a vector of string where the strings represent items. This makes
myBag fragileBag;
the real bag.
In other words, the only reason the working code works is it doesn't actually do what the naming implies it does. The code compiles and produces the expected result, but is semantically troubled.
This leads to the confusion with
rioLoc.push_back(newMyVector[x].getXoLoc());
rioLoc is a vector<trans> and can only hold trans. There is no trans::trans(string) to convert a string to a trans so the faulty logic of the grocery code is exposed. As bag and item have been intertwined in grocery, passenger and transport are combined here.
The fix for grocery described above is relatively straight forward. Passenger will need a slightly different solution with both a passenger class to describe the passengers and a transport class to describe the means of transport. transport will have a vector<passenger> member to contain its passengers as well as methods to add and remove the passengers and possibly book-keeping to track the location of the transport, details incompletely specified by the question.
Both codes are pushing string values into a vector that does not hold string values.
Your grocery code uses a vector of myBag objects. The code works because myBag has a non-explicit constructor that takes a single string as input, so the compiler is able to implicitly construct a temporary myBag object to push into the vector.
Your passenger code uses a vector of trans objects. The code fails because trans does not have a constructor that takes a single string as input, so the compiler cannot construct a temporary trans to push into the vector.
I'm not quite sure why the answer for the larger string ("cat" and "dog") is not consistent. I was doing some things with Linked Lists and the use of templates. My curiosity got me to revise templates and function overloading. If anyone can explain what is going on, I would appreciate it.
Thank you.
#include <iostream>
using namespace std; // for the sake of simplicity. (otherwise, std::)
// Function overloading and the use of templates
// overloading the function larger
int larger(int, int);
char larger(char, char);
double larger(double, double);
string larger(string, string);
template <class elementType>
elementType anyLarger(elementType parameter1, elementType parameter2);
int main() {
cout << endl;
cout << "Function Overloading" << endl;
cout << "larger(15, 27) = " << larger(15, 27) << endl;
cout << "larger('X', 'P') = " << larger('X', 'P') << endl;
cout << "larger(4.9, 3.2) = " << larger(4.9, 3.2) << endl;
cout << "larger(cat, dog) = " << larger("cat", "dog") << endl;
cout << endl;
cout << "Using the function template to find the larger of two items" << endl;
cout << "anyLarger(15, 27) = " << anyLarger(15, 27) << endl;
cout << "anyLarger('X', 'P') = " << anyLarger('X', 'P') << endl;
cout << "anyLarger(4.9, 3.2) = " << anyLarger(4.9, 3.2) << endl;
cout << "anyLarger(cat, dog) = " << anyLarger("cat", "dog") << endl;
cout << endl;
cout << "Compare two strings: cat, dog" << endl;
if ("cat" >= "dog") {
cout << "cat is greater than dog" << endl;
}
else {
cout << "dog is greater than cat" << endl;
}
cout << endl;
string strCat = "cat";
string strDog = "dog";
cout << "string strCat = cat" << endl;
cout << "string strDog = dog" << endl;
if (strCat >= strDog) {
cout << "strCat is greater than strDog" << endl;
}
else {
cout << "strDog is greater than strCat" << endl;
}
cout << endl;
} // end main
// Overloading larger
int larger(int x, int y) {
if (x >= y)
return x;
else
return y;
}
char larger(char a, char b) {
if (a >= b)
return a;
else
return b;
}
double larger(double p, double q) {
if (p >= q)
return p;
else
return q;
}
string larger(string y, string z) {
if (y >= z)
return y;
else
return z;
}
// Defining the template function
template <class elementType>
elementType anyLarger(elementType parameter1, elementType parameter2)
{
if (parameter1 >= parameter2)
return parameter1;
else
return parameter2;
}
Here is the result after running the program.
Function Overloading
larger(15, 27) = 27
larger('X', 'P') = X
larger(4.9, 3.2) = 4.9
larger(cat, dog) = dog
Using the function template to find the larger of two items
anyLarger(15, 27) = 27
anyLarger('X', 'P') = X
anyLarger(4.9, 3.2) = 4.9
anyLarger(cat, dog) = cat
Compare two strings: cat, dog
cat is greater than dog
string strCat = cat
string strDog = dog
strDog is greater than strCat
==============================================
Update: Made some changes and used strcmp
#include <iostream>
#include <string.h>
using namespace std;
// Function overloading and the use of templates
// overloading the function larger
int larger(int, int);
char larger(char, char);
double larger(double, double);
string larger(string, string);
template <class elementType>
elementType anyLarger(elementType parameter1, elementType parameter2);
int main(){
cout << endl;
cout << "// Function Overloading" << endl;
cout << "larger(15, 27) = " << larger(15, 27) << endl;
cout << "larger('X', 'P') = " << larger('X', 'P') << endl;
cout << "larger(4.9, 3.2) = " << larger(4.9, 3.2) << endl;
cout << "larger(\"cat\", \"dog\") = " << larger("cat", "dog") << endl;
cout << endl;
cout << "// Using the function template to find the larger of two items" << endl;
cout << "anyLarger(15, 27) = " << anyLarger(15, 27) << endl;
cout << "anyLarger('X', 'P') = " << anyLarger('X', 'P') << endl;
cout << "anyLarger(4.9, 3.2) = " << anyLarger(4.9, 3.2) << endl;
cout << "anyLarger(\"cat\", \"dog\") = " << anyLarger("cat", "dog") << endl;
cout << endl;
cout << "// Compare two strings using >= : \"cat\", \"dog\"" << endl;
if ("cat" >= "dog") {
cout << "\"cat\" is greater than \"dog\"" << endl;
}
else {
cout << "\"dog\" is greater than \"cat\"" << endl;
}
cout << endl;
cout << "// The use of variables: strCat and strDog. Compare using >=" << endl;
string strCat = "cat";
string strDog = "dog";
cout << "string strCat = \"cat\";" << endl;
cout << "string strDog = \"dog\";" << endl;
if (strCat >= strDog) {
cout << "strCat is greater than strDog" << endl;
}
else {
cout << "strDog is greater than strCat" << endl;
}
cout << endl;
cout << "// Using strcmp. strcmp(\"cat\", \"dog\")" << endl;
int result = strcmp("cat", "dog");
if (result > 0) {
cout << "\"cat\" is greater than \"dog\"" << endl;
}
else {
cout << "\"dog\" is greater than \"cat\"" << endl;
}
}
// Overloading larger
int larger(int x, int y) {
if (x >= y)
return x;
else
return y;
}
char larger(char a, char b) {
if (a >= b)
return a;
else
return b;
}
double larger(double p, double q) {
if (p >= q)
return p;
else
return q;
}
string larger(string y, string z) {
if (y >= z)
return y;
else
return z;
}
// Defining the template function
template <class elementType>
elementType anyLarger(elementType parameter1, elementType parameter2)
{
if (parameter1 >= parameter2)
return parameter1;
else
return parameter2;
}
================
Update: Output
// Function Overloading
larger(15, 27) = 27
larger('X', 'P') = X
larger(4.9, 3.2) = 4.9
larger("cat", "dog") = dog
// Using the function template to find the larger of two items
anyLarger(15, 27) = 27
anyLarger('X', 'P') = X
anyLarger(4.9, 3.2) = 4.9
anyLarger("cat", "dog") = cat
// Compare two strings using >= : "cat", "dog"
"cat" is greater than "dog"
// The use of variables: strCat and strDog. Compare using >=
string strCat = "cat";
string strDog = "dog";
strDog is greater than strCat
// Using strcmp. strcmp("cat", "dog")
"dog" is greater than "cat"
You are not lexicographically comparing strings in both cases.
"cat" >= "dog"
This is comparing char pointers because the type of the literals "cat" and "dog" is const char*. It could give either result, depending on how the compiler decided to materialize the literals.
To lexicographically compare C-style strings (including literals like these) the function strcmp must be used instead.
strCat >= strDog
This is comparing strings lexicographically because std::string provides comparison operators that explicitly implement this kind of comparison.
"cat" >= "dog"
You are comparing pointers but not the actual values. Use strcmp.
That's because string literal (e.g. "cat") isn't of type std::string. You're doing a pointer comparison on two unrelated arrays of const char.
The literal string "cat" and "dog" are actually pointers to arrays of characters when you come to compare them, so the greatest will be the one that happens to be stored in memory at a higher location.
Your string larger(string y, string z) works because std::string can be constructed from a char* and so "cat" and "dog" get converted to std::string objects before being compared.
The template function, on the other hand, accepts them as their actual types which, when passed as parameters, become const char* and only their addresses get compared.
As others have already mentioned, in your line
cout << "anyLarger(cat, dog) = " << anyLarger("cat", "dog") << endl;
you are invoking anyLarger<const char &[]>, i.e. you call anyLarger with string literal arguments, which indeed boils down to comparing pointers instead of strings. You can fix this by either calling your function with std::string arguments by one of the following lines:
larger("cat", "dog");
anyLarger<std::string>("cat", "dog");
anyLarger(std::string("cat"), std::string("dog"));
anyLarger("cat"s, "dog"s); // C++14
or you could do a template specialization for string literals (or just any C-type strings, whatever you choose):
template <>
elementType anyLarger<char*>(char* parameter1, char* parameter2)
{
if (strcmp(parameter1, parameter2) >= 0)
return parameter1;
else
return parameter2;
}
I have the next function and i want to print some parameters separated by a comma, my problem is that the console didn't show anything when "parametro[i] = linea[i]" in the FOR iteration.
Example:
Parametro 1: []
void funcionSeparadora (string linea){
int numParametros = 1;
string parametro;
for (int unsigned i=0;i<linea.length();i++){
if (linea[i] == ','){
cout <<"Parámetro "<<numParametros<<": "<<"["<< parametro <<"]"<< '\n';
numParametros++;
}
else (parametro[i] = linea[i]);
}
}
Mostly the way you handle the filling of parametro was wrong. Fixed version:
void funcionSeparadora(string linea) {
int numParametros = 1;
string parametro;
for (int unsigned i = 0; i<linea.length(); i++) {
if (linea[i] == ',') {
cout << "Parámetro " << numParametros << ": " << "[" << parametro << "]" << '\n';
numParametros++;
parametro.clear();
}
else {
parametro += linea[i];
}
}
if (!parametro.empty()) {
cout << "Parámetro " << numParametros << ": " << "[" << parametro << "]" << '\n';
}
}
Points you missed
Use curly brackets in else condition
Use size_t instead of unsigned in in for loop
initialize the parametro variable with necessary length
Try this
#include <iostream>
#include <string>
using namespace std;
void funcionSeparadora(string linea) {
int numParametros = 1;
string parametro(linea.length(),' ');
for (size_t i = 0; i < linea.length(); i++) {
if (linea[i] == ',') {
cout << "Parámetro " << numParametros << ": " << "[" << parametro << "]" << endl;
numParametros++;
}
else {
parametro[i] = linea[i];
}
}
}
int main()
{
funcionSeparadora("what is this,");
system("pause");
return 0;
}
I am trying to access a member of one class in another class. I am fairly new to C++ so forgive me if this is an easy fix but I cannot find the answer, so I came here.
In this instance I would like to call "init();" from class CGuessNumber and member CheckNumber.
Here is my code.
#include <iostream>
#include <ctime>
#include <cstdlib>
class CGuessNumber
{
public:
int GenerateNumber()
{
return rand() % 100 + 1;
}
void checkNumber(int guess, int answer, int &attempts)
{
if (guess < answer)
{
std::cout << "TOO LOW, TRY AGAIN" << "\n" << "TRYS LEFT: " << attempts << "\n";
attempts--;
}else if(guess > answer)
{
std::cout << "TOO HIGH, TRY AGAIN" << "\n" << "TRYS LEFT: " << attempts << "\n";
attempts--;
}else if(guess == answer)
{
std::cout << "YOU WON!" << "\n" << "TRYS LEFT: " << attempts << "\n";
}
if (attempts <= 0)
{
std::cout << "YOU LOST!" << "\n" << "TRYS LEFT: " << attempts << "\n";
CGAME::init(answer, attempts);
}
}
}Number;
class CGAME
{
public:
void init(int &answer, int &attempts)
{
answer = Number.GenerateNumber();
attempts = 5;
};
int newGame()
{
srand (time(NULL));
int intAnswer, playerGuess, trys;
init(intAnswer, trys);
while(intAnswer != playerGuess and trys > 0)
{
std::cin >> playerGuess;
Number.checkNumber(playerGuess, intAnswer, trys);
}
};
}ONewGame;
int main()
{
CGAME ONewGame
ONewGame.newGame();
return 0;
}
I think, this is what you're looking for
Basically you can pass a pointer which points to one object into a constructor of the other. In this case we just pass a pointer to CGuessNumber into the CGAME constructor, we also store this pointer in a private field so we can use it. Then you can use this pointer to call methods.
working example (pointer->method syntax)
working example (reference.method syntax)
#include <iostream>
#include <ctime>
#include <cstdlib>
class CGuessNumber
{
public:
int GenerateNumber()
{
return rand() % 100 + 1;
}
void checkNumber(int guess, int answer, int &attempts)
{
if (guess < answer)
{
std::cout << "TOO LOW, TRY AGAIN" << "\n" << "TRYS LEFT: " << attempts << "\n";
attempts--;
}else if(guess > answer)
{
std::cout << "TOO HIGH, TRY AGAIN" << "\n" << "TRYS LEFT: " << attempts << "\n";
attempts--;
}else if(guess == answer)
{
std::cout << "YOU WON!" << "\n" << "TRYS LEFT: " << attempts << "\n";
}
if (attempts <= 0)
{
std::cout << "YOU LOST!" << "\n" << "TRYS LEFT: " << attempts << "\n";
}
}
};
class CGAME
{
public:
CGAME(CGuessNumber* pNumber)
{
m_number = pNumber;
}
void init(int &answer, int &attempts)
{
answer = m_number->GenerateNumber();
attempts = 5;
};
void newGame()
{
srand (time(NULL));
int intAnswer, playerGuess, trys;
init(intAnswer, trys);
while(intAnswer != playerGuess and trys > 0)
{
std::cin >> playerGuess;
m_number->checkNumber(playerGuess, intAnswer, trys);
}
};
private:
CGuessNumber* m_number;
};
int main()
{
CGuessNumber* pGnum = new CGuessNumber();
CGAME* ONewGame = new CGAME(pGnum);
ONewGame->newGame();
return 0;
}
Let me just address the syntax errors.
In the checkNumber() function:
...
CGAME::init(answer, attempts);
...
There are 2 problems with this:
CGAME is not declared yet, so the compiler doesn't know it exists, or what it is. To avoid this, usually all the classes are declared at the top (or in a header file) and all there functions are defined later.
You can't call a member function of a class without an object, unless it's a static function. This function can be static as it doesn't use member variables (there are design issues, but lets ignore them for now).
Also in main() you missed a ';', but I think you already know that :-)
So, applying these changes:
#include <iostream>
#include <ctime>
#include <cstdlib>
// only declaring the classes here
class CGAME
{
public:
static void init(int &answer, int &attempts);
int newGame();
}ONewGame;
class CGuessNumber
{
public:
int GenerateNumber();
void checkNumber(int guess, int answer, int &attempts);
}Number;
// defining all the class member functions now
int CGAME::newGame()
{
srand (time(NULL));
int intAnswer, playerGuess, trys;
init(intAnswer, trys);
while(intAnswer != playerGuess and trys > 0)
{
std::cin >> playerGuess;
Number.checkNumber(playerGuess, intAnswer, trys);
}
}
int CGuessNumber::GenerateNumber()
{
return rand() % 100 + 1;
}
void CGuessNumber::checkNumber(int guess, int answer, int &attempts)
{
if (guess < answer)
{
std::cout << "TOO LOW, TRY AGAIN" << "\n" << "TRYS LEFT: " << attempts << "\n";
attempts--;
}else if(guess > answer)
{
std::cout << "TOO HIGH, TRY AGAIN" << "\n" << "TRYS LEFT: " << attempts << "\n";
attempts--;
}else if(guess == answer)
{
std::cout << "YOU WON!" << "\n" << "TRYS LEFT: " << attempts << "\n";
}
if (attempts <= 0)
{
std::cout << "YOU LOST!" << "\n" << "TRYS LEFT: " << attempts << "\n";
CGAME::init(answer, attempts);
}
}
void CGAME::init(int &answer, int &attempts)
{
answer = Number.GenerateNumber();
attempts = 5;
}
int main()
{
CGAME ONewGame;
ONewGame.newGame();
return 0;
}