Jonathan Jonathan - 1 month ago 7
C Question

How do I pass my struct values into my print function and then call it in main? - C Language

This is my code below:

enum DifficultyKind
{
Normal,
Hard,
Insane
} DifficultyKind;

typedef struct Target_Data
{
my_string name;
int hit_id;
int dollarvalue;
enum DifficultyKind difficulty;
} Target_Data;

enum DifficultyKind read_difficulty_kind (const char *prompt)
{
int temp;

enum DifficultyKind result;
printf("%s\n", prompt);

printf("\n");
printf("1: Normal Difficulty \n");
printf("\n");
printf("2: Hard Difficulty \n");
printf("\n");
printf("3: Insane Difficulty \n");
printf("\n");

temp = read_integer("Please make a selection between 1 and 3: \n");
if (temp < 1) {
printf("\n");
printf("You did not make a selection between 1 and 3\n");
printf("\n");
temp = read_integer("Please make a selection between 1 and 3: \n");
}

if (temp > 3) {
printf("\n");
printf("You did not make a selection between 1 and 3\n");
printf("\n");
temp = read_integer("Please make a selection between 1 and 3: \n");
}

result = temp - 1;
return result;
}

Target_Data read_target_data (const char *prompt)
{
Target_Data result;
enum DifficultyKind Difficulty;
printf("%s\n", prompt);

result.name = read_string("Enter name: ");

result.hit_id = read_integer("Enter hit ID: ");
if (result.hit_id < 0) {
printf("Please enter a value of 0 or higher \n");
result.hit_id = read_integer("Enter hit ID: ");
}

result.dollarvalue = read_integer("Enter $ value of target: ");
if (result.dollarvalue < 0) {
printf("Please enter a value of 0 or higher \n");
result.dollarvalue = read_integer("Enter $ value of target: ");
}

Difficulty = read_difficulty_kind("Please select the level of difficulty this bounty is from the below options:");

return result;
}

void print_target_data (Target_Data *toPrintData)
{
printf("\nDifficulty: %d, Target: %s, Hit ID: %i, $%i,\n", toPrintData->difficulty, toPrintData->name.str, toPrintData->hit_id, toPrintData->dollarvalue);
}

int main()
{
Target_Data *Target_Data;
read_target_data("Please enter the details of your bounty: ");
print_target_data(&Target_Data);
}


when the program runs and after entering the details, I get the below:

Please enter the details of your bounty:
Enter name: Jonathan
Enter hit ID: 10
Enter $ value of target: 500
Please select the level of difficulty this bounty is from the below options:

1: Normal Difficulty

2: Hard Difficulty

3: Insane Difficulty

Please make a selection between 1 and 3:
1

Difficulty: 10, Target: , Hit ID: 0, $0,


I have tried so many different ways and looked all over for a solution but don't really know what to do.

Why does the difficulty read out as the number I entered for hit ID... and the rest of the details don't even show?

this is also the warning message I get when I compile it:

BountyHunter.c:96:20: warning: incompatible pointer types passing
'Target_Data **' (aka 'struct Target_Data **') to parameter of type
'Target_Data *' (aka 'struct Target_Data *'); remove &
[-Wincompatible-pointer-types]
print_target_data(&Target_Data);
^~~~~~~~~~~~
BountyHunter.c:87:38: note: passing argument to parameter 'toPrintData' here
void print_target_data (Target_Data *toPrintData)


Someone please help!

Answer

You have a huge number of errors in your code, made much more difficult to identify given the lack of all necessary code needed to validate your reads. That said, I've reworked your example to use a statically declared Target_Data which is passed by address to read_target_data which eliminates the need to dynamically declare a struct within either read_target_data or read_difficulty_kind (which would likely over-complicate your learning at the moment)

I don't know if you come from java, or tried to copy java code, but toPrintData->name.str makes no sense at all.

I've also added err = -1 to your DifficultyKind enum to allow validation of the value returned within the code. It's up to you how you do it, but you need to validate each input to insure you are actually working with real values and not attempting to process uninitialized values.

