Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

I have a fish program in C, everything compiles and it seems to work i think.. b

ID: 3545016 • Letter: I

Question

I have a fish program in C, everything compiles and it seems to work i think.. but there seems to be a few bugs. Can you write what the bugs are and how to fix them? thanks


This is what it does:

-Runs each turn and waits for the user to press enter before advancing to the next

turn.

-The output from each turn is separated by an empty line.

-Fish tank should always contain 5 fish at the start of each turn.  New fish should be added if

there are fewer than 5.

-Each fish has a randomly generated name and type.  There should be differences between

fish.  While possible, it is VERY unlikely that all fish will have the same name and type.

-A fish dies of hunger if its hunger level is 10 after the feeding cycle.

-Floaters and Schoolers always eat and will never die of hunger.  A tank full of only floaters and schoolers

will be in "equilibrium" and never change as no fish will ever die of hunger.

-Lazy fish never eat.

-Bottom feeders and Loners have a chance to not eat.

-Predators can eat another fish or eat fish food like the rest of the other fish.  Predators

can eat other predators, but a predator cannot eat itself.

-Exit the program by entering q or Q at the prompt.



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

#define TRUE 1
#define FALSE 0
#define NUM_FISH 5

/*     
* Structs
*/
typedef struct {
    short boolAlive;
    char *strName;
    char *strType;
    int iHungerLevel;
} Fish;

typedef struct {
    Fish fishes[NUM_FISH];
} Tank;

/*
* Fish makeNewFish(char *strName, char* strType    
*                                                  
* Action:                                          
*    -Creates a new fish with the given parameters.
*                                                  
*  Parameters:                                      
*    -strName = The name of the new fish.           
*    -strType = the type of the new fish.           
*                                                  
* Returns:                                         
*    -A new fish with the specified parameters.     
*/
Fish makeNewFish(char *strName, char *strType) {
    Fish fshNewFish;
    fshNewFish.strName = strName;
    fshNewFish.strType = strType;
    fshNewFish.boolAlive = TRUE;
    fshNewFish.iHungerLevel = 5;
    return fshNewFish;
}

/*
* char *namePicker(void)                         
*                                                
*  Action:                                        
*    -Randomly picks a name string for a fish.    
*                                                
* Returns:                                       
*    -A randomly picked name string for the fish.
*/
char *namePicker(void) {
    /* Get index between 0 and 9 */
    int iChosenName = rand() % 10;
    switch (iChosenName) {
        case '0':
            return "Scales";
        case '1':
            return "Shiny Sides";
        case '2':
            return "Goldie";
        case '3':
            return "Bob";
        case '4':
            return "Kirby";
        case '5':
            return "Nemo";
        case '6':
            return "Dory";
        case '7':
            return "Bubbles";
        case '8':
            return "Hoover";
        case '9':
            return "Squirt";
        default:
            /*Should never be reached */
            return "Fishie";
    }
}

/*
* char *typePicker(void)                         
*                                                
* Action:                                        
*    -Randomly picks a type string for a fish.    
*                                                
* Returns:                                       
*    -A randomly picked type string for the fish.
*/
char *typePicker(void) {
    /* Get index between 0 and 4 */
    int iChosenType = rand() % 5;
    char *strType;

    switch (iChosenType) {
        case 0:
           strType = "bottom feeder";
       case 1:
            strType = "schooler";
        case 2:
            strType = "predator";
        case 3:
            strType = "loner";
        case 4:
            strType = "floater";
        default:
            /* Should not be reached */
            strType = "lazy";
    }
    return strType;
}

/*
* void addFish(Tank *pTank, int index, char *strName, char *strType)       
*                                                                          
* Action:                                                                  
*    -Adds a fish with the given parameters to the tank at the given index.
*                                                                          
* Parameters:                                                              
*    -pTank  = Pointer to the tank to add the fish to.                      
*    -index  = The index at which to add the new fish.                      
*    -strName = The name of the new fish.                                   
*    -strType = The type of the new fish.                                   
*/
void addFish(Tank *pTank, int index, char *strName, char *strType) {
    pTank->fishes[index] = makeNewFish(strName, strType);
    printf("Added %s the %s to the tank! ", pTank->fishes[index].strName,
            pTank->fishes[index].strType);
}

/*
* void eat(Fish fish)               
*                                    
* Action:                           
*    -Causes the given fish to eat.  
*                                    
* Parameter:                       
*    -fish = The fish that will eat.
*/
void eat(Fish fish) {
    fish.iHungerLevel--;
}

