Defining Functions, Passing Values In/Out

All -

First, I used to do some very simple C++ coding a few years ago - just picking it back up. Passing values, pointers, etc into and out of functions has always been confusing. I have 2 books but this still has me confused. Can someone tell me what is wrong with my definitions of functions and why it complains about the variable definitions? This is probably pretty simple...

By the way this is NOT for any class!

//
// OrbitManager_simple
//
// Created by Charles Phillips on 4/3/18.
// Copyright (c) 2018 Charles Phillips. All rights reserved.
//
// need to add in calculate apogee, perigee

#include <iostream>
#include <stdio.h> // printf
#include <errno.h> //get error numbers probably don't need them here
#include <string.h> // strtok, strcpy stuff
#include <stdlib.h> // atoi, atof

int card_number=1; // first or second card, initial value given
// add valid card number 1 or 2 check
int satellite_number=90000; // satellite number
// string international_designator="56111"; // international designator read in as string
double epoch=56180.1; // epoch time - system says this is decimal???
float inclination=30.0; // duh
float RAAN=180.0; // duh
float argument_perigee=180.0; // argument of perigee
float eccentricity=0.5; // duh
float mean_anomaly=180.0; // duh
float apogee=500; // du
float perigee=600; // duh
char answer;

// declare two functions


// is type of readFile supposed to be int???

float readFile (int* card_number, int* satellite_number, double* epoch, float* inclination, float* RAAN, float* argument_perigee, float* eccentricity, float* mean_anomaly);
void printParameters (int* satellite_number, double* epoch, float* inclination, float* RAAN, float* argument_perigee, float* eccentricity, float* mean_anomaly);

int main(void) // go to function read in parameters and output parameters
{

printf("In main now\n"); //debug step

unsigned short quit=0; // initialize quit
char answer; // get this from keyboard
char newline; // get from keyboard

while (!quit) // while quit is false, i.e. not 1
{
printf("\n What do you want to do? Enter the letter for your response.\n\n");
printf(" a) Enter orbital information\n");
printf(" b) Print the orbital information\n");
printf(" c) Take the input and display it (for testing)\n");
printf(" q: Quit\n");

scanf("%c%c", &answer, &newline); // get the user’s input,

switch (answer)

{
case 'a': printf("I will take input\n"); // now call read file function to take information
readFile (&card_number, &satellite_number, &epoch, &inclination, &RAAN, &argument_perigee, &eccentricity, &mean_anomaly);
// later add international designator as well
printf("I got the values and will stop now\n");
break; // don't go further in the switch
case 'b': printf("I will print the parameters\n"); // now call print parameters
printParameters (&satellite_number, &epoch, &inclination, &RAAN,
&argument_perigee, &eccentricity, &mean_anomaly); // & is correct
printf("I output the values and will stop now\n");
break;
case 'c': printf("I will take input\n"); // now call read file function to take information
readFile (&card_number, &satellite_number, &epoch, &inclination, &RAAN, &argument_perigee, &eccentricity, &mean_anomaly);
// later add international designator as well
printf("for test, immediately print what was just input\n");
printParameters (&satellite_number, &epoch, &inclination, &RAAN,
&argument_perigee, &eccentricity, &mean_anomaly); // & is correct
printf("I got the values and will stop now\n");
break; // don't go further in the switch

case 'q': printf("You said to quit so I will quit\n");
break;
default: printf("No valid selection, I will quit\n"); // quit
quit=1; // should stop execution
break;

} // end of switch
return 0; // return zero

} // end of while need to loop back and ask if user wants to go thru loop again


} // end of main

float readFile(int* card_number, int* satellite_number, double* epoch, float* inclination, float* RAAN, float* argument_perigee, float* eccentricity, float* mean_anomaly)

// is this a float? void?
// so where does the * go? int* card_number or int *card_number??? this should be ?? a pointer?