(as a side note, C generally makes use of lower-case variable names, leaving camelCase and UpperCase names for java and C++, and reserving UPPERCASE names for macros, etc... Granted, it is style, so it is completely up to you)

With that said, here is the reworked example that I believe keeps with your intent. Look it over and let me know if you have any further questions. The input routines are simply calls to scanf (which should more properly be calls to fgets with subsequent calls to sscanf, but that is for another day)

#include <stdio.h>
#include <stdlib.h>

#define MAXC 128

typedef enum { err = -1, Normal = 1, Hard, Insane } DifficultyKind;

typedef struct {
    char name[MAXC];
    int hit_id;
    int dollarvalue;
    DifficultyKind difficulty;
} Target_Data;

DifficultyKind read_difficulty_kind (const char *prompt)
{
    int rtn, temp;

    printf ("%s\n\n"
            " 1: Normal Difficulty\n"
            " 2: Hard Difficulty\n"
            " 3: Insane Difficulty\n\n", prompt);

    while ((rtn = scanf (" %d", &temp)) != 1 || (temp < 1 || temp > 3)) {
        if (rtn == EOF)
            return err;  /* trap cancel of input (ctrl+d, ctrl+z) */
        fprintf (stderr, "error: invalid selection\n"
                        "Please make a selection between 1 and 3:\n\n"
                        " 1: Normal Difficulty\n"
                        " 2: Hard Difficulty\n"
                        " 3: Insane Difficulty\n\n");
    }

    return temp;
}

Target_Data *read_target_data (Target_Data *result, const char *prompt)
{
    int rtn;

    printf ("%s\n\nEnter name: ", prompt);
    while ((rtn = scanf (" %127[^\n]%*c", result->name) != 1))
        if (rtn == EOF) {
            fprintf (stderr, "warning: input canceled, exiting.\n");
            exit (EXIT_FAILURE);
        }

    printf ("Enter hit ID: ");
    while ((rtn = scanf (" %d", &(result->hit_id)) != 1) ||
            result->hit_id < 0) {
        if (rtn == EOF) {
            fprintf (stderr, "warning: input canceled, exiting.\n");
            exit (EXIT_FAILURE);
        }
        fprintf (stderr, "Please enter a value of 0 or higher \n");
        printf ("Enter hit ID: ");
    }

    printf ("Enter $ value of target: ");
    while ((rtn = scanf (" %d", &(result->dollarvalue)) != 1) || 
            result->dollarvalue < 0) {
        if (rtn == EOF) {
            fprintf (stderr, "warning: input canceled, exiting.\n");
            exit (EXIT_FAILURE);
        }
        fprintf (stderr, "Please enter a value of 0 or higher \n");
        printf ("Enter $ value of target: ");
    }

    if ((result->difficulty = read_difficulty_kind ("Please select the"
            " level of difficulty from the options below:")) == err) {
        fprintf (stderr, "warning: input canceled, exiting.\n");
        exit (EXIT_FAILURE);
    }

    return result;
}

void print_target_data (Target_Data *toPrintData)
{
    printf ("\nDifficulty: %d, Target: %s, Hit ID: %i, $%i,\n",
            toPrintData->difficulty, toPrintData->name,
            toPrintData->hit_id, toPrintData->dollarvalue);
}

int main (void) {

    Target_Data Target_Data = { .name = "" };
    read_target_data (&Target_Data, 
                    "Please enter the details of your bounty: ");
    print_target_data (&Target_Data);

    return 0;
}

Example Use/Output

$ ./bin/difficultystruct
Please enter the details of your bounty:

Enter name: Some Funny Name
Enter hit ID: 123
Enter $ value of target: 234
Please select the level of difficulty from the options below:

 1: Normal Difficulty
 2: Hard Difficulty
 3: Insane Difficulty

0
error: invalid selection
Please make a selection between 1 and 3:

 1: Normal Difficulty
 2: Hard Difficulty
 3: Insane Difficulty

4
error: invalid selection
Please make a selection between 1 and 3:

 1: Normal Difficulty
 2: Hard Difficulty
 3: Insane Difficulty

2

Difficulty: 2, Target: Some Funny Name, Hit ID: 123, $234,