2

I'm having trouble grasping the concept of pointers. I was given the following problem.

The square root of a number N can be approximated by repeated calculation using the formula NG = 0.5( LG + N/ LG) where NG stands for next guess and LG stands for last guess. Write a function that calculates the square root of a number using this method. The initial guess will be the starting value of LG . The program will com-pute a value for NG using the formula given. The difference between NG and LG is checked to see whether these two guesses are almost identical. If they are, NG is accepted as the square root; otherwise, the next guess ( NG ) becomes the last guess ( LG ) and the process is repeated ( another value is computed for NG, the difference is checked, and so on). The loop should be repeated until the difference is less than 0.005. Use an initial guess of 1.0.

The program must be written using pointers wherever possible both in main and in all functions. Declare pointers in main for the number whose square root is to be guessed and for the approximated square root answer which will be calculated and returned/referenced back to main by the function. The function will be a void function, so the approximated square root answer must be returned/referenced to main as an output argument of the function, i.e., to an argument in the function calling statement. You must pass to the function the actual value of the number to be guessed using a pointer.

In the function, have the user enter a "guess" number which is the user's initial guess of the square root of the number passed to the function.

(sorry about the lengthy explanation, I felt I should be thorough)

I wrote the following code:

#include <stdio.h> 
#include <math.h> 

void fctn(double *nPtr,double *NGPtr){  
    double n;
    nPtr=&n;
    double NG;
    double LG;
    NGPtr=&NG;

    printf("Enter guess\n");
    scanf_s("%lf",&LG);

    do{
        NG=(.5*(LG+n/LG));
        LG=NG;
    }while(fabs(NG*NG-n)>.005);
}

int main(){
    double *NGPtr;
    double *nPtr;

    printf("Enter number\n");
    scanf_s("%lf",&nPtr);

    fctn(NGPtr,nPtr);
    double root=*NGPtr;
    printf("The approximate root of the function is %f",root);
}

I was wondering if anyone had any ideas as to why it was not working? Thank you for reading.