/*
* void die(Fish *fish)             
*                                   
*  Action:                          
*    -Causes the given fish to die.
*                                   
* Parameter:                       
*    -fish = The fish to kill.      
*/
void die(Fish *fish) {
    fish->boolAlive = FALSE;
}

/*
* void feedFish(Tank *pTank, int index)    
*                                           
* Action:                                  
*    -Feeds the fish at the given index.    
*     Action is based on the fish's type.   
*                                            
* Parameters:                               
*    -pTank = The tank that the fish are in.
*    -index = The index of the fish to feed.
*/
void feedFish(Tank *pTank, int index) {

    Fish *pfish;
    int preyIndex;
    pfish = &(pTank->fishes[index]);

    /* ~50% of the time, bottom feeders get to eat */
    if (strcmp(pfish->strType, "bottom feeder") == 0) {
        if (rand() % 2) {
            eat(*pfish);
            printf("%s the bottom feeder ate!", pfish->strName);
        }

        else {
            printf("%s the bottom feeder didn't get to eat...", pfish->strName);
        }
    }

    /* Schoolers and Floaters always get to eat */
    else if (strcmp(pfish->strType, "schooler") == 0
            || strcmp(pfish->strType, "floater") == 0) {
        eat(*pfish);
        printf("%s the %s ate!", pfish->strName, pfish->strType);
    }

    /* Loners get to eat 2/3 of the time */
    else if (strcmp(pfish->strType, "loner") == 0) {
        if (rand() % 3 == 1) {
            printf("%s the loner didn't get to eat...", pfish->strName);
       }

        else {
            eat(*pfish);
            printf("%s the loner ate!", pfish->strName);
        }
    }

    /* Predators will eat another fish ~50% of the time */
    else if (strcmp(pfish->strType, "predator") == 0) {

        /* Eat another fish */
        if (rand() % 2) {

           /*
            * Choose another fish at random, fish can't eat itself!
            * First part gets an index at random and should loop until an index other than
            * the current predator is found.
            * Second part makes sure that the prey fish is alive.
            */
            while ((preyIndex = rand() % NUM_FISH) != index
                    && pTank->fishes[preyIndex].boolAlive)
                ;

            /* Eat that fish */
            eat(*pfish);
            die(&pTank->fishes[preyIndex]);
            printf("%s the predator ate %s the %s!", pfish->strName,
                    pTank->fishes[preyIndex].strName,
                    pTank->fishes[preyIndex].strType);
        }

        /* Eat something else */
        else {
            eat(*pfish);
            printf("%s the predator ate!", pfish->strName);
        }
    }

    /* Lazy fish don't eat... ever!  They're too lazy! */
    else {
        printf("%s the lazy fish didn't eat...", pfish->strName);
    }
    printf(" Hunger level: %d ", pfish->iHungerLevel);
}

/*                                                  
* Runs the fish tank simulator. There should always be  
* NUM_FISH fish in the tank and it should replace fish  
* if the number drops below that amount. After          
* restocking, the fish will be fed, and then get hungry
* again to end the turn.  Advance to the next turn by   
* pressing enter.                                       
*/
int main(void) {
    Tank tank;
    int i;
    Fish currentFish;
    char running = TRUE;
    char input;
   char fillTank = TRUE;

    /* Seed random number generator */
    srand(time(NULL));

    while (running) {

        /* Restock fish tank */
        for (i = 0; i < NUM_FISH; i++) {
            if (!tank.fishes[i].boolAlive || fillTank) {
                addFish(&tank, i, namePicker(), typePicker());
            }
        }

        fillTank &= FALSE;

        /* Feeding cycle */
        for (i = 0; i <= NUM_FISH; i++) {
            currentFish = tank.fishes[i];
            if (currentFish.boolAlive) {
                feedFish(&tank, i);
            }
        }

        /* Fish get hungry */
        for (i = 0; i < NUM_FISH; i++) {
            /* If hunger level reaches 10, fish dies */
            if (tank.fishes[i].iHungerLevel = 10 && tank.fishes[i].boolAlive) {
                die(&(tank.fishes[i]));
                printf("%s the %s has died of hunger... ",
                        tank.fishes[i].strName, tank.fishes[i].strType);
            }

            tank.fishes[i].iHungerLevel++;
        }

        /* Wait for user */
        printf("Enter 'q' or 'Q' to exit:");
        input = getchar();
        running = input != 'q' && input != 'Q';
        if (input != ' ') {
            while (getchar() != ' ')
                ;
        }
        printf(" ");
    }
    return 0;
}


Explanation / Answer

Here are my findings


1. When ever you try to restock the fishes in tank. you always add Fishie the lazy to the tank this is because of the switch case in name picker

