Search code examples
ccs50

How do you move the contents of the main function to a different function and retain functionality?


I am currently trying to move the contents of the "main" function to its own function, both so I can repeat things and also to have more options of what happens and when. Once the function is complete, I also want to increase an integer each time something is purchased, so it can be checked with some sort of inventory command.

I've made the mistake of effectively copy-pasting what I previously had in main into what I want to be its own function. Unfortunately, this is actually my first time trying to declare a function other than main that wasn't given to me by other people on this site, so I don't really know how to declare them. I'm guessing the declaration was incorrect/lacked data, causing problems.

The code:

#include <cs50.h>
#include <stdio.h>
#include <string.h>

//Attempting to declare the function early, which is the only thing CS50 has taught me about custom functions thus far.
void itemshop(int buckaroonies);

//Struct given to me in another post
struct item
    {
        string name;
        int price;
        string description;
    };

//Part of aformentioned struct
int find_item(string item_name, struct item items[], size_t num_items)
{
    for (size_t i = 0; i < num_items ; i++)
    {
        if (0 == strcmp(items[i].name, item_name))
        {
            return i;
        }
    }
    //Item not available
    return -1;
}

int main(void)
{
    //Item struct
     struct item items[] = {
        {"Matchbox", 50, "They're cheap, and they'll keep you warm."},
        {"Wool Hat", 125, "A nice, handknit, cozy hat. Thank my ma for that!"},
        {"Heavy Coat", 250, "This coat'll keep you cozy through the night no matter the situation!"},
        {"Canned Food", 25, "It don't taste too good, but it'll last you a lifetime. Eat up!"}
    };
    const size_t num_items = sizeof(items) / sizeof(items[0]);

    //Integers for items once they are purchased
    int buckaroonies = 500;
    int matchb = 0;
    int woolh = 0;
    int heavyc = 0;
    int canf = 0;

    itemshop(int buckaroonies);
}

//This is probably the worst part, I just copy-pasted what I had in main into this function, and likely declared it incorrectly as well
void itemshop(int buckaroonies)
{
    //Dialogue and selection
    printf("Hey chum, welcome to the item shop. You've got a handful 'o coin on ya, huh?\nYou came to the right place, we got the best wares in town!\n\n");
    printf("Store:\n\nMatchbox - 50\nWool Hat - 125\nHeavy Coat - 250\nCanned Food - 25\n");
    string select = get_string ("What'll it be? You have %i buckaroonies, pal.\n", buckaroonies);
    string description[] = { "They're cheap, and they'll keep you warm.\n", "A nice, handknit, cozy hat. Thank my ma for that!\n", "This coat'll keep you cozy through the night no matter the situation!\n", "It don't taste too good, but it'll last you a lifetime. Eat up!" };


    //Get item details from selection, error comes from here
    int index = find_item(select, items, num_items);

    //Return dialogue based on selected item
    if (-1 == index)
    {
        printf("We aint got that, pal.\n");
    }
    else
        {
            char c = get_char ("That %s'll cost ya %i buckaroonies. %s You want it?\n", items[index].name, items[index].price, items[index].description);

            if(c == 'y' || c == 'Y')

                {
                    printf("Pleasure doing business with you, pal. -%i Buckeroonies\n", items[index].price);
                    buckaroonies = buckaroonies - items[index].price;
                }
            else if (c == 'n' || c == 'N')
                {
                    printf("Alright, feel free to keep browsing.\n");
                }
            else
                {
                    printf("Hey, uh... I don't know what that means.\n");
                }
        }
}

The error:

itemshop.c:48:14: error: expected expression
    itemshop(int buckaroonies);
             ^

Solution

  • The basic technique to move the contents of main() into a function called from main() is to change the name of the function and write the new main(). Since your main() program ignores all command line arguments, the change would look like this:

    Before

    int main(void)
    {
        …declarations and code…
    }
    

    After

    static int old_main(void)
    {
        …declarations and code…
        return 0;   // Necessary - only main() gets special treatment
    }
    
    int main(void)
    {
        return old_main();
    }
    

    You can then make changes, moving appropriate code from old_main() to main() and adding parameters to old_main() so that it can access the data it needs to work on.

    If your program took command line arguments, you'd replace each occurrence of (void) with (int argc, char **arg). However, you'd most likely want to process the command line arguments in the revised main(), calling the function to process files named on the command line (or strings specified on the command line).

    When I'm working on a problem, I often start out with a main() function that includes far too much material, and I end up writing a test harness function based on the original main() that can be called repeatedly from the revised main(). You can see an example of this in some code in my SOQ (Stack Overflow Questions) repository on GitHub — for example, the files mds41.c and mds43.c in the src/so-4715-1134 sub-directory. There are numerous other examples in that repo.