/* This program */
using namespace std;
#include <iostream>
#include <cmath>
#include <iomanip>
#include <fstream>
void readit();
void calcit(int, int);
void writeit(float, float, float);
int distvels[4] = {15, 25, 35, 45};
int main()
{
readit();
system("pause");
return 0;
}
void readit()
{
int targetdist, angl;
cout << "Enter the distance (meters) to the target:" << endl;
cin >> targetdist;
cout << "Enter the angle to fire the cannon:" << endl;
cin >> angl;
cout << "\n---------------\n\n";
calcit (targetdist, angl);
}
void calcit(int targetdist, int angl)
{
double distvals[4];
double tyme[4];
double maxhite[4];
for (int i=0; i<4; i++) {
distvals[i] = (2 * sin(angl) * cos(angl) * (distvels[i] * distvels[i]))/9.8;
tyme[i] = (2 * cos(angl) * distvels[i])/9.8;
maxhite[i] = ((cos(angl) * cos(angl)) * (distvels[i] * distvels[i]))/9.8;
}
writeit(distvals, tyme, maxhite);
}
void writeit(float distvals[4], float tyme[4], float maxhite[4])
{
cout << "Velocity " << "time " << "height " << "distance " <<endl;
for (int i=0; i<4; i++) {
cout << distvals[i] << " " << tyme[i] << " " << maxhite[i] << " " << endl;
}
whenever I run the program I keep getting this error code cannot convert double* to float for argument 1 to void writeit(float, float, float). I've tried everything I can think of to get rid of it with no luck. Can anyone help?
You declared the function as:
void writeit(float, float, float);
but the definition has it as:
void writeit(float distvals[4], float tyme[4], float maxhite[4])
{
// ...
}
Fix the declaration to match:
void writeit(float[4], float[4], float[4]);
It's also worth pointing out at this juncture that this doesn't do what you think it does. In fact, it's the same as this:
void writeit(float[], float[], float[]);
which is the same as this:
void writeit(float*, float*, float*);
That's because you can't pass an array by value, so it degrades into a pointer-to-the-start-of-the-array instead.
However, you can pass it by reference and keep the dimensions:
void writeit(float (&)[4], float (&)[4], float (&)[4]); // declaration
void writeit(float (&distvals)[4], float (&tyme)[4], float (&maxhite)[4]) // definition
{
// ...
}
I'd even recommend passing it as reference-to-const, as you won't be changing it:
void writeit(float (&)[4], float (&)[4], float (&)[4]);
void writeit(const float (&distvals)[4], const float (&tyme)[4], const float (&maxhite)[4])
{
// ...
}
It would also be easier if you used a std::vector<float>, but that's another discussion.
Plenty to think about there; hope it helps.
Edit Just noticed another problem, in that you're trying to pass an array of double to a function that will be expecting an array of float! Pick one and stick with it.
The error is exactly as you note -- writeit is expecting a pointer to an array of floats and you're trying to pass it an array of doubles, which are a different size. The easiest fix would be to declare the args of writeit to be arrays of doubles, so they match. Barring that, you need to copy to arrays of floats before passing (converting each element as you copy)
The function prototype is different from the function definition. So, change it to -
void writeit(double*, double*, double*);
And the function definition to -
void writeit(double distvals[], double tyme[], double maxhite[])
{
// ......
}
Notice that the array size (i.e., optional, in fact compiler won't consider it) because array decays to a pointer. It is the reason why usually array size is also sent as an argument to the functions and is a good practice.
Related
I want to display the range of x and f(x) and keep f(x) in array but i always get this error:
invalid type 'float*[float]' for array subscript
can someone help me? I'm still stuck.
Here's the code:
#include <iostream>
#include <cmath>
#include <math.h>
using std::cin;
using std::cout;
using namespace std;
void displayValue(float funx[], float j, float x);
int main()
{
float num9[]={};
float a, r;
displayValue(num9, a, r);
return 0;
}
void displayValue(float funx[], float j, float x)
{
float i;
cout << "Please enter range of x: " << endl;
for (i=0; i<1; i++)
{
cin >> x >> j;
}
for (float i=1; i<=160.5; i++)
{
x+=0.5;
funx[i]=1/sin(x)+1/tan(x);
//1.2 Display f(x) and x within the range
}cout << x << " = " << funx[i] << "\n";
}
The problems you're trying to solve aren't actually problems you need to solve. There's a lot going wrong in this code that can simply be removed because you're using the wrong tools.
You don't need an array here. If you did you'd need to allocate one, not pass in something that's empty, or you'd be using it out of bounds. In C++ for arrays like this use std::vector.
That being said, here's a simplified version of the code:
#include <iostream>
#include <cmath>
#include <math.h>
// Don't add "using namespace std", that separation exists for a reason.
// Separate the math function to make it clear what's being done
float f(const float x) {
return 1/sin(x)+1/tan(x);
}
// Define your functions before they're used to avoid having to declare
// then later define them.
void displayValue(const float min, const float max, const float step = 0.5)
{
for (float x = min; x <= max; x += step)
{
// Note how the f(x) function here is a lot easier to follow
std::cout << "f(" << x << ") = " << f(x) << std::endl;
}
}
int main()
{
std::cout << "Please enter range of x: " << std::endl;
// Capture the range values once and once only
float min, max;
std::cin >> min >> max;
// Display over the range of values
displayValue(min, max);
return 0;
}
There's some important C++ fundamentals here:
float num9[]={}; is not an empty array that you can later add to, it is a permanently zero-length array, or in other words, it's useless.
Pay close attention to the variables you've defined and avoid defining them twice in the same scope.
Turn on all your compiler warnings while you're learning to be alerted to potential problems. C++ is full of nuances and gotchas.
This question already has an answer here:
Using float gives "call to overloaded function is ambiguous" error [duplicate]
(1 answer)
Closed 6 years ago.
I'm learning C++ through Sololearn. I have a doubt about function overloading
this is the code
#include<iostream>
using namespace std;
void printSomething(int x) {
cout << "I'm printing an integer " << x << endl;
}
void printSomething(float x) {
cout << "I'm printing a float " << x << endl;
}
int main() {
int a =3;
float b = 2.65;
printSomething(a);
printSomething(b);
return 0;
}
it gives output as
I'm printing an integer 3
I'm printing a float 2.65
but if I directly give argument when calling function
like this
#include<iostream>
using namespace std;
void printSomething(int x) {
cout << "I'm printing an integer " << x << endl;
}
void printSomething(float x) {
cout << "I'm printing a float " << x << endl;
}
int main() {
printSomething(3);
printSomething(2.65);
return 0;
}
i get following error
..\Playground: In function 'int main()':
..\Playground:19:24: error: call of overloaded 'printSomething(double)' is ambiguous
printSomething(2.65);
^
..\Playground:19:24: note: candidates are:
..\Playground:5:6: note: void printSomething(int)
void printSomething(int x) {
^
..\Playground:9:6: note: void printSomething(float)
void printSomething(float x) {
^
but if I change
void printSomething(float x) {
cout << "I'm printing a float " << x << endl;
}
to
void printSomething(double x) {
cout << "I'm printing a float " << x << endl;
}
I will get output as
I'm printing a float 2.65
why is it?
but if it's only the integer it works fine
#include<iostream>
using namespace std;
void printSomething(int x) {
cout << "I'm printing an integer " << x << endl;
}
void printSomething(float x) {
cout << "I'm printing a float " << x << endl;
}
int main() {
printSomething(3);
return 0;
}
Result
I'm printing an integer 3
Why isn't this working with float
Thankyou
2.65 is not a float literal, it's a double literal.
So the compiler doesn't know whether you want to convert the double to a float or an int and so issues the error.
In your first case, when writing float b = 2.65; the compiler assumes you know what you're doing, and calling the overload with b is unambiguous.
If you had written printSomething(2.65f); then that would also have been unambiguous: 2.65f is a float literal.
2.65 is considered a double. But you didn't provide an overload void printSomething(double x). Therefore the compiler must cast the value and it doesn't know if it should cast to float or int (both with precision loss`).
If you write 2.65f it is considered a float and it should work.
The reason for that is the conversion rules and overload resolution strategy. If C++ is unable to find an exact match on parameters, it looks for a conversion. The best conversion is an implicit one, that is widening (casting a data type to one that can hold all the values of the original type and potentially more), then a narrowing conversion (casting to a smaller data type, which may cause errors or loss of precision for some values), then a user-defined conversion.
As literal 2.65 is of type double, the compiler looks for conversions. There are two: double -> float and double -> int. They are both narrowing, which means they are equally good. The compiler is unable to pick the best one, thus reports an error.
To remedy this, you can either:
define overload for double as you did
use a float literal (2.65f) instead of a double
I am very new to programming, and am near the end of this program, but cannot quite finish the last detail, which I have been stuck on. I am attempting to switch what shape pointer *sp is pointing to, and it seems to me that what I am doing should work, since rectangle and circle both are shapes; however, when I compile, only the value of the color changes. The area of the circle prints instead of the area of the rectangle and the perimeter prints 0. Any help would be greatly appreciated!
#include <iostream>
#include <string>
using namespace std;
double const pi = 3.1519;
class shape {
public:
shape() {};
shape(string);
virtual double getCircumference() {
return 0;
};
virtual double getPerimeter() {
return 0;
};
virtual double getArea() {
return 0;
};
string getColor();
protected:
string color;
};
string shape::getColor() {
return color;
}
class circle : public shape {
public:
circle(double r, string c) {
radius = r;
color = c;
};
double getArea();
double getCircumference();
private:
double radius;
};
double circle::getCircumference() {
return pi * radius * 2;
}
double circle::getArea() {
return pi * radius * radius;
}
class rectangle:public shape {
public:
rectangle(double w, double l, string c) {
width = w;
length = l;
color = c;
};
double getArea();
double getPerimeter();
private:
double length;
double width;
};
double rectangle::getPerimeter() {
return width * 2 + length * 2;
}
double rectangle::getArea() {
return length * width;
}
void change(shape *sp, shape *sp1) {
*sp = *sp1;
}
int main() {
circle mary(3.2, "Green");
shape *sp = new circle(4.5, "Yellow");
cout << "Circle #1 is " << mary.getColor() << endl;
cout << "Circle #1 has an area of " << mary.getArea() << endl;
cout << "Circle #1 has a circumference of " << mary.getCircumference() << endl << endl;
cout << "Circle #2 is " << sp->getColor() << endl;
cout << "Circle #2 has an area of " << sp->getArea() << endl;
cout << "Circle #2 has a circumference of " << sp->getCircumference() << endl << endl;
shape *sp1 = new rectangle(1.0, 2.1, "Red");
change(sp, sp1);
cout << "Rectangle #1 is " << sp->getColor() << endl;
cout << "Rectangle #1 has an area of " << sp->getArea() << endl;
cout << "Rectangle #1 has a perimeter of " << sp->getPerimeter() <<endl<< endl;
}
It’s important to keep in mind what is meant by various different ways of using pointers. In your program, sp refers to the pointer itself—that is, a memory location telling the computer where to find an object. The asterisk in *sp is a ‘dereference’ operator; it takes a pointer and gives you the thing that it is pointing to.
With this in mind, your line *sp = *sp1; is saying, ‘take the thing that sp is pointing to, and set it to be equal to the thing that sp1 is pointing to.’ In other words, you are changing the value of the object pointed to by sp, not the value of sp itself. To point sp at the object pointed to by sp1, you need sp = sp1; with no asterisks.
The other thing to bear in mind is that C++ by default passes function arguments by value: when the function is called, the arguments are copied, and the function operates on the copies. This means that the original arguments themselves cannot be changed by a function that works like this. Adding an ampersand to the argument declaration, like void change(shape *&sp, shape *sp1) causes the first argument to be passed by reference: the object operated on by the function is the same object that was passed in by the calling code. This allows the function to change objects passed as arguments, and for those changes to remain after the function has returned.
Sorry for the long answer: I could have given you a few lines that did what you wanted, but I thought you might appreciate an explanation of the reason why things work the way they do.
If you are trying to change the address of pointers, you must pass pointers by reference. Try this:
void change(shape *&sp, shape *&sp1)
A pointer is passed by value even if it's a pointer.
This means that you are actually passing the address by value, so the argument is a copy of the original argument.
Think about
void sum(int a, int b, int result);
void foo() {
int result;
sum(5,10,result);
}
While you expect to be able to store the result into the variable passed to the sum argument you won't be able to do it since result is passed by value and hence copied. Every modification you do to result inside the method will be local to the method.
That's exactly the same thing, a pointer is nothing more than an address, if you pass it by value then a copy of the address is passed but every modification to the local variable is just local.
That's why you must use references if you want to be able to modify their values, exactly as every other variable, so you would have
void sum(int a, int b, int& result);
void change(shape*& shape1, shape*& shape2);
This, under the hood, will pass the address to the variable which stores the address (a sort of shape**) so the function is able to know where the original argument is located and modify it directly.
Using C++, I declared the following static variable in a class SavingsAccount
static float *waitingInQueue;
But I'm not able to initialize the data pointed, I'm only able to initialize the address of the pointer as follows : float* SavingsAccount::waitingInQueue=0;
I would like the data of this pointer initialized at 0. I don't want to use a setter because I need to be able to initialized it once without using an object of the class SavingsAccount. I would like to do the following statement outside a function : *waitingInQueue=0;
Here is my header file :
#ifndef SAVINGSACCOUNT_H
#define SAVINGSACCOUNT_H
class SavingsAccount
{
public:
SavingsAccount();
float getInterestDue(){return *interestDue;};
float getAmountDue() {return *amountDue;};
int getArrivalTime() {return *arrivalTime;};
int getFinishTime() {return *finishTime;};
void setFinishTime(int newTime) {*finishTime=newTime;};
float computeInterestDue();
// compute the interest due...
float computeAmountDue();
// compute the total amount due
void waitingClient();
// increment *arrivalTime
void waitingProcess();
// increment *finishTime checking if there is not another client already processing, in that case make him wait during the previous client processing
void display();
// display the information about 1 client
void saveAccounts();
// save the information of the 20 clients
// void setWaitingInQueue(float x) {*waitingInQueue=x;}; <- can't be used
private:
float clientTable[8];
// information about a single client
static float globalTable[20][8];
static int clientCount;
float *customerID;
static float *arrivalTime;
static float *finishTime;
static const float depositType[6];
float *depositAmount;
static const float interestRate[12];
float *interestDue;
float *amountDue;
float *PtrDepType, *PtrRate;
static float *waitingInQueue;
};
#endif /* SAVINGSACCOUNT_H */
Here is my .cpp
#ifndef SAVINGSACCOUNT_CPP
#define SAVINGSACCOUNT_CPP
#include<cstdlib>
#include <iostream>
#include <ctime> // include to get the number of seconds since 1970 (srand))
#include <iomanip> // to set precision of numbers setprecision()
#ifdef WIN32
#include <windows.h> // for windows
#else
#include <unistd.h>
#endif // win32 // for unix
#include "SavingsAccount.h"
using namespace std;
float SavingsAccount::globalTable[20][8];
int SavingsAccount::clientCount=0;
const float SavingsAccount::depositType[6]={0.25, 0.5, 1, 2, 3, 5};
const float SavingsAccount::interestRate[]={1.71, 1.80, 2.07, 2.25, 2.25, 2.52, 2.70, 3.06, 3.24, 3.69, 3.60, 4.14};
float* SavingsAccount::arrivalTime;
float* SavingsAccount::finishTime;
float* SavingsAccount::waitingInQueue=0; // should be *waitingInQueue = 0;
SavingsAccount::SavingsAccount()
{
clientCount++;
int index;
srand(time(NULL)); //
index=rand()%6; //
customerID=&clientTable[0];
arrivalTime=&clientTable[1];
finishTime=&clientTable[2];
PtrDepType=&clientTable[3]; // &depositType[index]
depositAmount=&clientTable[4];
PtrRate=&clientTable[5]; // &interestRate[N]
interestDue=&clientTable[6];
amountDue=&clientTable[7];
*customerID=clientCount;
*PtrDepType=depositType[index];
*depositAmount=(rand()%49+1)*1000;
if (clientCount<=10) *PtrRate=interestRate[2*index]; // N=2*index
else *PtrRate=interestRate[2*index+1]; // N=2*index+1
}
float SavingsAccount::computeInterestDue()
{
*interestDue=*PtrDepType*(*depositAmount)**PtrRate*(1-0.2)/100;
}
float SavingsAccount::computeAmountDue()
{
*amountDue=*depositAmount+*interestDue;
}
void SavingsAccount::waitingClient()
{
if (clientCount==1) *arrivalTime=0;
else {
int milliseconds=(rand()%6+3)*1000; // random time in milliseconds
#ifdef WIN32 // for windows
Sleep(milliseconds);
#else // for unix
usleep(milliseconds * 1000); // nano seconds have to be multiplied by 1000
#endif // win32
*arrivalTime = *arrivalTime+milliseconds/1000;
}
}
void SavingsAccount::waitingProcess()
{
if(*finishTime < *arrivalTime)
{
*waitingInQueue =*arrivalTime-*finishTime;
}
int milliseconds=(rand()%6+2)*1000; // random time in milliseconds
#ifdef WIN32
Sleep(milliseconds);
#else
usleep(milliseconds * 1000);
#endif // win32
*finishTime= *arrivalTime + milliseconds/1000 + *waitingInQueue;
}
void SavingsAccount::saveAccounts()
{
globalTable[clientCount-1][0]=*customerID;
globalTable[clientCount-1][1]=*arrivalTime;
globalTable[clientCount-1][2]=*finishTime;
globalTable[clientCount-1][3]=*PtrDepType;
globalTable[clientCount-1][4]=*depositAmount;
globalTable[clientCount-1][5]=*PtrRate;
globalTable[clientCount-1][6]=*interestDue;
globalTable[clientCount-1][7]=*amountDue;
}
void SavingsAccount::display()
{
cout << setprecision(0) << setw(4) << right << clientTable[0];
cout << setprecision(0) << setw(7) << right << clientTable[1];
cout << setprecision(0) << setw(8) << right << clientTable[2];
cout << setprecision(2) << setw(10) << right << fixed << clientTable[3];
cout << setprecision(2) << setw(12) << right << clientTable[4];
cout << setprecision(2) << setw(7)<< right << clientTable[5];
cout << setprecision(2) << setw(12)<< right << clientTable[6];
cout << setprecision(2) << setw(12)<< right << clientTable[7] << endl;
}
#endif
The idea of the program is to display information about 20 clients that are arriving every x seconds (3static float *waitingInQueue; to increase the finishing time of all the client if needed.
If you have any other idea to easily simulated a queue I would be interested.
Even if *waitingInQueue = 0; were valid outside a function, it would be incorrect because you're initializing the pointer to null.
The easiest way to do what you're asking is something like this:
class SavingsAccount
{
...
private:
static float zero;
static float* waitingInQueue;
};
float SavingsAccount::zero = 0.0f;
float SavingsAccount::waitingInQueue = &SavingsAccount::zero;
You can initialise your static variable in many different ways -- but you should be asking a different question - "How can I get rid of my static variables?". static variables are often a sign that something is not quite right, and in that light I think you have a pretty large design problem here.
I'd group all your static variables into a Branch object. Then have each SavingsAccount have a pointer to their Branch. And add a newAccount() to Branch for creation. Then you have no more statics and everything is neater (and easier to test).
There also seems to be a lot of uses of pointers where non-pointer types would be OK, and cases where fixed length arrays are used, but would be improved by switching to std::vector<>
I have a little question about how default values are given to function parameters in C++. The problem I faced is probably due to my lack of understanding as to where the parameters are supposed to be declared/defined in the function prototype or the function header, or both? Codes are below with the errors noted:
#include <iostream>
using namespace std;
float volume(float l, float w, float h);
int main() {
float length;
float width;
float height;
cout << volume() << endl; // Here, with 'volume()' underlined, it says:
//no matching function for call to 'volume()'
cout << "Length: ";
cin >> length;
cout << "Width: ";
cin >> width;
cout << "Height: ";
cin >> height;
cout << "Volume = " << volume(length, width, height) << endl;
}
float volume(float l = 1, float w = 1, float h = 1){
float vol = l * w * h;
return vol;
}
In another attempt, here's what happened:
#include <iostream>
using namespace std;
float volume(float l = 1, float w = 1, float h = 1);
int main() {
float length;
float width;
float height;
cout << volume() << endl;
cout << "Length: ";
cin >> length;
cout << "Width: ";
cin >> width;
cout << "Height: ";
cin >> height;
cout << "Volume = " << volume(length, width, height) << endl;
}
float volume(float l = 1, float w = 1, float h = 1){ //Here, Xcode says that
// that the error is: Redefinition of default argument. < which I believe I understand.
float vol = l * w * h;
return vol;
}
In my last attempt, which is the one that worked, I did this:
#include <iostream>
using namespace std;
float volume(float l = 1, float w = 1, float h = 1);
int main() {
float length;
float width;
float height;
cout << volume() << endl;
cout << "Length: ";
cin >> length;
cout << "Width: ";
cin >> width;
cout << "Height: ";
cin >> height;
cout << "Volume = " << volume(length, width, height) << endl;
}
float volume(float l, float w, float h){
float vol = l * w * h;
return vol;
}
Could someone please explain to me the logic behind why the latter worked while the first two did not? Is there another way that the code would still work in the same way with the parameters specified elsewhere or the default values set in some place else? Are there any conventions or more favored practices in this area?
Adam
C++ and C are parsed top-down. When the compiler interprets a statement, it doesn't know about things it hasn't read yet.
In your first example, you declare a function called "volume", prototyped as taking 3 floats and returning a float. You then try to call a function called "volume" that takes no parameters, which doesn't exist yet (it would be a different function, since C++ supports polymorphism). You later define a function that can take 0, 1, 2, or 3 floats, but it is both too late and has an incompatible prototype to the first.
Your second example intuitively makes sense to be wrong, kind of like defining variables twice, but I don't have any specific information about why it is invalid code when the default values are identical.
Default parameters must be specified in the function prototype, which must occur prior to first usage in order for the compiler to know about it. Typically, you would put the prototypes with their default values in a header file that gets included above the code.
One thing to watch out for when dealing with default parameters from a shared header file, especially if you use it with dynamic libraries: The default values for the parameters are stored with the caller, and not the function being called. That is, if you update the function with new default values and don't rebuild the code calling that function, the old defaults will still be used by the calling code.
Adding to the above answer from Bjarne Stroustrup
A default argument is type checked at the time of the function declaration and evaluated at the time of the call. Default arguments may be provided for trailing arguments only. For example:
int f (int, int =0 , char * =0 ); // ok
int g (int =0 , int =0 , char *); // error
int h (int =0 , int , char * =0 ); // error
A default argument can be repeated in a subsequent declaration in the same scope but not changed.
For example:
void f (int x = 7 );
void f (int = 7 ); // ok
void f (int = 8 ); // error: different default arguments
void g () { void f (int x = 9 ); // ok: this declaration hides the outer one }
Declaring a name in a nested scope so that the name hides a declaration of the same name in an outer scope is error prone.
Default values could be defined in function declaration, as you done in your third attempt. This means usually they're appeared in header files, although this is not a rule.
Note that function declarations are scoped. This means that you could have more than one declaration for a function as long as they have different scopes:
void f(int);
int main() {
f(3); // argument should specified.
void f(int = 1);
f(); // calls f(1)
}
void f(int n = 2) {
}
void g() {
f(); // calls f(2)
}
In your second attempt you put default values on both declaration and definition of the function. This cause the compiler to confused because they are in the same scope.