C text game segmentation fault and debugging - c

I wanted to wrote a simple text game in C. The game generates random 2D position using 2 double variables in range from -10.000 to 10.000 (X, Y) as the "treasure" position. Player begins at position 0.000, 0.000. Then the game asks the player which directions to go in X and Y. After that the game needs to give the player a simple hint, if he's getting closer(right or wrong direction based on the treasure position). When the player is less than 0.050 away from treasure in any direction, the game ends and prints out the score(cycle steps).
I wrote this, but I'm getting 'Segmentation fault' and I'm also interested about how would you modify it to get it more effective and functional.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int main()
{
srand (time(NULL));
char *direction_x;
char *direction_y;
double direction_forward;
double direction_back;
double direction_left;
double direction_right;
double score_x;
double score_y;
double diff_x;
double diff_y;
double lastmove_x;
double lastmove_y;
int i;
double random_x = (double)rand()/RAND_MAX*20.000-10.000;
double rounded_x = (int)(random_x * 1000.0)/1000.0;
printf ( "%f\n", random_x);
printf ( "%.3f\n", rounded_x);
double random_y = (double)rand()/RAND_MAX*20.000-10.000;
double rounded_y = (int)(random_y * 1000.0)/1000.0;
printf ( "%f\n", random_y);
printf ( "%.3f\n", rounded_y);
double player_x=0.000;
double player_y=0.000;
printf("Hello freind! Let's find the hidden treasure!\n");
do{
i++;
printf("Where would you want to go? ('straight', 'back')\n");
scanf("%s", &direction_x);
if (strcmp(direction_x, "straight") == 0)
{
printf("How far?\n");
scanf("%f", &direction_forward);
player_x = player_x + direction_forward;
printf("You've walked %.3f straight!\n", direction_forward);
printf("Your current postion is: %.3f, %.3f.\n", player_x, player_y);
diff_x = random_x - player_x;
if (diff_x < random_x)
{
printf("You're closer...\n");
}
else
{
printf("Don't like this way...\n");
}
}
else if (strcmp(direction_x, "back") == 0)
{
printf("How far?\n");
scanf("%f", &direction_back);
player_x = player_x - direction_back;
printf("You've walked %.3f backwards!\n", direction_back);
printf("Your current position is: %.3f, %.3f.\n", player_x, player_y);
if (diff_x < random_x)
{
printf("You're closer...\n");
}
else
{
printf("Don't like this way...\n");
}
}
else
{
printf("Don't accept this direction...\n");
}
printf("Where now? ('left', 'right')\n");
scanf("%s", &direction_y);
if (strcmp(direction_y, "left") == 0)
{
printf("How far?\n");
scanf("%f", &direction_left);
player_y = player_y + direction_left;
printf("You've walked %.3f left!\n", direction_left);
printf("Your current position is: %.3f, %.3f.\n", player_x, player_y);
if (diff_y < random_y)
{
printf("You're closer...\n");
}
else
{
printf("Don't like this way...\n");
}
}
else if (strcmp(direction_y, "right") == 0)
{
printf("How far?\n");
scanf("%f", &direction_right);
player_y = player_y - direction_right;
printf("You've walked %.3f right!\n", direction_right);
printf("Your current position is: %.3f, %.3f.\n", player_x, player_y);
if (diff_y < random_y)
{
printf("You're closer...\n");
}
else
{
printf("Don't like this way...\n");
}
}
else
{
printf("Don't accept this direction...\n");
}
score_x = (player_x + 0.050) - random_x;
score_y = (player_y + 0.050) - random_y;
}while ((-0.050 <= score_x <= 0.050) || (-0.050 <= score_y <= 0.050));
printf("Congratulations, treasure was finally founded! Treasure position is %.3f, %.3f.\n", random_x, random_y);
printf("Score (steps taken, less is better): %d\n", i);
return 0;
}

I just tried to compile your code.
First: If you use scanf() you should specify "%lf" if you want to read in a double. For example:
scanf("%lf", &direction_right);
Second: Many of your variables are not initialized. The first segmentation fault will likely be thrown at the beginning of your while-loop at this line:
scanf("%s", &direction_x);
because direction_x is not initialized it stores a pointer with a random value. This means, that it is pointing to somewhere in your memory, depending on the value previously stored at the spot where direction_x was located to. This likely causes the crash.
Avoid this by declaring an array like so.
char direction_x[42];
char direction_y[42];
But don't forget to check your input lengths!
There are many more variables you use before initializing them. Check your compilerwarnings by adding the flag -Wall (if you are using gcc).
Third: Try to structure your code. anything within a if-else statement can be put into an own function. This will help you and anyone else who tries to understand your code.

