I'm seriously confused right now. I'm working on a school project that uses overloading. I have a constructor that has two parameters, a lower index and upper index for an int array. Here is the constructor:
IntArray::IntArray(int lower, int upper){
arrLower = lower;
arrUpper = upper;
// Creates array size
size = arrUpper - arrLower;
operator[](size);
}
and when my program gets to this testing point via this function:
void test2() {
cout << "2. Array declared with two integers: IntArray b(-3, 6);" << endl << endl;
csis << "2. Array declared with two integers: IntArray b(-3, 6);" << endl << endl;
IntArray b(-3, 6);
//cout << b.low() << " " << b.high();
for(int i = b.low(); i <= b.high(); i++)
b[i] = i * 10;
b.setName("b");
cout << b << endl;
csis << b << endl;
wait();
}
it seizes and utilizes all of my cpu power. the low() and high() functions simply return arrLower and arrUpper. What I don't understand is why it works if I add
cout << b.low() << " " << b.high() << endl;
after the constructor call.
Why does adding a cout statement fix my problem? Am I not managing memory properly?
heres the full WIP program if you want to look at it. It's not done by a long shot.
https://gist.github.com/anonymous/963fb80351ae23c58f18
Related
Okay so I have a calorie calculator that is supposed to be separated into the five functions including main seen below. My issue is that I get a compiler error because the variables from the inputNumber function and calculateCalories function cannot be read by any of the other functions once they are obtained. I am not allowed to use Global variables. There must be something I am missing to be able to read the variables within the main function then output them into the other functions to get the proper output. Any help would be appreciated.
Here is the code as it stands:
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
int main()
{
int Lbs, hourr, hourW, hourWe, hourb;
double calBad, calRun, calWal, calWei;
string name;
cout << "Welcome to Megan McCracken's Workout Calculator!" << endl;
cout << endl;
cout << "Please enter your name: ";
getline(cin, name);
inputNumber(Lbs, hourr, hourW, hourWe, hourb);
calculateCalories(Lbs,hourr,hourb,hourW,hourWe,calBad,calRun,calWal,calWei);
displayHeadings(name);
displayLine(hourr,hourb,hourW,hourWe,calBad,calRun,calWal,calWei);
system("pause");
return 0;
}
int inputNumber(int Lbs, int hourr, int hourb, int hourW, int hourWe)
{
cout << "Please enter your weight: ";
cin >> Lbs;
return Lbs;
cout << "Please enter the minutes spent playing badminton: ";
cin >> hourb;
return hourb;
cout << "Please enter the minutes spent running: ";
cin >> hourr;
return hourr;
cout << "Please enter the minutes spent walking: ";
cin >> hourW;
return hourW;
cout << "Please enter the minutes spent lifting weights: ";
cin >> hourWe;
return hourWe;
cout << endl;
}
double calculateCalories(int Lbs, int hourW, int hourb, int hourr, int hourWe, double calBad, double calRun, double calWal, double calWei)
{
const double Badburn = .044, Runburn = .087, Walkb = .036, Weightb = .042;
double calBad, calRun, calWal, calWei;
calBad = (Badburn * Lbs) * hourb;
calRun = (Runburn * Lbs) * hourr;
calWal = (Walkb * Lbs) * hourW;
calWei = (Weightb * Lbs) * hourWe;
return calBad;
return calRun;
return calWal;
return calWei;
}
void displayHeadings(string name)
{
cout << "Here are the results for " << name << ": " << endl;
cout << endl;
cout << "Activity" << right << setw(18) << "Time" << right << setw(10) << "Calories" << endl;
cout << "--------------------------------------" << endl;
}
void displayLine(int hourb,int hourr, int hourW, int hourWe, double calBad, double calRun, double calWal, double calWei)
{
int HB, MB, HR, MR, HW, MW, HWE, MWE, Hour, Min;
double Calorie;
HB = (hourb / 60);
MB = (hourb % 60);
HR = (hourr / 60);
MR = (hourr % 60);
HW = (hourW / 60);
MW = (hourW % 60);
HWE = (hourWe / 60);
MWE = (hourWe % 60);
Calorie = calBad + calRun + calWal + calWei;
Hour = (hourb + hourr + hourW + hourWe) / 60;
Min = (hourb + hourr + hourW + hourWe) % 60;
cout << "Badminton" << right << setw(14) << HB << ":" << setfill('0') << setw(2) << MB << setfill(' ') << right << setw(10) << setprecision(3) << fixed << showpoint << calBad << endl;
cout << resetiosflags(ios::fixed | ios::showpoint);
cout << "Running" << right << setw(16) << HR << ":" << setfill('0') << setw(2) << MR << setfill(' ') << right << setw(10) << setprecision(3) << fixed << showpoint << calRun << endl;
cout << resetiosflags(ios::fixed | ios::showpoint);
cout << "Walking" << right << setw(16) << HW << ":" << setfill('0') << setw(2) << MW << setfill(' ') << right << setw(10) << setprecision(3) << fixed << showpoint << calWal << endl;
cout << resetiosflags(ios::fixed | ios::showpoint);
cout << "Weights" << right << setw(16) << HWE << ":" << setfill('0') << setw(2) << MWE << setfill(' ') << right << setw(10) << setprecision(3) << fixed << showpoint << calWei << endl;
cout << "--------------------------------------" << endl;
cout << resetiosflags(ios::fixed | ios::showpoint);
cout << "Totals" << right << setw(17) << Hour << ":" << setfill('0') << setw(2) << Min << setfill(' ') << right << setw(10) << setprecision(3) << fixed << showpoint << Calorie << endl;
cout << endl;
}
If you want to modify passed-in variables within a function in C++, you should be passing them in by reference (default is by value, meaning you get a copy of the variable which is effectively thrown away when the function exits).
So, by way of example:
void xyzzy (int plugh) { plugh = 42; }
int main() {
int twisty = 7;
xyzzy (twisty);
cout << twisty << '\n';
return 0;
}
will output 7 because twisty was passed by value and changes to it within the function will not be echoed back to the caller.
However, if you pass by reference with:
void xyzzy (int &plugh) { plugh = 42; }
// ^
// This does the trick.
then you'll find it outputs 42 as desired.
For your particular case, you want to look at the variables in the argument list of inputNumber:
int inputNumber(int Lbs, int hourr, int hourb, int hourW, int hourWe)
Any of these that you want echoed back to the caller (and that looks like all of them from a cursory glance) should be pass by reference rather than pass by value.
You should also look into calculateCalories as well, since that is doing the same thing. Keep in mind that only the ones you want to change and echo back to the caller need to be pass-by-reference. So that's only the ones starting with cal.
And, since you're using the pass-by-reference to modify the variables, there's absolutely no reason to return anything from that function so it can be specified as void calculateCalories ... and the return statements removed (in any case, only the first return would have actually done anything, the others would have been unreachable code).
If you haven't yet got to the point where you can use references in your classwork (as seems to be indicated by one of your comments), you can do what C coders have been doing for decades, emulating pass-by-reference with pointers. In terms of the simplified example above, that would mean modifying the function to receive a pointer to the item you want changed, changing what it points to, and calling it with the address of the variable to be changed:
void xyzzy (int *pPlugh) { *pPlugh = 42; }
int main() {
int twisty = 7;
xyzzy (&twisty);
cout << twisty << '\n';
return 0;
}
However, it's a poor substitute for the real thing and, if your educator is trying to teach you that, it's the same as if they're getting you to use printf/scanf rather than cout/cin for user I/O: it's certainly possible in C++ since the language includes legacy C stuff, but it's not really teaching you the C++ way.
People who claim to be C++ developers but really code in C using a C++ compiler, are a rather strange breed that I like to call C+ developers - they've never really embraced the language properly. The sooner people put aside the legacy stuff, the better they'll be as C++ developers.
Pass the variables by references. Then the functions will be able to edit them.
Your other solution (not so much of a good idea but still working) is to create a struct/class and make the functions return it.
P.S. Your code won't work if the functions are in this order unless you add their signatures in the beginning:
int main();
int inputNumber(int,int,int,int,int);
//and so on
In input number, you can not use 'return' to return each value - it will do the first return statement.
In C++ you can use pass by reference so that values assigned to the variables will be passed back up.
In this case, via the input variables would be inputNumber so use '&' to denote the vaiables are references:
void inputNumber(int &Lbs, int &hourr, int &hourb, int &hourW, int &hourWe)
{
.
.
.
}
Similar idea for calculateCalories, get rid of the returns:
void calculateCalories(int Lbs, int hourW, int hourb, int hourr, int hourWe, double &calBad, double &calRun, double &calWal, double &calWei)
{
.
.
}
Note that we are only bothering to pass to reference for the variables that we will be passing back.
I've been trying to write a short program allowing the user to add entries to a "database", listing the entries they have put in, and the ability to clear all the entries without ending the program. Here's what i've got
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
struct BIRTH
{int month; int year;};
struct ID
{string name; bool vip; float score;
struct BIRTH date;} ;
int main(int argc, char** argv) {
ID **ptrarr;
ptrarr = new ID * [10];
for (int r=0; r<10; r++)
{ptrarr[r] = new ID[1] ;}
int counter = 0;
while(counter<100){
cout << "Type add to create a new entry" << endl;
cout << "Type list to see all entries" << endl;
cout << "Type clear to delete all entries" << endl;
cout << "Type exit to terminate" << endl;
string command = "0";
getline (cin,command);
if(command=="add")
{
cout << "Enter name" << endl;
getline (cin,ptrarr[counter][1].name);
cout << "VIP? 1 for yes, 0 for no" << endl;
cin >> ptrarr[counter][1].vip;
cout << "Enter score" << endl;
cin >> ptrarr[counter][1].score;
cout << "Month of birth" << endl;
cin >> ptrarr[counter][1].date.month;
cout << "Year of birth" << endl;
cin >> ptrarr[counter][1].date.year;
counter++;
}
else if(command=="list")
{
for (int i=0; i<counter; i++)
{int n=i+1;
cout << n << " "
<< ptrarr[i][1].name << " ";
if (ptrarr[i][1].vip)
{cout << "VIP ";}
cout << "Score: " << ptrarr[i][1].score << " "
<< "Born: " << ptrarr[i][1].date.month << "/" << ptrarr[i][1].date.year << endl;
}
}
else if(command=="clear")
{delete[] ptrarr;
cout << "Entries cleared" << endl;}
else if(command=="exit")
{return 0;}
else
cout << "try again" << endl;
}
return 0;
}
Now here's the deal: the following code successfully compiles, but when I type in the "add" command, the program crashes (achievement unlocked, didn't think it's possible to obtain with such a short code). The most important thing is that the array is made of a multitype structure and that the "clear" command wipes out all the entries in the array.
NOTE: I understand that there are thousand better ways to write this piece of code, but I'm writing it to practice the things I have covered so far regarding C++. So unless it is absolutely necessary for the code to run, please do not introduce any new gimmicks =)
Replace all ptrarr[counter][1] with ptrarr[counter][0] fixes the problem.
Further advices:
I. This code has redundancy:
ID **ptrarr;
ptrarr = new ID * [10];
for (int r=0; r<10; r++)
{ptrarr[r] = new ID[1] ;}
Replace it with:
ID *ptrarr;
ptrarr = new ID [10];
Then you do not need extra [0] at the end of each ptrarr[counter]
II. functions make your code more readable:
if(command=="add")
add();
else if(command=="list")
list();
else if(command=="clear")
clear();
else if(command=="exit")
return 0;
else
cout << "try again" << endl;
Then decisions are made in a smaller area (Good practice for large programs.)
III. There is another mistake in your code:
else if(command=="clear")
{delete[] ptrarr;
cout << "Entries cleared" << endl;}
Here you should reset the counter. Also if you regard my point (I) this part is fine. Otherwise, if you use new with a for loop, I am afraid that you need to delete with a for loop too. Merely removing the root of the array tree brings you memory leak!
Also, if you cleared the list by delete, wont you need to store data in the list anymore? Using delete in linked lists is a good idea, but it does not apply here. Just reseting the counter does the job and it does not show IDs in the list anymore. The for inside the list does only count up to the counter.
If you exit the program don't you free the memory?
I say
delete [] ptrarr;
is good for being at exit.
You are creating an an array of pointers, each one of which points to one element:
ptrarr[r] = new ID[1] ;
The maximum index that you can use with ptrarr[r] is 0. Since you are using ptrarr[counter][1], you are accessing memory that is out of bounds. This leads to undefined behavior. Crashing is one such undefined behavior.
There are other issues with your code that you may want to fix.
More out of bounds memory access
You are using:
int counter = 0;
while(counter<100){
...
getline (cin,ptrarr[counter][1].name);
That is again going to lead to undefined behavior if counter > 10 since you allocated only 10 pointers for ptrarr.
Deleting the contents
You are using:
else if(command=="clear")
{
delete[] ptrarr;
cout << "Entries cleared" << endl;
}
There are couple of problems with this:
You have memory leak. You never call delete [] on what ptrarr[0] - ptrarr[9] point to. You'll have to use:
else if(command=="clear")
{
for ( int i = 0; i < 10; ++i )
{
delete [] ptrarr[i];
}
delete[] ptrarr;
cout << "Entries cleared" << endl;
}
Remember that every allocation must have a corresponding deallocation. Otherwise, you are leaking memory.
Once you call delete [] ptrarr;, it points to dangling memory. I don't see any code that reallocates memory for ptrarr while you continue to use it.
You need to reallocate memory and reset counter to 0 when the user chooses "clear".
My suggestion
You don't two levels of pointers. You just need something like:
int const MAX_ITEMS = 100;
ID* IDarr = new ID[MAX_ITEMS];
Instead of ptrarr[counter][1], use IDarr[counter].
Use MAX_ITEMS in the expression of the while statement instead of the magic number 100.
int counter = 0;
while(counter<MAX_ITEMS){
When processing "clear", you don't need to deallocate or allocate memory. Just reset counter.
else if(command=="clear")
{
counter = 0;
cout << "Entries cleared" << endl;
}
Make sure to deallocate memory before returning from main.
Here's the complete main function with the changes:
int main(int argc, char** argv) {
const int MAX_ITEMS = 100;
ID* IDarr = new ID[MAX_ITEMS];
int counter = 0;
while(counter < MAX_ITEMS){
cout << "Type add to create a new entry" << endl;
cout << "Type list to see all entries" << endl;
cout << "Type clear to delete all entries" << endl;
cout << "Type exit to terminate" << endl;
string command = "0";
getline (cin,command);
if(command=="add")
{
cout << "Enter name" << endl;
getline (cin, IDarr[counter].name);
cout << "VIP? 1 for yes, 0 for no" << endl;
cin >> IDarr[counter].vip;
cout << "Enter score" << endl;
cin >> IDarr[counter].score;
cout << "Month of birth" << endl;
cin >> IDarr[counter].date.month;
cout << "Year of birth" << endl;
cin >> IDarr[counter].date.year;
counter++;
}
else if(command=="list")
{
for (int i=0; i<counter; i++)
{
int n=i+1;
cout << n << " " << IDarr[i].name << " ";
if (IDarr[i].vip)
{
cout << "VIP ";
}
cout
<< "Score: " << IDarr[i].score << " "
<< "Born: " << IDarr[i].date.month << "/" << IDarr[i].date.year << endl;
}
}
else if(command=="clear")
{
counter = 0;
cout << "Entries cleared" << endl;
}
else if(command=="exit")
{
// Don't use return 0;
// Just break out of the while loop so that memory
// can be deallocated at the end of this function.
break;
}
else
cout << "try again" << endl;
}
delete [] IDarr;
return 0;
}
Array indices start at 0.
ptrarr[counter][1] refers to the second element of ptrarr[counter]. ptrarr[counter] points to an array of one element.
try this :
if(command=="add") {
cout << "Enter name" << endl;
getline (cin,ptrarr[counter][0].name);
cout << "VIP? 1 for yes, 0 for no" << endl;
cin >> ptrarr[counter][0].vip;
cout << "Enter score" << endl;
cin >> ptrarr[counter][0].score;
cout << "Month of birth" << endl;
cin >> ptrarr[counter][0].date.month;
cout << "Year of birth" << endl;
cin >> ptrarr[counter][0].date.year;
counter++;
}
else if(command=="list") {
for (int i=0; i<counter; i++){
int n=i+1;
cout << n << " "<< ptrarr[i][0].name << " ";
if (ptrarr[i][0].vip){
cout << "VIP ";
}
cout << "Score: " << ptrarr[i][0].score << " "
<< "Born: " << ptrarr[i][0].date.month << "/" << ptrarr[i][0].date.year << endl;
}
}
Conclusion :
Just as you initialized counter with 0 you should have used 0 index to access the first element;
Same goes while listing.
Arrays are 0 index based.
The purpose of this program is for the user to declare the size of their array, then have various functions operate on it. My problem is I realize nothing valid is declared in FunctionTwo. How can I get information from my main function to FunctionTwo and so on for my other functions as well?
int main()
{
srand(time(NULL));
int arraySize = 0;
cout << "How large would you like your array to be?" << endl;
cin >> arraySize;
int theArray [arraySize];
int selection = 0;
cout << "What would you like to do with your array? " << endl << endl;
cout << "1. Pass in an integer location and return the value. " << endl;
cout << "2. Initialize an array of all 0's. " << endl;
cout << "3. Initialize an array of random numbers between 1 and your specification. " << endl;
cout << "4. Populate an array one at a time. " << endl;
cout << "5. Select a position in the array and set that value to your specification. " << endl;
cout << "6. Print the entire array. " << endl;
cout << "7. Find the average of each value in the array. " << endl;
cout << "8. Find the largest element of the array. " << endl;
cout << "9. Find the smallest element of the array. " << endl;
cout << "12. Print all numbers in the array larger than your input. " << endl;
cout << "13. Tell if the array is empty. " << endl;
cout << "15. Return the difference between the largest and smallest value in the array. " << endl;
cin >> selection;
}
int FunctionTwo()
{
int theArray [arraySize] = {0};
return theArray;
}
int theArray [arraySize]; is not valid C++ if arraySize is only known at run-time.
The correct solution for your problem in C++:
std::vector<int> theArray(arraySize);
In C++ the size of an array shall be a constant expression known at compile time. This code
int arraySize = 0;
cout << "How large would you like your array to be?" << endl;
cin >> arraySize;
int theArray [arraySize];
is not C++ compliant because variable arraySize is not a constant expression.
So either you will set a fixed size of the array yourself without asking the user to specify the size as for example
const int arraySize = 20;
int theArray [arraySize];
or you must to allocate dynamically the array as for example
int arraySize = 0;
cout << "How large would you like your array to be?" << endl;
cin >> arraySize;
int *theArray = new int[arraySize];
In this case do not forget to delete the array before exiting the program:
delete []theArray;
You could use standard container std::vector<int> but I am sure that your assignment requires to use an array.
As for the function call of FunctionTwo then the function has to have two parameters: pointer to the first element of the array and the number of elements in the array. There is no sense to declare its return type as int, It would be better to declare it as void Here an example
void FunctionTwo( int theArray[], int arraySize )
{
for ( int i = 0; i < arraySize; i++ ) theArray[i] = 0;
}
Or you may use standard algorithm std::fill. For example
#include <algorithm>
//...
void FunctionTwo( int theArray[], int arraySize )
{
std::fill( theArray, theArray + arraySize, 0 );
}
Here is an example of so-called FunctionThree that has to initialize the array with random numbers in the range [1, n]
void FunctionThree( int theArray[], int arraySize, int n )
{
for ( int i = 0; i < arraySize; i++ ) theArray[i] = std::rand() % n + 1;
}
Or the same but using standard algorithm std:::generate
#include <algorithm>
//...
void FunctionThree( int theArray[], int arraySize, int n )
{
std::generate( theArray, theArray + arraySize, [&] { return ( std::rand() % n + 1 ); } );
}
Take into account that functions shall be declared before their usage.
As for the menu that it should be enclosed in a loop. For example
do
{
cout << "What would you like to do with your array? " << endl << endl;
cout << "1. Pass in an integer location and return the value. " << endl;
cout << "2. Initialize an array of all 0's. " << endl;
cout << "3. Initialize an array of random numbers between 1 and your specification. " << endl;
cout << "4. Populate an array one at a time. " << endl;
cout << "5. Select a position in the array and set that value to your specification. " << endl;
cout << "6. Print the entire array. " << endl;
cout << "7. Find the average of each value in the array. " << endl;
cout << "8. Find the largest element of the array. " << endl;
cout << "9. Find the smallest element of the array. " << endl;
cout << "12. Print all numbers in the array larger than your input. " << endl;
cout << "13. Tell if the array is empty. " << endl;
cout << "15. Return the difference between the largest and smallest value in the array. " << endl;
cout << "\n0. Exit from the program" << endl;
cin >> selection;
//...some other code
} while ( selection != 0 );
How can I get information from my main function to FunctionTwo and so on for my other functions as well?
You can provide function arguments. For example:
int FunctionTwo(std::vector<int>& the_vector)
Then in main():
switch (selection)
{
case 2: FunctionTwo(the_vector); break;
...other cases...
}
int FunctionTwo(int[] theArray) {}
This would allow you to use theArray inside the function. Hopefully this is what you meant. I was somewhat unclear on exactly what you wanted to do.
Now you can call the function as so:
FunctionTwo(anArray);
i would like to resize my ZZ vector during running program. Is there any way, how to make it? I found methods .setLenght() alternatively .DosetLenght(), but it seems like only initialization step, due to my pro/gram refuses change the vector with these methods..
Many thanks.
Vec<ZZ> v1,v2;
v1.SetLength(8);
v2.SetLength(8);
ZZ velkeCislo,odmocnina,factor,test;
long i = 0;
cin >> velkeCislo;
odmocnina = SqrRoot(velkeCislo);
cout << "new v1 dlzka " << v1.length() << endl;
for(i=0;i<v1.length();i++) {
v1(i) = odmocnina;
odmocnina++;
cout << "Number1 " << v1(i) << endl;
}
for(i=0;i<v1.length();i++){
v2(i)=(v1(i)*v1(i))-velkeCislo;
cout << "Number2 " << v2(i) << endl;
}
bool found=false;
int tp = v1.length();
cout << "old v1 " << v1.length() << endl;
v1.SetLength(tp+1); //causes error
cout << "new v1 " << v1.length() << endl;
The problem with your code is also explained here. You are using the method v1(i) to access the array, but this is a 1-based indexing system so you have out of bounds accesses in your program. Replace v1(i) with v1[i] (which is zero-based) and your program should work.
so i made a DOS program however my game always crashes on my second time running to the cin function.
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
using namespace std;
//call functions
int create_enemyHP (int a);
int create_enemyAtk (int a);
int find_Enemy(int a);
int create_enemyDef (int a);
// user information
int userHP = 100;
int userAtk = 10;
int userDef = 5;
string userName;
//enemy Information
int enemyHP;
int enemyAtk;
int enemyDef;
string enemies[] = {"Raider", "Bandit", "Mugger"};
int sizeOfEnemies = sizeof(enemies) / sizeof(int);
string currentEnemy;
int chooseEnemy;
// ACTIONS
int journey;
int test;
int main()
{
// main menu
cout << "welcome brave knight, what is your name? " ;
cin >> userName;
cout << "welcome " << userName << " to Darland" << endl;
//TRAVELING
MENU:
cout << "where would you like to travel? " << endl;
cout << endl << " 1.> Theives Pass " << endl;
cout << " 2.> Humble Town " << endl;
cout << " 3.> Mission HQ " << endl;
cin >> journey;
if (journey == 1)
{
// action variable;
string c_action;
cout << "beware your journey grows dangerous " << endl;
//begins battle
// Creating the enemy, HP ATK DEF AND TYPE. ;
srand(time(0));
enemyHP = create_enemyHP(userHP);
enemyAtk = create_enemyAtk(userAtk);
enemyDef = create_enemyDef(userDef);
chooseEnemy = find_Enemy(sizeOfEnemies);
currentEnemy = enemies[chooseEnemy];
cout << " Here comes a " << currentEnemy << endl;
cout << "stats: " << endl;
cout << "HP :" << enemyHP << endl;
cout << "Attack : " << enemyAtk << endl;
cout << "Defense : " << enemyDef << endl;
ACTIONS:
cout << "Attack <A> | Defend <D> | Items <I>";
cin >> c_action;
//if ATTACK/DEFEND/ITEMS choice
if (c_action == "A" || c_action == "a"){
enemyHP = enemyHP - userAtk;
cout << " you attack the enemy reducing his health to " << enemyHP << endl;
userHP = userHP - enemyAtk;
cout << "however he lashes back causing you to have " << userHP << "health left " << endl;
//end of ATTACK ACTION
}
the last line "cin >> c_action crashes. i use two other pages. they just create the functions. is it a complier issue. also why does my complier always shutdown after it runs he app. is there a way to stop it?
A few hints:
I never use forward declarations of functions ( such as "int create_enemyHP (int a);" ) if I can avoid them. If you do this then there are two places in your code that must be correct for your program to work. It makes life easier if there is always a "single source of truth"
Have you run this code through the debugger? It will help you find problems much more quickly.
If your c_action variable is only intended to be a char, I'd suggest to use a char variable, rather than a string.
You might want to try this way, and if you're still faced with an error, you might give
scanf("%c", &c_action); //assuming you used a char.
I didn't understand if the program crashes before you type the "action" or after. Because if it crashes before, then I think your problems are caused by white spaces characters in the input buffer.