{

// printf("in readFile"); // debug step

printf("enter card number\n"); // information on card 1 or 2?
scanf("%i", &card_number); // incompatible with function definition??

// if card number is NOT 1 or 2, give error and ask again

printf("enter satellite number\n");
scanf("%i", &satellite_number);

// printf("enter international designator\n");
// scanf("%c", &international_designator); // must scan in a string of char

printf("enter epoch\n");
scanf("%lf", &epoch);

printf("enter inclination (for testing, not 30)\n");
scanf("%f", &inclination);

printf("enter RAAN (for testing, not 180)\n");
scanf("%f", &RAAN);

printf("enter argument of perigee(for testing, 180)\n");
scanf("%f", &argument_perigee);

printf("enter eccentricity (for testing, not .5)\n");
scanf("%f", &eccentricity);

printf("enter mean anomaly (for testing, not 180)\n");
scanf("%f", &mean_anomaly);

return 0; // need this??

} // end of readFilec
By the way, this is actually about a half of the program - I did not include printParameters but probably should have. So main() is completed in the program - it does build and run. But of course gives incorrect data.

If it is needed I could paste in the complete program.
Pick a language. Don't mix iostream and stdio.h. Your program is entirely C, so get rid of iostream.

Organize your satellite data into a struct.

Don't use global variables.

Your return 0 from main should be outside the loop.

In scanf, if the variable is already a pointer then you shoudn't use the &. That goes for strings (arrays of chars) too, since they act like pointers.