char *direction_x; and char *direction_y; should be like char st[1024] for use in scanf
i must init before use it
scanf("%s", &direction_x); should be scanf("%s", direction_x);
For double should use %lf, not %f
-0.050 <= score_x <= 0.050 should be -0.050 <= score_x && score_x <= 0.050
and so on ...
I rewrite it.
The follow code could work:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <math.h>
int main()
{
srand (time(NULL));
double random_x = (double)rand()/RAND_MAX*20.000-10.000;
double random_y = (double)rand()/RAND_MAX*20.000-10.000;
double player_x=0.000;
double player_y=0.000;
double score_x;
double score_y;
int step = 0;
printf("Hello friend! Let's find the hidden treasure!\n");
do {
step++;
char st[1024];
double data;
printf("Where would you want to go? (horizontal or vertical)\n");
scanf("%s", st);
printf("How far?\n");
scanf("%lf", &data);
if (strcmp(st, "horizontal") == 0)
{
player_x = player_x + data;
printf("You've walked %.3f left!\n", data);
printf("Your current position is: %.3f, %.3f.\n", player_x, player_y);
if (fabs(player_x - random_x) < fabs(player_x - data - random_x))
printf("You're closer...\n");
else
printf("Don't like this way...\n");
}
else if (strcmp(st, "vertical") == 0)
{
player_y = player_y + data;
printf("You've walked %.3f down!\n", data);
printf("Your current position is: %.3f, %.3f.\n", player_x, player_y);
if (fabs(player_y - random_y) < fabs(player_y - data - random_y))
printf("You're closer...\n");
else
printf("Don't like this way...\n");
} else {
continue;
}
score_x = player_x - random_x;
score_y = player_y - random_y;
} while (fabs(score_x) > 0.050 && fabs(score_y) > 0.050);
printf("Congratulations, treasure was finally founded! Treasure position is %.3f, %.3f.\n", random_x, random_y);
printf("Score (steps taken, less is better): %d\n", step);
return 0;
}

Related

"error: implicit declaration of function 'srand' is invalid in C99" Adding stdlib.h header removes this error but why?

Initially, I didn't have the stdlib.h header on the file and I got the error on VS Code but the code seemed correct to me, and I resolved any other existing errors, so I copied and pasted the code onto an online compiler (without adding the stdlib.h header) and the code worked perfectly. Is this because I may just have an older or maybe bad toolset installed onto my computer for VS Code? I have the program written below:
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
main()
{
int dice1, dice2;
int total1, total2;
time_t t;
char ans;
//Remember that this is needed to to make sure each random number
//generated is different
srand(time(&t));
//This would give you a number between 0 and 5, so the + 1
//makes it 1 to 6
dice1 = (rand() % 5) + 1;
dice2 = (rand() % 5) + 1;
total1 = dice1 + dice2;
printf("First roll of the dice was %d and %d, ", dice1, dice2);
printf("for a total of %d.\n\n\n", total1);
//Asks you to make a guess for your next roll.
do
{
puts("Do you think the next roll will be ");
puts("(H)igher, (L)ower, or (S)ame?\n");
puts("Enter H, L, or S to reflect your guess.");
scanf(" %c", &ans);
ans = toupper(ans);
}
while ((ans != 'H') && (ans != 'L') && (ans != 'S'));
//Roll the dice a second time to get your second total
dice1 = (rand() % 5) + 1;
dice2 = (rand() % 5) + 1;
total2 = dice1 + dice2;
//Display the second total for the user
printf("\nThe second roll was %d and %d, ", dice1, dice2);
printf("for a total of %d.\n\n\n", total2);
//Now compare the two dice totals against the users guess
//and tell them if they were right or not
if (ans == 'L')
{
if (total2 < total1)
{
printf("Good job! You were right!\n");
printf("%d is lower than %d\n", total2, total1);
}
else
{
printf("Sorry! %d is not lower than %d\n\n", total2, total1);
}
}
else if (ans == 'H')
{
if (total2 > total1)
{
printf("Good job! You were right!\n");
printf("%d is higher than %d\n", total2, total1);
}
else
{
printf("Sorry! %d is not lower than %d\n\n", total2, total1);
}
}
else if (ans == 'S')
{
if (total2 == total1)
{
printf("Good job! You were right!\n");
printf("%d is the same as %d\n", total2, total1);
}
else
{
printf("Sorry! %d is not lower than %d\n\n", total2, total1);
}
}
return 0;
}
A declaration must be provided.[1] #include <stdlib.h> is the normal way of doing that.
Defined in header <stdlib.h>
void srand( unsigned seed );
Maybe the online compiler implicitly includes it for you, or maybe it was indirectly included by another library. Regardless, you should use #include <stdlib.h>.
In C99 or later, this is the case for all functions. (Do note that a definition acts as a declaration.) Before C99, srand still needed one because its signature didn't match the default one.