in the namePicker function you are generating an integer value but in the switch case you are comparing integer value with character value this leads to the selection of default case, which is why your namepikcer() always returns "Fishie"

  

2. A bug while in typePicker() which always returns "lazy" as type of the fish this is because you forgot to put break statements for each case as a result the cases will be executed one after the other which will finally cause the default case to be executed and returns "laz"


3.While feeding a fish you are passing the object of fish structure to the eat function but the eat function is expecting a pointer to Fish structure object.


4.In eat funtion you are trying to access iHungerLevel with a dot(.) operator instead of -> operator.


5. while executing feeding cycle in the for loop you are comparing

i <= NUM_FISH

this results in a runtime error of null reference

it should be

i < NUM_FISH

6. remove

if (input != ' ') {
while (getchar() != ' ')
;
} code at the end of main()


Here is the correct program




Here is the correct code



//I have a fish program in C, everything compiles and it seems to work i think.. but there seems to be a few bugs. Can you write what the bugs are and how to fix them? thanks


//This is what it does:

//-Runs each turn and waits for the user to press enter before advancing to the next

//turn.

//-The output from each turn is separated by an empty line.

//-Fish tank should always contain 5 fish at the start of each turn. New fish should be added if

//there are fewer than 5.

//-Each fish has a randomly generated name and type. There should be differences between

//fish. While possible, it is VERY unlikely that all fish will have the same name and type.

//-A fish dies of hunger if its hunger level is 10 after the feeding cycle.

//-Floaters and Schoolers always eat and will never die of hunger. A tank full of only floaters and schoolers

//will be in "equilibrium" and never change as no fish will ever die of hunger.

//-Lazy fish never eat.

//-Bottom feeders and Loners have a chance to not eat.

//-Predators can eat another fish or eat fish food like the rest of the other fish. Predators

//can eat other predators, but a predator cannot eat itself.

//-Exit the program by entering q or Q at the prompt.



#include <stdlib.h>

#include <stdio.h>

#include <time.h>

#include <string.h>


#define TRUE 1

#define FALSE 0

#define NUM_FISH 5


/*

* Structs

*/

typedef struct {

short boolAlive;

char *strName;

char *strType;

int iHungerLevel;

} Fish;


typedef struct {

Fish fishes[NUM_FISH];

} Tank;


/*

* Fish makeNewFish(char *strName, char* strType

*

* Action:

* -Creates a new fish with the given parameters.

*

* Parameters:

* -strName = The name of the new fish.

* -strType = the type of the new fish.

*

* Returns:

* -A new fish with the specified parameters.

*/

Fish makeNewFish(char *strName, char *strType) {

Fish fshNewFish;

fshNewFish.strName = strName;

fshNewFish.strType = strType;

fshNewFish.boolAlive = TRUE;

fshNewFish.iHungerLevel = 5;

return fshNewFish;

}


/*

* char *namePicker(void)

*

* Action:

* -Randomly picks a name string for a fish.

*

* Returns:

* -A randomly picked name string for the fish.

*/

char *namePicker(void) {

/* Get index between 0 and 9 */

int iChosenName = rand() % 10;

switch (iChosenName) {

case 0:

return "Scales";

case 1:

return "Shiny Sides";

case 2:

return "Goldie";

case 3:

return "Bob";

case 4:

return "Kirby";

case 5:

return "Nemo";

case 6:

return "Dory";

case 7:

return "Bubbles";

case 8:

return "Hoover";

case 9:

return "Squirt";

default:

/*Should never be reached */

return "Fishie";

}

}


/*

* char *typePicker(void)

*

* Action:

* -Randomly picks a type string for a fish.

*

* Returns:

* -A randomly picked type string for the fish.

*/

char *typePicker(void) {

/* Get index between 0 and 4 */

int iChosenType = rand() % 5;

char *strType;


switch (iChosenType)

{

case 0:

strType = "bottom feeder";

break;

case 1:

strType = "schooler";

break;

case 2:

strType = "predator";

break;

case 3:

strType = "loner";

break;

case 4:

strType = "floater";

break;

default:

/* Should not be reached */

strType = "lazy";

}

return strType;

}


/*

* void addFish(Tank *pTank, int index, char *strName, char *strType)

*

* Action:

* -Adds a fish with the given parameters to the tank at the given index.

*

* Parameters:

* -pTank = Pointer to the tank to add the fish to.

* -index = The index at which to add the new fish.

* -strName = The name of the new fish.

* -strType = The type of the new fish.

*/

