I am making an application for playing Dungeons & Dragons, just for fun, and I ran into a problem. I've written multiple printfs and somehow it stopped working. When it finishes the first calculation and when it has to move on to the next, then it stops. I have no idea why.
This is the code:
#include <stdio.h>
#include <stdlib.h>
#include <ctime>
#include <string>
int main(){
//variables
int dmgDice;
char entityName, dmgType;
int initiative, dmgBonus, damage, userAC, userHp;
//user input
printf("Type in your armor class: \n");
scanf("%d", &userAC);
printf("Type in your hit points : \n");
scanf("%d", &userHp);
printf("type in your initative: \n");
scanf("%d", &initiative);
printf("type in you damage bonus: \n");
scanf("%d", &dmgBonus);
printf("type in you damage type: \n");
scanf("%s", &dmgType);
printf("your damage dice: \n");
scanf("%d", &dmgDice);
printf("Entity you want to damage: \n");
scanf("%s", &entityName);
//d20 roll
srand((unsigned)time(0));
printf("d20 roll: \n");
int d20roll = (rand() % 20);
int SUM = d20roll + initiative;
printf("you have rolled SUM %d + %d = %d", d20roll, initiative, SUM);
if(d20roll > 14){
printf("\nYou've passed the enemies AC, now roll for damage!");
printf("\nYou did %d damage to the %s!", damage, entityName);
}
else{
printf("\nYou have missed, now %s attacks..", entityName);
int entityd20roll = (rand() % 20) + 1;
printf("\n%s passed your armor class, now it will roll for damage");
if(entityd20roll > userAC){
int edmg = (rand() % 12);
int hp = userHp - edmg;
if(hp < 0)
hp *= -1;
printf("\nhit points taken: \n");
printf("%s has dealt %d damge", entityName, edmg);
}
else{
printf("%s has missed you", entityName);
}
}
return 0;
}
Also, how can I create a memory file so the user doesn't have to type in everything over and over again?
I suggest including the library and trying the same thing with cout<< and cin>> because these commands work a little different.
So for example printf("Type in your armor class: \n");
becomes cout<<"Type in your armor class: "<<endl;
And scanf("%d", &userAC); becomes cin>>userAC;
And for your file saving system, I suggest you follow a class on file I/O like for example this video: https://www.youtube.com/watch?v=Iho2EdJgusQ.
You can then write all the user's options to a file and then read the information when the programs starts. This way the user's preferences will be kept.
I suggest (as #samu_242 already has done) to use the std::cout and std::cin commands for the inputs.
In your code, the printf
printf("\n%s passed your armor class, now it will roll for damage");
expects a string (%s), but you did not pass nothing. Moreover, maybe you had in mind to use array of chars, but you allocated memory for just one char:
char entityName, dmgType;
In this way, entityName will get only the first char that the user gives in input (e.g., if he/she types "Goblin" entityName will have only "G"). To declare an array of char, use
char entityName[N];
where N is the maximum length of the array. There are also ways to dynamically allocate memory, but my advise is to use the std::string.
Related
My problem was to take the inputs until user input the test value 0 and the problem is to be solved only by c language, my code below becomes infinite loop by using scanf and printf but the same code if written in C++ it works fine with no problem, Can you help me with my C program what i am missing.
#include <stdio.h>
#include <stdlib.h>
int main() {
int click,test=1,count=0;
char vote;
scanf("%d",&test);
while(test){
int i=0;
for(int i=0;i<test;i++){
scanf("%c",&vote);
scanf("%d",&click);
printf("%c %d hi \n",vote,click);
}
scanf("%d",&test);
}
//printf("%d\n",count);
return 0;
}
my test case was
2
P 1
P 2
2
P 2
M -2
0
In c++ my output comes exactly like test case but in c language its TLE or output limit exceed
When dealing with C you should always check return values of runtime functions, it is the best way to avoid getting errors like the one you have.
scanf returns the number of items that it managed to parse or 0 if it failed.
personally i prefer to use fgets() to read from the stdin and then sscanf to parse the buffer, that way you have (IMHO) a better control of what comes into the program as opposed to obscure scanf formatting. it is easy to do mistakes with scanf because one tends to forget that all input is buffered and scanf reads from that buffer.
E.g. (ocular compiled only)
int click = 0;
int test = 0;
char buffer[128];
char vote = 0;
do
{
if ( fgets(buffer,sizeof(buffer),stdin) != NULL)
{
// read number of tests
if (sscanf(buffer, "%d", &test) == 1)
{
for(int i=0; i < test; ++i)
{
if (fgets(buffer, sizeof(buffer), stdin) != NULL)
{
if (sscanf( buffer, "%c %d", &vote, &click) == 2)
{
printf( "%c %d hi \n", vote, click );
}
else
{
fprintf(stderr, "Invalid format encountered\n");
}
}
}
}
}
}
while (test);
The %c conversion specifier poses problem with leading white spaces as it won't automatically skip them. Since you're receiving inputs in loop, one way to mitigate it is via putting extra space before %c.
scanf(" %c", &vote);
I'm very new at C++, maintaining my M.Sc on Information Systems. I have my first C++ homework announced and have been working on it for a couple of days. The aim of the code is simply to read info from a text file and print it on screen, then make calculation on some of it and print results to a new text file. However when I build, it gives the error:
EXC_BAD_ACCESS (code=EXC_I386_GBFLT)
in the first fscanf in readInfo function.
I know the code I wrote is not completely efficient but I just want it to print on screen and on output file correctly. I would really appreciate if anyone help me to resolve this error. I am about to freak out...
#include <stdio.h>
typedef struct {
char id[10];
char name[40];
float midterm;
float final;
int attendance;
}Student;
void readInfo(Student studentList[], int *count)
{
FILE *fin=fopen("scores.txt","r");
char surname = '\0';
*count=0;
while(!feof(fin))
{
fscanf(fin,"%c %c %c %f %f %d",studentList[*count].id, studentList[*count].name, &surname, &studentList[*count].midterm, &studentList[*count].final, &studentList[*count].attendance);
strcpy(studentList[*count].name, studentList[*count].name);
strcat(studentList[*count].name, " ");
strcat(studentList[*count].name, &surname);
*count++;
}fclose(fin);
printf("%-7s%17s %5.1f %5.1f %-2d\n", studentList[*count].id, studentList[*count].name, studentList[*count].midterm, studentList[*count].final, studentList[*count].attendance);
}
float studentScore(float midterm, float final, int attendance)
{
float score;
int maxAttend=0;
char id[10];
char name[40];
char surname[40];
FILE *fin=fopen("scores.txt","r");
while(!feof(fin))
{
fscanf(fin,"%c %c %c %f %f %d",id, name, surname, &midterm, &final, &attendance);
if(attendance>maxAttend)
maxAttend=attendance;
}fclose(fin);
score=midterm*0.3+final*0.5+(maxAttend/20)*attendance;
return score;
}
float avgScore(Student studentList[])
{
float average;
int count;
int totalScore=0;
readInfo(studentList, &count);
for(int i=0; i<=count; i++)
{
totalScore+=studentScore(studentList[count].midterm, studentList[count].final, studentList[count].attendance);
}
average=totalScore/count;
return average;
}
void courseGradeOutput(Student studentList[])
{
FILE *fout=fopen("output.txt","w");
int count;
int pass=0;
float score;
char letterGrade[2];
float avg;
fprintf(fout,"\tId\tName, Surname = (Score, Letter)\n");
readInfo(studentList, &count);
for(int i=0; i<=count; i++)
{
score=studentScore(studentList[i].midterm, studentList[i].final, studentList[i].attendance);
if(score>=0 && score<=49)
{ letterGrade[0]={'F'};
letterGrade[1]={'F'};}
else if (score>=50 && score<=59)
{letterGrade[0]={'F'};
letterGrade[1]={'D'};}
else if (score>=60 && score<=64)
{letterGrade[0]={'D'};
letterGrade[1]={'D'};}
else if (score>=65 && score<=69)
{letterGrade[0]={'D'};
letterGrade[1]={'C'};}
else if (score>=70 && score<=74)
{letterGrade[0]={'C'};
letterGrade[1]={'C'};}
else if (score>=75 && score<=79)
{letterGrade[0]={'C'};
letterGrade[1]={'B'};}
else if (score>=80 && score<=84)
{letterGrade[0]={'B'};
letterGrade[1]={'B'};}
else if (score>=85 && score<=89)
{letterGrade[0]={'B'};
letterGrade[1]={'A'};}
else if (score>=90 && score<=100)
{letterGrade[0]={'A'};
letterGrade[1]={'A'};}
if(score>=60)
pass++;
fprintf(fout,"%7s %16s = ( %4.1f, %6s\n)", studentList[i].id, studentList[i].name, score, letterGrade);
}
avg=avgScore(studentList);
fprintf(fout,"\nSome statistics:\n\nClass Avg Score: %5.2f \n #Students: %11d \n #Passed Students: %4d \n #Failed Students: %4d",avg,count,pass,(count-pass));
fclose(fout);
}
int main()
{ Student studentList[100];
int count;
readInfo(studentList, &count);
courseGradeOutput(studentList);
}
Screenshot
The crash is most likely caused by either fscanf followed by strcpy and/or by your increment of count inside readInfo.
You write *count++, but this is equivalent to
count = count + 1;
*(count-1);
What you want is (*count)++.
The fscanf scans characters %c where you want to scan strings %s (for id and name). You also want to scan surname as a string, probably, but then you need to change surname to be a character array:
char surname[30];
*count=0;
while(!feof(fin))
{
fscanf(fin,"%s %s %s %f %f %d",studentList[*count].id, studentList[*count].name, surname, &studentList[*count].midterm, &studentList[*count].final, &studentList[*count].attendance);
strcat(studentList[*count].name, " ");
strcat(studentList[*count].name, surname);
(*count)++;
}
fclose(fin);
I also removed the first strcpy as you were copying from a buffer to itself, which is not allowed.
I haven't checked the other functions thoroughly, but I do notice that you do not use the result from your readInfo called from main when you do courseGradeOutput: this function calls readInfo again. You could modify it to take the read student records and the count, so you don't have to read the file again.
You might also want to improve scanf a bit to pass a width, such as %29s for name, to avoid overflowing the buffer when the name inside the file is too long; and the same for the other strings you scan. You should then also look at the return value of fscanf and only use the things you scanned when it succeeded in scanning every argument.
This question already has answers here:
Simple C scanf does not work? [duplicate]
(5 answers)
Closed 7 years ago.
#include <stdio.h>
#include<conio.h>
#include<string.h>
#include<stdlib.h>
int p=0;
int g=1;int p1s=0;int p2s=0;
char pl,pt1,pt2;
char p1[20];
char p2[20];
char a[17][35];
int N;
int M;
void game();
void boxsize(){
printf("Enter the no. of dots you want in a horizontal row (should be less than 18) :\n");
scanf("%d",&M);
while(M>17){
printf("should be less than 18\n");
printf("Enter the no. of dots you want in a horizontal row (should be less than 18) :\n");
scanf("%d",&M);
}
printf("Enter the no. of such rows you want (should be less than 10) :\n");
scanf("%d",&N);
while(N>9){
printf("should be less than 10\n");
printf("Enter the no. of such rows you want (should be less than 10) :\n");
scanf("%d",&N);
}
}
void result(){
printf("\n FINAL SCORE >----->> \n %s = %d\n%s =%d\n",p1,p1s,p2,p2s);
if(p1s>p2s)printf("=========> %s WINS <=========\n",p1);
if(p1s<p2s)printf("=========> %s WINS <=========\n",p2);
if(p1s==p2s)printf("=========> MATCH DRAW <=========\n");
}
void getname(){
printf("Enter first player's name:\n");
gets(p1);
printf("Enter second player's name:\n");
gets(p2);
pt1=p1[0];
pt2=p2[0];
if(p1[0]==p2[0])pt2=p2[1];
}
void printer(){
int i,j;
system("cls");
printf("score ----> %s => %d %s => %d\n\n",p1,p1s,p2,p2s);
printf(" 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 \n");
for(i=0;i<(2*N-1);i++){if(i%2==0)printf("%c ",'a'+(i/2));else printf(" ");for(j=0;j<(2*M+1);j++)printf("%c ",a[i][j]);printf("\n");}
printf("\n");
}
void check(char c,char d,int i1,int i2,int *f){int i,j,k,l;
if(c==d){
i=c-'a';i=2*i;j=2*i1+1;
if(a[i-2][j]=='_' && a[i-1][j-1]=='|' && a[i-1][j+1]== '|'){*f=1;if(p%2==0){p1s++;a[i-1][j]=pt1;};if(p%2==1){p2s++;a[i-1][j]=pt2;}};
if(a[i+2][j]=='_' && a[i+1][j-1]=='|'&& a[i+1][j+1]== '|'){*f=1;p--;if(p%2==0){p1s++;a[i+1][j]=pt1;};if(p%2==1){p2s++;a[i+1][j]=pt2;}};
;
}
if(i1==i2){
i=c-'a';i=2*i;j=2*i1;
if(a[i][j-1]=='_'&&a[i+2][j-1]=='_'&&a[i+1][j-2]=='|'){*f=1;if(p%2==0){p1s++;a[i+1][j-1]=pt1;};if(p%2==1){p2s++;a[i+1][j-1]=pt2;}};
if(a[i][j+1]=='_'&&a[i+2][j+1]=='_'&&a[i+1][j+2]=='|'){*f=1;if(p%2==0){p1s++;a[i+1][j+1]=pt1;};if(p%2==1){p2s++;a[i+1][j+1]=pt2;}};
}
}
void rematch (){
char y,z;
printf("Do you want to play again (y/n)\n");
scanf("%c",&y);
if(y=='y'){
game();
}
}
void game(){ int i,j,k,i1,i2,i3,is,f=0;
p1s=0;p2s=0;
for(i=0;i<(2*N-1);i++){for(j=0;j<(2*M+1);j++){if(i%2==0){if(j%2==0)a[i][j]='.';else a[i][j]=' ';}else a[i][j]=' ';}}
printer();g=1;
char c[4];char d[4];char e[4];
while(g==1){ f=0;if(p%2==0){printf("%s's turn\n",p1);}
if(p%2==1){printf("%s's turn\n",p2);}
printf("enter first coordinate\n");
gets(c);
if(c[0]=='q'){g=0;continue;
}
printf("enter second coordinate\n");
gets(d);
if(d[0]=='q'){g=0;continue;
}
i1=10*(c[1]-'0')+(c[2]-'0');
i2=10*(d[1]-'0')+(d[2]-'0');
if(c[2]=='\0')i1=c[1]-'0'; /* correction if single digit is entered */
if(d[2]=='\0')i2=d[1]-'0';
if(c[0]>d[0]||i1>i2){strcpy(e,c);strcpy(c,d);strcpy(d,e);is=i1;i1=i2;i2=is;} /*correction if entered in reverse order*/
i3=d[0]-c[0]+i2-i1;
i3=d[0]-c[0]+i2-i1;
printf("%d %d %d\n",i1,i2,is);
if(i3!=1){printf(">> invalid move\n");continue;}
if(!((c[0]-'a')<N)&&!((d[0]-'a')<N)){printf(">>invalid move\n");continue;}
if(!(i1<(M+1))&&!(i2<(M+1))){printf(">>invalid move\n");continue;}
if(c[0]==d[0]){j=c[0]-'a';j=2*j;k=i1*2+1;if(a[j][k]=='_'){printf(">>repeated line\n");continue;}else a[j][k]='_';}
if(i2==i1){j=c[0]-'a';j=2*j+1;k=i1*2;if( a[j][k]=='|'){printf(">>repeated line\n");continue;}else a[j][k]='|';}
check(c[0],d[0],i1,i2,&f);
p++;
if (f==1)p--;
printf("%d\n",p);
printer();
}
result();
rematch();
}
int main (){
getname();
printf("Coordinate of point has to be entered as first alphabet and then followed by number. e.g. - a11,b4,e05,c10.\nenter coordinate as q at any time to exit\n");
boxsize();
game();
printf("game over\n");
return 0;
getch();
}
Whenever function game() is intiated, get(c) doesnt work for first time in loop (in line no. 90).after that it woks fine for next loop iteration. but whenever rematch is initiated game func. is initiated all over again and get(c) will not work properly again.
About the game-
this game is 'dot box'. Players join adjacent points to form a line. They take turn alternately. If a player makes a line that finishes a box completly he will score and write his name's first letter in box to mark it. He will again take another turn then. If he scores again he continues taking turn.Its an interesting game. please help me out with the problem in line 90.
The earlier scanf("%d", ...); instructions will leave a newline in the input buffer, which is captured by
scanf("%c", &y);
instead of the input you expect.
To consume any previous white-space characters in the input buffer, it needs a ' ' (space) before the %c
scanf(" %c", &y);
I am writing this code to allow user to play game "Guess the number". Once the user guesses right number it asks user if he/she wants to play again. This code works for two plays and if user inputs 'y' to play again for third time, the code shows exception. The exception details are:"Unhandled exception at 0xFEFEFEFE in Ex 5.32 Guess the number.exe: 0xC00001A5: An invalid exception handler routine has been detected (parameters: 0x00000003)."
#include "stdafx.h"
#include <math.h>
#include <stdlib.h>
int a = 1;
int main(int g){
int num, guess;
char YesOrNo;
srand(g);
num = 1 + rand() % 1000;
printf("I have a number between 1 and 1000\nCan you gess my number?\n");
do{
scanf_s("%d", &guess);
if (guess == num){
printf("Excellent! You guessed the number!\n");
break;
}
else if (guess < num)
printf("Too low. Try Again.\n");
else
printf("Too High. Try Again.\n");
} while (1);
printf("Would you like to play again(y or n) ? ");
scanf_s("%s", &YesOrNo);
if (YesOrNo == 'Y' || 'y'){
a++;
main(a);
}
else{
return 0;}
}
Have your scanf_s use the correct format specificer:
scanf_s(" %c", &YesOrNo, 1); // expecting a char
instead of:
scanf_s("%s", &YesOrNo); // expecting a string
If you were using the standard scanf() using the wrong format string can lead to undefined behavior… not positive about the same for scanf_s() but it can’t be good.
Also note that scanf_s() requires a size to be passed with character or string input (hence the 1 after the YesOrNo parameter):
Unlike scanf and wscanf, scanf_s and wscanf_s require the buffer size to be specified for all input parameters of type c, C, s, S, or string control sets that are enclosed in []. The buffer size in characters is passed as an additional parameter immediately following the pointer to the buffer or variable.
Also... you tagged this with both C and C++, note that C allows you to call main() from within itself while C++ does not. Although, frankly IMO there's never a good reason to do this, and I don't see a good reason for your program to.
I have an assignment where I have to type in the amount of names I want to compare. Then I have to see if the first name printed is repeated in the names I printed. For example if I put in 5 Reagan, Bush, Reagan, Bush, Clinton it will print out "The first name was repeated" but if I put in Davis for either of the Reagans it would say no. I've attempted a for loop and if statements but I can't seem to find the correct output. I am using Dev C++ and here is what I have so far.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main () {
char curname[30], firstname[30];
int num, i, freq = 1;
printf("How many names do you want to enter?\n");
scanf("%d", &num);
printf("What is the first name?");
scanf("%s", firstname);
printf("Enter each of their names.\n");
for (i=0; i<num; i++) {
scanf("%s", curname);
if (i==0) {
strcmp(curname, firstname) != 0;
printf("The first name in the list was repeated.\n");
}
else if (strcmp(curname, firstname) == 1)
printf("The first name in the list was not repeated.\n");
}
system("pause");
return 0;
}
You need to do only one comparison and print your message based on the result of that comparison.
if (strcmp(curname, firstname) == 0 ) {
printf("The first name in the list was repeated.\n");
}
else {
printf("The first name in the list was not repeated.\n");
}
Its always worthwhile to be very clear on what the return value of any function call is, in this case strcmp.
you have to compare names, strcmpi is more appropriate (case insensitive comparison)
if (strcmpi(curname, firstname)==0)
printf("The first name in the list was repeated.\n");
else
printf("The first name in the list was not repeated.\n");
strcmp return value may be greater 0 or less then 0, so:
strcmp(curname, firstname) == 1
change to:
strcmp(curname, firstname) != 0
others: You did not record the names into a list, so you can not find the name if or not repeated.
So I have edited my program based on the suggestions. Here is what I have now. It will only give me the correct output if the name is entered as the last value. Thank you so much!! :)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main () {
char curname[30], firstname[30];
int num, i, freq = 1;
// Read in the number of students.
printf("How many names do you want to enter?\n");
scanf("%d", &num);
printf("What is the first name?\n");
scanf("%s", firstname);
printf("Enter each of their names.\n");
for (i=0; i<num; i++)
// Read the current name.
scanf("%s", curname);
// Always update the best seen for the first name.
if (strcmp(firstname, curname)== 0) {
printf("The first name in the list was repeated.\n"); }
else
printf("The first name in the list was not repeated.\n");
system("pause");
return 0;
}