How do I add a loop for scanf in C?

I have a short question:
How can I expand my program so that it checks if I entered the right format?... if not the program should repeat the scanf.
This is how far I came:
#include <stdio.h>
int main()
{
float zahlen[2];
int i = 0;
while (i < 2 && zahlen != EOF) {
printf("%d. Zahl", i + 1);
scanf_s("%f", &zahlen[i]);
}
printf("Division: %f\n", zahlen[0] / zahlen[1]);
printf("Produkt: %f\n", zahlen[0] * zahlen[1]);
printf("Summe: %f\n", zahlen[0] + zahlen[1]);
printf("Diffenrenz: %f\n", zahlen[0] - zahlen[1]);
printf("Mittelwert: %f\n", (zahlen[0] + zahlen[1]) / 2);
getchar();
return 0;
}
Would appreciate any help of you. Have a nice day/night.
You should define what a right format is. But in a form of pseudo-code
float input;
// First get the input
do {
sacnf_s("%f", &input);
} while (!IsRightFormat(input)); // If the input was not correct get it again
// Do your stuff here
// ...

Infinite loop in c due to rounding?

The following code is looping infinitely. I believe it may be a rounding issue though not entirely sure.
I am fairly new to C so not sure why I'm getting the infinite looping that I'm getting. The code seems to make sense though keeps looping.
#include <stdio.h>
#include <cs50.h>
#include <math.h>
#include <string.h>
int main(void){
float quarter = .25;
int Qtr = 0;
float dime = .10;
int Dm = 0;
float nickel = .5;
int Nck = 0;
float penney = .01;
int Pn = 0;
float change;
float userInput;
float newspaperCost;
do{
printf("How much is the news paper today: \n");
newspaperCost = GetFloat();
printf("Amount Tendered: ");
userInput = GetFloat();
printf("You entered $%2.2f\n", userInput);
change = userInput - newspaperCost;
printf("Change: $%2.2f\n", change);
}
while(newspaperCost <= 0);
while(change > 0){
printf("%f\n", change);
while(change - quarter > 0){
change = change - quarter;
Qtr++;
}
while(change - dime > 0){
change = change - dime;
Dm++;
}
while(change - nickel > 0){
change = change - nickel;
Nck++;
}
while(change - penney > 0){
change = change - penney;
Pn++;
}
}
printf("Your change consists of %d quarters, %d dimes, %d nickels, and %d pennies\n", Qtr, Dm, Nck, Pn);
} //end main
You have a logic error in the last while loop.
Instead of
while(change - penney > 0){
change = change - penney;
Pn++;
}
Use
while(change > 0){
change = change - penney;
Pn++;
}
Don't use floating point to represent currency.
Prefer double over float unless you have a good reason.
penny*
You're not using any equality operators with floating point operands, so you probably have a logical error.
Your code:
do{
printf("How much is the news paper today: \n");
newspaperCost = GetFloat();
printf("Amount Tendered: ");
userInput = GetFloat();
printf("You entered $%2.2f\n", userInput);
change = userInput - newspaperCost;
printf("Change: $%2.2f\n", change);
} while(newspaperCost <= 0);
Won't exit this loop while newspaperCost <= 0. I'm assuming you aren't inputting a negative number at
printf("How much is the news paper today: \n");
newspaperCost = GetFloat();
That's why you have an infinite loop.

For Loop in C- implementation