void addFish(Tank *pTank, int index, char *strName, char *strType) {

pTank->fishes[index] = makeNewFish(strName, strType);

printf("Added %s the %s to the tank! ", pTank->fishes[index].strName,

pTank->fishes[index].strType);

}


/*

* void eat(Fish fish)

*

* Action:

* -Causes the given fish to eat.

*

* Parameter:

* -fish = The fish that will eat.

*/

void eat(Fish *fish) {

fish->iHungerLevel--;

}


/*

* void die(Fish fish)

*

* Action:

* -Causes the given fish to die.

*

* Parameter:

* -fish = The fish to kill.

*/

void die(Fish *fish) {

fish->boolAlive = FALSE;

}


/*

* void feedFish(Tank *pTank, int index)

*

* Action:

* -Feeds the fish at the given index.

* Action is based on the fish's type.

*

* Parameters:

* -pTank = The tank that the fish are in.

* -index = The index of the fish to feed.

*/

void feedFish(Tank *pTank, int index)

{


Fish *pfish;

int preyIndex;

pfish = &(pTank->fishes[index]);

/* ~50% of the time, bottom feeders get to eat */

if (strcmp(pfish->strType, "bottom feeder") == 0)

{

if (rand() % 2)

{

eat(pfish);

printf("%s the bottom feeder ate!", pfish->strName);

}

else

{

printf("%s the bottom feeder didn't get to eat...", pfish->strName);

}

}


/* Schoolers and Floaters always get to eat */

else if (strcmp(pfish->strType, "schooler") == 0 || strcmp(pfish->strType, "floater") == 0)

{

eat(pfish);

printf("%s the %s ate!", pfish->strName, pfish->strType);

}


/* Loners get to eat 2/3 of the time */

else if (strcmp(pfish->strType, "loner") == 0)

{

if (rand() % 3 == 1)

{

printf("%s the loner didn't get to eat...", pfish->strName);

}

else

{

eat(pfish);

printf("%s the loner ate!", pfish->strName);

}

}


/* Predators will eat another fish ~50% of the time */

else if (strcmp(pfish->strType, "predator") == 0)

{

/* Eat another fish */

if (rand() % 2)

{

  

/*

* Choose another fish at random, fish can't eat itself!

* First part gets an index at random and should loop until an index other than

* the current predator is found.

* Second part makes sure that the prey fish is alive.

*/

while ((preyIndex = rand() % NUM_FISH) != index && pTank->fishes[preyIndex].boolAlive)

;

/* Eat that fish */

eat(pfish);

die(&pTank->fishes[preyIndex]);

printf("%s the predator ate %s the %s!", pfish->strName,

pTank->fishes[preyIndex].strName,

pTank->fishes[preyIndex].strType);

}

/* Eat something else */

else

{

eat(pfish);

printf("%s the predator ate!", pfish->strName);

}

}


/* Lazy fish don't eat... ever! They're too lazy! */

else

{

printf("%s the lazy fish didn't eat...", pfish->strName);

}

printf(" Hunger level: %d ", pfish->iHungerLevel);

}


/*

* Runs the fish tank simulator. There should always be

* NUM_FISH fish in the tank and it should replace fish

* if the number drops below that amount. After

* restocking, the fish will be fed, and then get hungry

* again to end the turn. Advance to the next turn by

* pressing enter.

*/

int main(void) {

Tank tank;

int i;

Fish currentFish;

char running = TRUE;

char input;

char fillTank = TRUE;


/* Seed random number generator */

srand(time(NULL));


while (running)

{


/* Restock fish tank */

for (i = 0; i < NUM_FISH; i++)

{

if (!tank.fishes[i].boolAlive || fillTank)

{

addFish(&tank, i, namePicker(), typePicker());

}

}

fillTank &= FALSE;


/* Feeding cycle */

for (i = 0; i < NUM_FISH; i++)

{

currentFish = tank.fishes[i];

if (currentFish.boolAlive)

{

feedFish(&tank, i);

}

}


/* Fish get hungry */

for (i = 0; i < NUM_FISH; i++)

{

/* If hunger level reaches 10, fish dies */

if (tank.fishes[i].iHungerLevel == 10 && tank.fishes[i].boolAlive)

{

die(&(tank.fishes[i]));

printf("%s the %s has died of hunger... ",

tank.fishes[i].strName, tank.fishes[i].strType);

}

  

tank.fishes[i].iHungerLevel++;

}


/* Wait for user */

printf("Enter 'q' or 'Q' to exit:");

input = getchar();

running = input != 'q' && input != 'Q';

printf("running %d",running);

printf(" ");

}

return 0;

}