Use %s with scanf to read a whitespace-delimited string into an array of char (and don't use &).

An initial space before the %c in a scanf format causes it to skip initial whitespace (in particular any pesky newlines hanging around from the last scanf).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//
// OrbitManager.c
//
// need to add in calculate apogee, perigee

#include <stdio.h>
#include <string.h> // strtok, strcpy stuff
#include <stdlib.h> // atoi, atof

typedef struct Satellite {
    int    number;
    char   international_designator[12];
    double epoch;
    float  inclination;
    float  RAAN;
    float  argument_perigee;
    float  eccentricity;
    float  mean_anomaly;
} Satellite;

void readFile (int* card_number, Satellite *sat);
void printParameters (Satellite *sat);

int main(void) {
    int card_number = 1; // first or second card, initial value given
                         // add valid card number 1 or 2 check
    float apogee, perigee;
    char answer = 'x';
    Satellite sat;

    while (answer != 'q') {
        printf("\n What do you want to do? Enter the letter for your response.\n\n");
        printf(" a) Enter orbital information\n");
        printf(" b) Print the orbital information\n");
        printf(" c) Take the input and display it (for testing)\n");
        printf(" q) Quit\n");

        scanf(" %c", &answer);

        switch (answer) {
        case 'a':
            printf("I will take input\n");
            readFile (&card_number, &sat);
            // later add international designator as well
            printf("I got the values and will stop now\n");
            break;
        case 'b':
            printf("I will print the parameters\n");
            printParameters (&sat);
            printf("I output the values and will stop now\n");
            break;
        case 'c':
            printf("I will take input\n");
            readFile (&card_number, &sat);
            // later add international designator as well
            printf("for test, immediately print what was just input\n");
            printParameters (&sat);
            printf("I got the values and will stop now\n");
            break;
        case 'q':
            printf("You said to quit so I will quit\n");
            break;
        default:
            printf("Invalid selection. Try again.\n");
            break;
        }
    }

    return 0;
}

void printParameters (Satellite *sat) {
   printf("Satellite number: %d\n", sat->number);
}

void readFile(int* card_number, Satellite *sat) {
    printf("enter card number\n");
    scanf("%d", card_number);
    // if card number is NOT 1 or 2, give error and ask again

    printf("enter satellite number\n");
    scanf("%d", &sat->number);

    printf("enter international designator\n");
    scanf("%s", sat->international_designator);

    printf("enter epoch\n");
    scanf("%lf", &sat->epoch);

    printf("enter inclination (for testing, not 30)\n");
    scanf("%f", &sat->inclination);

    printf("enter RAAN (for testing, not 180)\n");
    scanf("%f", &sat->RAAN);

    printf("enter argument of perigee(for testing, 180)\n");
    scanf("%f", &sat->argument_perigee);

    printf("enter eccentricity (for testing, not .5)\n");
    scanf("%f", &sat->eccentricity);

    printf("enter mean anomaly (for testing, not 180)\n");
    scanf("%f", &sat->mean_anomaly);
}

Last edited on
tpb - Thank You!!! I wondered about putting this on the Beginners forum or here - I decided here since I used a variety of char, int, float, etc variables.

I must admit that I hope to improve this - eventually importing maybe 1000 satellites into a structure and outputting quantities like inclination, RAAN, apogee, perigee, etc so people can plot them.

I hope to make this available as freeware to astronomers (that track satellites) on my web page:

https://sites.google.com/site/macsatellitesoftware/home

please no snippy comments about Macintosh.

I am working to improve some tools that amateur astronomers use:

http://satobs.org/orbsoft.html

This is what it looks like now:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//
// OrbitManager.c  as modified by tpb
// copyright Charles Phillips
//
// thanks to: Cees Bassa for inspiration, tpb and brian chambers for coding
// need to add in calculate apogee, perigee in a function

#include <stdio.h>
#include <string.h> // strtok, strcpy stuff
#include <stdlib.h> // atoi, atof

typedef struct Satellite  // set up parameters
{
    int card_number; // first or second card, initial value given define in Main vice global??
    // add valid card number 1 or 2 check
    int    number;
    char   international_designator[12];  // will this read in the whole thing?
    double epoch;
    float  inclination;
    float  RAAN;
    float  argument_perigee;
    float  eccentricity;
    float  mean_anomaly;
}

Satellite;  // this is our structure

void readFile (Satellite *sat);
void printParameters (Satellite *sat);

int main(void)
{
    
   // float apogee, perigee;
    
    char answer = 'x';
    Satellite sat;      // what does this do here?
    
    while (answer != 'q') {
        printf("\n What do you want to do? Enter the letter for your response.\n\n");
        printf(" a) Enter orbital information\n");
        printf(" b) Print the orbital information\n");
        printf(" c) Take the input and display it (for testing)\n");
        printf(" q) Quit\n");
        
        scanf(" %c", &answer);
        
        switch (answer) {
            case 'a':
                printf("I will take input\n");
                readFile (&sat);
                // later add international designator as well
                printf("I got the values and will stop now\n");
                break;
            case 'b':
                printf("I will print the parameters\n");
                printParameters (&sat);
                printf("I output the values and will stop now\n");
                break;
            case 'c':
                printf("I will take input\n");
                readFile (&sat);
                // later add international designator as well
                printf("for test, immediately print what was just input\n");
                printParameters (&sat);
                printf("I got the values and will stop now\n");
                break;
            case 'q':
                printf("You said to quit so I will quit\n");
                break;
            default:
                printf("Invalid selection. Try again.\n");
                break;
        }
    }
    
    return 0;
}

void printParameters (Satellite *sat)   // prints, duh
{
    printf("card number: %d \n", sat->card_number);
    printf("Satellite number: %d\n", sat->number);
    printf("International Designator: %s \n", sat->international_designator);
    printf("Epoch Time: %lf \n", sat->epoch);
    printf("Inclination: %f \n", sat->inclination);
    printf("RAAN: %f \n", sat->RAAN);
    printf("Argument of Perigee: %f \n", sat->RAAN);
    printf("Eccentricity %f \n", sat->eccentricity);
    printf("Mean Anomaly %f \n", sat->mean_anomaly);
    
}

void readFile(Satellite *sat)  // read from keyboard, later from input file
{
    printf("enter card number\n");
    scanf("%d", &sat->card_number);
    // if card number is NOT 1 or 2, give error and ask again
    
    printf("enter satellite number\n");
    scanf("%d", &sat->number);
    
    printf("enter international designator\n");
    scanf("%s", sat->international_designator);
    
    printf("enter epoch\n");
    scanf("%lf", &sat->epoch);
    
    printf("enter inclination (for testing, not 30)\n");
    scanf("%f", &sat->inclination);
    
    printf("enter RAAN (for testing, not 180)\n");
    scanf("%f", &sat->RAAN);
    
    printf("enter argument of perigee(for testing, 180)\n");
    scanf("%f", &sat->argument_perigee);
    
    printf("enter eccentricity (for testing, not .5)\n");
    scanf("%f", &sat->eccentricity);
    
    printf("enter mean anomaly (for testing, not 180)\n");
    scanf("%f", &sat->mean_anomaly);
}


"Card" needs to be a global variable so I put that into the structure. What do lines 26 and 37 do?

I am adding a function to calculate apogee and perigee and need to add them to the structure...
Where you say "this is our structure", I think you have a misunderstanding about structs. And I would move the word "Satellite" back where I had it since it's part of that typedef statement.

Satellite is just a type. It is not a thing in itself. You need to create an instance of the type to use it. This can be done as in main where we make an instance of the Satellite type called sat. Or it can be done dynamically with malloc (or new in C++).

Wrapping the struct in a typedef just allows us to refer to the Satellite type without always needing to say "struct" in front of it. In C++, the typedef isn't needed. If you don't have a preference, you might want to switch to C++ which at this point pretty much just means to change your printf's to couts and scanf's to cins.

"Card" needs to be a global variable so I put that into the structure.


This is the same misunderstanding. The "structure" is not a global variable in any way. It's nothing; only a type. If for some strange reason you really "need" card_number to be global, put it outside the struct by itself.
tpb - I think I understand. Each individual satellite comes in (this is some ancient technology, they were originally formatted for and printed on Hollerith cards) two "cards". I need to (later) keep track of - is the quantity on "card" 1 or 2? For each satellite. So my terminology - global variable, was sloppy. It is in the structure as it should be.

So line 37, Satellite sat, just starts a structure called "sat"? That would better be the satellite number I think. So that Structure called sat has one satellite in it - which we poll the user for shortly. That will work for now - I will try to add several satellites, maybe sat1, sat2, sat3. Then when I output inclination, etc I can also output satellite number.

I will switch to C++ since I hope to extend this to do several more calculations and tasks. I am now taking my Excel spreadsheet and putting the calculations in - to give me apogee and perigee for each satellite.

Do you mind this back and forth exchange of messages?
Do you mind this back and forth exchange of messages?

Not at all. Here's a little C++ to get you started.

It reads a file into a vector and then prints the vector to the terminal.
The file's fields are space-separated, three fields per row like this
1 hello 1.23
2 world 3.22
1 okay  7.77
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;

struct Satellite {
    int cardno;
    string id;
    float x;
};

// Reads from input stream into satellite struct.
istream& operator>>(istream& is, Satellite& s) {
    return is >> s.cardno >> s.id >> s.x;
}

// Writes to output stream from satellite struct.
ostream& operator<<(ostream& os, Satellite& s) {
    return os << s.cardno << ',' << s.id << ',' << s.x << '\n';
}

int main() {
    vector<Satellite> v;

    ifstream ifs("satellite.txt");
    Satellite sat;
    while (ifs >> sat)
        v.push_back(sat);

    for (const auto& x: v)
        cout << x;
}

Last edited on
Oh - I might be able to use that to read a big string in, a string with eccentricity, inclination, etc. So this "Satellite" structure could be replaced with the one from OrbitManager.

Instead of id I could use eccentricity, x would be inclination, etc. What if there is more than a single space between some quantities?

We would still need to fopen satellite.txt for input?
Last edited on
So what is the name of the input file supposed to be? Your line 14 seems to indicate "is" I changed that to input.txt - line 15 changed also. When I build, it wants an &x on line 32.

No output. Do I need to change os on line 19?
Topic archived. No new replies allowed.