I am confused on how to complete this for loop. The mission is to read input in unix. For the input if the radius is >0 it should prompt the user each time and then if <=0 it should terminate. I am going from centimeters to square inches. My current configuration requires 2 inputs (1 prompted, 1 not) before giving output to the console. Cheers.
#include <stdio.h>
#define PI 3.14159
main()
{
float r, a;
int y = 9999999;
for(int i =0; i <y; i++){
printf("Enter the circle's radius (in centimeters): ");
scanf ("%f", &r);
if(r>0){
r=r;
a = PI * r * r *2.54;
printf("Its area is %3.2f square inches.\n", a);
} else {}
}
}
Your code flow is the following:
for (infinite condition) {
scan input
if (input > 0) {
do things
}
else {
do nothing
}
}
So there's no way to exit out of the loop, that's why the break statement exists, to force quitting an iterative block of code:
while (true) {
scanf ("%f", &r);
if (r > 0) {
// do whatever;
}
else
break;
}
The break will stop the cycle when executed, just going out of the loop.
You may want to try using a while loop instead so that the question is continually prompted until the user inputs a value =>0. see if below helps (also your conversion factor was not quite right);
#include <stdio.h>
#define PI 3.14159
void main()
{
float r, a;
printf("Enter the cirle's radius (in centimeters):");
scanf("%f",&r);
while (r>0)
{
a=PI*r*r*0.155; // conversion from sqcm to sqin is ~0.155
printf("Its area is %3.2f square inches \n", a);
printf("Enter the cirle's radius (in centimeters):");
scanf("%f",&r);
}
}
r=1.0f;
// break if no. of cases exhausted or r is negative or zero
for(int i =0; i < y && r > 0; i++)
{
printf("Enter the circle's radius (in centimeters): ");
if( scanf ("%f", &r) == 1) // Always check for successful scanf
{
a = PI * r * r/2.54/2.54; //This is correct formula
printf("Its area is %3.2f square inches.\n", a);
}
}
Consider a while loop instead:
#include <stdio.h>
#define PI 3.14159
main(){
float r, a;
int continueBool = 1;
while(continueBool == 1){
printf("Enter the circle's radius (in centimeters): ");
scanf ("%f", &r);
if(r>0){
a = PI * r * r *2.54;
//the above formula may be wrong, so consider trying:
//a = PI * r * r/2.54/2.54;
printf("Its area is %3.2f square inches.\n", a);
}
else{
continueBool = 0;
}
}
}
The break statement can be dangerous if you are new to C programming, so I recommend not using it until you get a better understanding of C and break. If you do want to use break, then this could be your solution:
#include <stdio.h>
#define PI 3.14159
main(){
float r, a;
while(1){
printf("Enter the circle's radius (in centimeters): ");
scanf ("%f", &r);
if(r<=0){
break;
}
a = PI * r * r *2.54;
//the above formula may be wrong, so consider trying:
//a = PI * r * r/2.54/2.54;
printf("Its area is %3.2f square inches.\n", a);
}
}
Use this:
for(int i =0; i < y; i++)
{
printf("Enter the circle's radius (in centimeters): ");
scanf ("%f", &r);
if(r > 0)
{
a = PI * r * r *2.54;
printf("Its area is %3.2f square inches.\n", a);
}
else
{
break;
}
}

BMI classification structure

I am working on an assignment in C where I have to read in multiple people's heights and weights and determine their bmi. I then classify them into their respective bmi categories, but I am getting stuck on how to do this properly, this is my code thus far:
# include <stdio.h>
int main () {
int people;
double bmi, weight, inches;
printf("How many peoples? > ");
scanf("%d", &people);
do {
printf("Enter height (inches) and weight (lbs) (%d left) > ", people);
scanf("%lf %lf", &inches, &weight);
people--;
}
while (people > 0);
bmi = (weight / (inches * inches)) * 703;
if (bmi < 18.5) {
printf("Under weight: %d\n", people);
}
else if (bmi >= 18.5 && bmi < 25) {
printf("Normal weight: %d\n", people);
}
else if (bmi >= 25 && bmi < 30) {
printf("Over weight: %d\n", people);
}
else if (bmi >= 30) {
printf("Obese: %d\n", people);
}
return 0;
}
where am i going wrong? where do i fix this code?
Use some data structure for storing data. You are getting input for more than one people but, finally processed for one person.
And also people--; is done. so people variable is decremented up to zero, which makes while to exit without executing your BMI calculation.
Modified Code:
#include <stdio.h>
#define MAX_PEOPLE 100
int main () {
int people;
double bmi[MAX_PEOPLE], weight[MAX_PEOPLE], inches[MAX_PEOPLE];
int index = 0;
printf("How many peoples? > ");
scanf("%d", &people);
index = people;
do {
printf("Enter height (inches) and weight (lbs) (%d left) > ", index);
scanf("%lf %lf", &inches[index], &weight[index]);
index--;
}while (index > 0);
for(index = 0; index < people; index++)
{
bmi[index] = (weight[index] / (inches[index] * inches[index])) * 703;
if (bmi[index] < 18.5) {
printf("Under weight: %d\n", index);
}
else if (bmi[index] >= 18.5 && bmi[index] < 25) {
printf("Normal weight: %d\n", index);
}
else if (bmi[index] >= 25 && bmi[index] < 30) {
printf("Over weight: %d\n", index);
}
else if (bmi[index] >= 30) {
printf("Obese: %d\n", index);
}
}
return 0;
}
Right now you are processing the same data.
Each time you assign a new value to weight the old one is erased.
You could create multiple variables like so:
double weight1, weight2, weight3, weight4, ...etc (highly unpractical!!)
or
create an array of doubles:
double weight[100];
and refer to each specific double variable like this:
scanf("%lf %lf", inches[0], weight[0]);
scanf("%lf %lf", inches[1], weight[1]);
scanf("%lf %lf", inches[2], weight[2]);
You see where i-m getting at ? you can manipulate the array tru a for loop.

Resources