Lance Hall
  • 202
  • 1
  • 9
  • Welcome to SO! What is not working? – J0e3gan Feb 23 '14 at 10:31
  • 1
    I get an error "Uninitialized variable NGPtr used". – Lance Hall Feb 23 '14 at 10:32
  • 1
    You have too many errors in your code. Why not start with something simpler? BTW there is absolutely no reason to use pointers to solve this problem. – juanchopanza Feb 23 '14 at 10:33
  • 1
    @juanchopanza makes a good point. Put a different way, why not write the simplest PoC you can to initialize, pass, and manipulate a pointer and/or what it references? A single pointer, an app entry point, and a couple calls to a simple function that accepts and tweaks a pointer should do it. With that behind you, you should be prepared to use them more extensively for this. – J0e3gan Feb 23 '14 at 10:38
  • 1
    It seems like your being asked to solve two distinct requirements: 1) solve the mathematical problem, and 2) make use of pointers. First create the functions to solve the math without worrying about the pointers, then use pointers to pass the user's data to the functions. – bvj Feb 23 '14 at 10:40
  • [This post](http://stackoverflow.com/questions/5727/what-are-the-barriers-to-understanding-pointers-and-what-can-be-done-to-overcome/5754#5754) could also be helpful. – πάντα ῥεῖ Feb 23 '14 at 10:43

4 Answers4

3
double *nPtr;

printf("Enter number\n");
scanf_s("%lf",&nPtr);

Let's look at what's happening here. First you declare a pointer to double. That pointer doesn't point anywhere. No double object has been created, only a pointer. You then pass &nPtr, which is a pointer to the pointer, to scanf_s, which attempts to read a value into the pointer. So you're asking the user to enter a memory address! That's not right.

What you want instead is to have a double object that you then read into. To do this, you should declare a double (not a pointer), and then pass a pointer to that double to scanf_s:

double n;

printf("Enter number\n");
scanf_s("%lf", &n);

You have a similar problem with NGptr too. It should just be a double NG; instead. Otherwise later, when you do *NGPtr, you will be dereferencing a pointer that doesn't point at anything.

I believe you then pass your arguments to fctn the wrong way round. The declaration suggests n should come first and NG should come second.

Since you only need to use the value of n inside the function, you should just pass it by value:

void fctn(double n, double *NGPtr){ 

Passing a pointer to NG is required because you wish to modify it inside the function, but a reference type would be nicer:

void fctn(double n, double& NG){

You then have a series of problems at the beginning of fctn. You don't need to create n and NG doubles anymore because we are passing them in to the function.

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
  • Thanks, I got it to work using the reference type, but if I change it to "void fctn(double n, double *NGPtr){", I get errors inside the function "expression must have arithmetic or unscoped enum type", and I have no idea what that means. – Lance Hall Feb 23 '14 at 11:27
  • It's hard to say without seeing the code, or at least the line that the error is referring to. Maybe you could post a new question with this problem. Did you try the function declaration with a reference argument (`double&`)? – Joseph Mansfield Feb 23 '14 at 11:32
  • Yes, it worked with the reference argument, though I must admit that I'm not entirely sure why. Maybe I just need to do more reading. I am very new to programming, but everything made perfect sense until pointers were introduced, and now I am just lost. I probably just misunderstand how they work entirely. – Lance Hall Feb 23 '14 at 11:36
  • @user3342994 Pointers always confuse new programmers for some reason. At some point it just clicks and it suddenly makes sense. I think part of it is just having the right mental model for what's happening. It's actually very simple. Everything in C++ is about creating and manipulating objects. Some objects are pointers. A declaration like `int x;` or `int* p;` creates an object. The latter creates a pointer object. The value stored in a pointer is the address of another object. An `int*` object is expected to hold the address of an `int`. You can get the address of an object with `&`. – Joseph Mansfield Feb 23 '14 at 11:50
  • @user3342994 However, just like `int x;` leaves the `int` object uninitialised, doing `int* p;` leaves the pointer uninitialised. It doesn't point anywhere. You need to give it an address of an `int` object. To do that, you need to have an `int` object of course. It doesn't automatically conjure one up for you. Since `int x;` creates an `int` object for you, you can of course do `&x` to get the address of that `int` and assign it to the pointer. – Joseph Mansfield Feb 23 '14 at 11:52
  • @user3342994 I realise now that I may have confused you by introducing the reference argument. This is simply a confusing aspect of C++: the `&` in the reference type `double&` is not the same as the "address of" operator `&`. It's the same symbol being used for a different purpose. – Joseph Mansfield Feb 23 '14 at 11:54
  • Oh, okay, that is actually exactly where I was confused, thanks. What is the purpose of the & in the reference type, then. – Lance Hall Feb 23 '14 at 12:06
  • @user3342994 Well it makes it a reference type. `double` is the type "double", `double*` is the type "pointer to double", and `double&` is the type "reference to double". It means that you should pass in a `double` object and it won't be copied. If you modify the parameter inside the function, it will modify the object outside. – Joseph Mansfield Feb 23 '14 at 12:15
1

Without giving you the code: You never "point your pointers at anything". (aka initialize them). You probably want actual doubles in main and pass pointers to those double to fctn.

John3136
  • 28,809
  • 4
  • 51
  • 69
  • +1. Your answer fits perfectly with the same-timed comment _I get an error "Uninitialized variable NGPtr used"_. – J0e3gan Feb 23 '14 at 10:34
1

At least this is going to be problematic

double n;
nPtr=&n;

since you're returning a reference to a temporary object.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
0

The program must be written using pointers wherever possible both in main and in all functions.

Is this a homework assignment? If so, your teacher must be trying to teach you code obfuscation. If you take it literally, then why not take it to the extreme and use function pointers? Instead of calling fctn, fabs, printf and scanf_s directly, declare function pointer variables.

Here's how you would use a function pointer to call printf:

int (*output_function)(char const *, ...);
output_function = printf;
output_function("%s %d", "test", 123);

The real problem with "using pointers wherever possible", however, is that the definition is an endless recursion, for in C++, there can be pointers to pointers, and pointers to pointers to pointers, and pointers to pointers to pointers to pointers, and so on... There's no real limit to the number of pointers you can use in a program.

Here's a complete example for a pointer to a function pointer:

#include <stdio.h>

int main()
{
    int (*output_function)(char const *, ...);
    int (**pointer_to_output_function)(char const *, ...);

    output_function = printf;
    pointer_to_output_function = &output_function;

    (*pointer_to_output_function)("%s %d", "test", 123);
}

This is horrible C++ programming style, of course, but so is the code example you gave. If this a real problem, forget about pointers for now. Use references or pass by value, and use <iostream> instead of printf et al.

Christian Hackl
  • 27,051
  • 3
  • 32
  • 62