My c program keeps crashing and I do not know why - arrays

I am writing a program like hangman in c and I am trying to run it .The problem is that it's working fine until I give it a letter to quess the word but then it crashes with -1073741819 (0xC0000005). Can someone help me solve this, I think its something really small that I cant
see . Thank you for helping me!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void Rules(void);
void maskWord (char starword[], int size);
int playRound(char starword[], char answer[]);
void updateStarWord(char starword[], char answer[], char userguess);
int occurancesInWord(char userguess, char answer[]);
int c=0;
char answer[128];
int N;
int main()
{
int ch,size;
char starword[1000];
do
{
printf("---Welcome to Hangman!---\n");
printf("1.Start Game\n2.Instructions\n3.Exit\n");
scanf("%d",&ch);
if(ch>0&& ch<4)
{
switch(ch)
{
case 1:
maskWord(starword,size);break;
case 2:
Rules();break;
}
}
else
system("cls");
}
while(ch!=3);
return 0;
}
void Rules(void)
{
do
{
do
{
printf("\nThe word to guess is represented by a row of dashes representing each letter of the word.");
printf("\nRules may permit or forbid proper nouns, such as names, places, brands, or slang.");
printf("\nIf the guessing player suggests a letter which occurs in the word, the other player writes it in all its correct positions.");
printf("\nIf the suggested letter does not occur in the word, the other player draws one element of a hanged stick figure as a tally mark.\n");
}
while(getchar()!='\n');
}
while(getchar()!='\n');
}
void maskWord (char starword[], int size)
{
printf("Enter word to guess: ");
fflush(stdout);
scanf(" %s", answer);
int N = strlen(answer);
int mask[N];
for (int i=0; i < N; ++i)
{
mask[i] = 0;
}
playRound(mask,N);
}
int playRound(char starword[], char answer[])
{
// Loop over each round of guessing
int gameover = 0;
while (! gameover)
{
// Print word with *s for unguessed letters
printf("The word is : ");
for(int j=0; j < answer; ++j)
{
if (starword[j])
{
printf("%c", answer[j]);
}
else
{
printf("*");
}
}
printf("\n");
// Get player's next guess
char guess;
printf("\nGive a letter: ");
fflush(stdout);
scanf(" %c", &guess);
updateStarWord(starword,answer,guess);
}
}
void updateStarWord(char starword[], char answer[], char userguess)
{
// Mark true all mask positions corresponding to guess
int k;
for(k=0; k < answer; ++k)
{
if ((answer[k]) ==(userguess))
{
starword[k] = 1;
}
}
}

Your for loop doesn't make sense because the condition for terminating it is k < answer. You are comparing an integer (k) to a pointer (answer). The compiler should have warned you about this, so make sure your compiler warnings are turned on and you are paying attention to them. Pointers and integers are different things, and comparing them is almost never what you want to do.
If answer is null-terminated, you could probably replace that condition with answer[k]. Or maybe updateStarWord needs to take an argument that indicates the length of answer, and then the condition would be k < answer_length.

Related

Read values into an array fails

I want to use a function to scanf up to 10 values for an array with the size 10, and also keep track of the number of values that are in the array because I'll need it later for solving some maths about the array, (max value, min value, etc.).
#include <stdio.h>
int enter(int MeasurmentData[], int nrOfmeasurments)
{
for(int i=0;i<10;++i)
{
int MeasurmentData[10];
scanf("%d",&MeasurmentData[i]);
int nrOfmeasurments = 0;
nrOfmeasurments ++;
return nrOfmeasurments;
}
int main()
{
int MeasurmentData[10];
int nrOfmeasurments;
char menuoption;
while (1)
{
printf("Measurment tool 2.0\n");
printf("v (View)\n");
printf("e (Enter)\n");
printf("c (Compute)\n");
printf("r (Reset)\n");
printf("q (Quit)\n");
printf("enter your option:\n");
scanf(" %c", &menuoption);
if (menuoption =='e') \\ enter values
{
int MeasurmentData[10];
int nrOfmeasurments;
enter(MeasurmentData, nrOfmeasurments);
}
else if(menuoption == 'v') \\\ view values
{
//printf("%d", MeasurmentData[]);
}
else if(menuoption == 'c')
{
}
if(menuoption == 'q')
{
printf("Exiting Measurment tool 2.0\n");
return 0;
}
}
}
When I run the program it should print Measurment tool 2.0, after the the user has the choice of inputting e(enter) which will scan in up to 10 values into an array, if the user clicks q(quit) while in the enter option already he will be returned to the main menu where he can do whatever.
V(view) prints out the array for the user so that he can view what elements are inside.
C(compute) uses the elements inside and the nr of elements to calculate the highest value element, lowest.
There are some errors in your code. Ill try to explain. You have over declared your variables too many times. And since you have a fixed loop you don't need to count the measurements you will always read 10 measurements.
Below are the code with some modifications. Feel free to ask anything about it.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXIMUM_MEASURMENT 10
int enter(int MeasurmentData[])
{
char input[100];
int nrMeasurement = 0;
// reseting Measurment data
for(int i=0;i<MAXIMUM_MEASURMENT;++i) MeasurmentData[i] = 0;
for(int i=0;i<MAXIMUM_MEASURMENT;++i)
{
scanf("%99s", input);
if(strcmp(input, "q") == 0) {
break;
}
MeasurmentData[i] = (int) strtol(input, (char **)NULL, 10);
nrMeasurement++;
}
return nrMeasurement;
}
void showMeasurments(int* MeasurmentData, int length) {
int i = 0;
printf(" ======== Measurment ======== \n");
for(i = 0; i < length; i++) {
printf("%d ", MeasurmentData[i]);
}
printf("\n");
}
int main()
{
int MeasurmentData[MAXIMUM_MEASURMENT];
int nrOfmeasurments;
char menuoption;
while (1)
{
printf("Measurment tool 2.0\n" "v (View)\n" "e (Enter)\n" "c (Compute)\n" "r (Reset)\n" "q (Quit)\n enter your option:\n");
scanf(" %c", &menuoption);
if (menuoption =='e') // enter values
{
enter(MeasurmentData);
}
else if(menuoption == 'v') // view values
{
// show
showMeasurments(MeasurmentData, MAXIMUM_MEASURMENT);
}
else if(menuoption == 'c')
{
}
if(menuoption == 'q')
{
printf("Exiting Measurment tool 2.0\n");
break;
}
}
return 0;
}
Edit: i have updated the code. So i have read the comments of your question and there you have explained a little better what you are trying to accomplish. So since you have the requirement to press 'q' to stop reading values. I have to read all measurments as string and convert to integer if it is not the character q.
Edit 2: Thanks to #user3629249 to point out some of the flaws from the code ill update with his suggestions.

Stack around the variable was corrupted with pointer arithmetics

With the code below, I'd always run into "Stack around the variable 'UserCode' was corrupted.
If I'm not mistaken, when I do userCode = (char*)malloc(sizeof(char)*N);, shouldn't it create an "array" with size of char*n ? I'm guessing my issue is either with my declaration of an array, or my pointer arithmetic.
Any help would be highly appreciated.
#include "stdafx.h"
#include <math.h>
int userPrompt1() {
int numOfAlphabets = 0;
printf("Please enter a number from 1 to 8 to choose how many alphabets you want\n");
scanf_s(" %d", &numOfAlphabets);
if (numOfAlphabets > 8 || numOfAlphabets < 0) {
printf("Sorry! Invalid number entered. Try again. \n");
numOfAlphabets = userPrompt1();
}
return numOfAlphabets;
}
int userPrompt2() {
int numOfLetters = 0;
printf("Please enter the number of letters you want to guess\n");
scanf_s(" %d", &numOfLetters);
if (numOfLetters < 0) {
printf("Sorry! Invalid number entered. Try again. \n");
numOfLetters = userPrompt2;
}
return numOfLetters;
}
int tryCalculator(int K, int N) {
int tries = 0;
tries = 1 + ceil(N * log2(K));
return tries;
}
void codeGenerator(char codeGuessIn[], char letters[], int size) {
for (int i = 0; i < size; i++) {
int rando = rand() % size;
codeGuessIn[i] = letters[rando];
printf(" %c", codeGuessIn[i]);
}
printf("\n");
}
void codeChecker(char codeGuessIn[], char generatedCode[], int size) {
int correctAlphabets = 0;
for (int i = 0; i < size; i++) {
if (codeGuessIn[i] == generatedCode[i]) {
correctAlphabets++;
}
}
printf(" %d in correct place \n", correctAlphabets);
}
void getUserCode(int size, char *userCode[]) {
for (int i = 0; i < size; i++) {
printf("Please enter letter #%d \n", i+1);
getchar();
scanf_s(" %c", &userCode[i]);
}
}
int main(void)
{
char letters[8] = { 'A','B','C','D','E','F','G','H' };
char *generatedCode; //array to hold generated code
char *userCode; // array to hold generated code.
int K = userPrompt1(); //how many different alphabets in code
int N = userPrompt2(); //how many letters in code
int tries = tryCalculator(K, N);
//int gameEnd = 1;
userCode = (char*)malloc(sizeof(char)*N);
generatedCode = (char*)malloc(sizeof(char)*N);
codeGenerator(generatedCode, letters, N);
getUserCode(N, &userCode);
//codeChecker(userCode, generatedCode, N);
return 0;
}
void getUserCode(int size, char *userCode[]) {
scanf_s(" %c", &userCode[i]);
Here, userCode[i] is a char * (pointer-to-char), &userCode[i] is a char ** (pointer-to-pointer-to-char), and scanf("%c") expects a char *. A good compiler would warn about that.
I think what you meant to do here is something like:
void getUserCode(int size, char *userCode) {
scanf_s(" %c", &userCode[i]);
}
int main(void) {
char *userCode = malloc(N);
getUserCode(N, userCode);
}
The printf(), getchar(), scanf() combination here reeks of the bad habits created by scanf: you're discarding the first character entered by the user because you're relying on an extra character in the input buffer.
See http://c-faq.com/stdio/scanfprobs.html and read full lines of input with fgets() instead of using scanf().
Also,
int userPrompt2() {
int numOfLetters = 0;
...
numOfLetters = userPrompt2;
}
You're assigning a function pointer to an int. (A normal compiler should warn about this.) If the idea here is to call the function again to repeat the prompt in case the user enters something silly, it's probably a better idea to use a loop instead of a recursive call anyway.

Lower to Upper Case Conversion with C

Problem Statement
I'm facing difficulty in solving a programming contest problem, which reads as follows:
You are given T name(s) in english letters. Each name will include some
of the uppercase letters from A to Z, some of the lowercase letters
from a to z and some spaces. You have to transform the name(s) from
lowercase to uppercase. Letters that are originally uppercase
will remain the same and the spaces will also remain in their
places.
Sample Input-Output
If I type this in...
5
Hasnain Heickal Jami
Mir Wasi Ahmed
Tarif Ezaz
Mahmud Ridwan
Md Mahbubul Hasan
the computer should output this...
Case 1: HASNAIN HEICKAL JAMI
Case 2: MIR WASI AHMED
Case 3: TARIF EZAZ
Case 4: MAHMUD RIDWAN
Case 5: MD MAHBUBUL HASAN
Note that exactly one space is required between the semi-colon and the initial letter of the name.
My Coding
This is what I've coded in C:
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
int main(void)
{
int T, i;
char string [100];
scanf("%d", &T);
for (i=0; i<T; i++)
{
gets(string);
printf("Case %d: ", i);
while (string[i])
{
putchar (toupper(string[i]));
i++;
}
printf("\n");
}
getch();
return 0;
}
Now, this code fails to produce the desired output. Where am I doing it wrong? Is there any matter with my syntax? Can somebody guide me? Please bear in mind that I'm a middle-schooler and just a beginner in C.
You need to cycle over each letter of the string one-by-one.
In this code below, I have done that with variable K, which goes from 0 to the length of the string.
Variable I keeps track of the number of strings.
int main(void)
{
int T, i, k;
char string [100];
scanf("%d", &T);
for ( i = 0; i < T; ++i)
{
gets (string);
for(k=0; k<strlen(string); ++k)
{
putchar (toupper(string[k]));
}
}
getch();
return 0;
}
In response your question: IDEOne Link
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(void)
{
int T, i,k;
char string [100];
scanf("%d ", &T);
for ( i = 0; i < T; ++i)
{
gets (string);
printf("[%d] : %s\n", i, string);
for(k=0; k<strlen(string); ++k)
{
putchar (toupper(string[k]));
}
putchar('\n');
}
return 0;
}
Please go through the code and implement the test cases scenarios as per your requirement.
#include <stdio.h>
#include<string.h>
int main(){
char string[100];
int i;
scanf("%s",string);
for(i=0;i<strlen(string);i++){
string[i]=string[i]-32;
}
printf("%s",string);
return 0;
}

C Outputting array from another function

I am trying to copy the array winner from my function 'enter', so that i am able to just output it on the 'previous' function. When picking the option for the previous option I have gotten nothing outputting. Its only the last function named 'previous' that is not working, but to produce the problem the majority of the code is needed.
#include <stdio.h>
#include <string.h>
char enter(char names[][20]);
void menu();
void previous(char winner[][8]);
int main()
{
char names[16][20];
int i;
printf("Please enter the names of the players:\n");
/*Making the user enter 16 times*/
for (i = 0; i < 16; i++)
{
scanf("%9s", &names[i]);
fflush(stdin);
}
/*Clearing Screen*/
system("cls");
menu(names);
return names[16][20];
}
void menu(char names[][20], char winner[][8])
{
int choice;
printf("Please select one of the following options:\n\n"
"Press 1 to enter game results\n"
"Press 2 to display the current round\n"
"Press 3 to display the players advancing to the next round\n"
"Press 4 to display the previous round\n"
"Press 5 to exit the program\n");
scanf("%d", &choice);
if(choice == 1)
{
enter(names);
}
system("cls");
if(choice == 3)
{
previous(winner);
}
}
char enter(char names[][20])
{
int result;
int score1;
int score2;
int p, c, j, l, i;
char winner[8][8];
system("cls");
for(i = 0; i < 8; i++)
{
printf("\n\n%s vs %s",names[i],names[i+8]);
score1 = 0;
score2 = 0;
for(j = 0; j < 5; j++)
{
printf("\n\nEnter game %d results, press 1 if %s won or"
" 2 if %s won :\n",(j+1), names[i], names[i+8]);
scanf("%d", &result);
if(result == 1)
{
score1++;
}
if(result == 2)
{
score2++;
}
printf("\n\n1Current score is %d-%d", score1, score2);
if(score1 == 3)
{
printf("\n\n%s adavances to the next round!",names[i]);
strncpy(winner[i], names[i], 10);
printf("\n\nPress Enter to Continue");
getch();
system("cls");
break;
}
if(score2 == 3)
{
printf("\n\n%s adavances to the next round!",names[i+8]);
strncpy(winner[i], names[i+8], 10);
printf("\n\nPress Enter to Continue");
getch();
system("cls");
break;
}
}
}
system("cls");
printf("The players advancing to the next round are:\n\n");
for(p = 0; p < 8; p++)
{
for(c = 0; c < 8; c++)
{
printf("%c",winner[p][c]);
}
printf("\n");
}
printf("\n\nPress Enter to Continue");
getch();
system("cls");
menu(names, winner);
return winner[8][8];
}
void previous(char winner[][8])
{
int i, j;
for(i = 0; i < 8; i++)
{
for(j = 0; j < 8; j++)
{
printf("%c",winner[i][j]);
}
printf("\n");
}
}
There is no data for the array winner in your program! At least not when you call it for the first time.
The signature for the menu function is:
void menu(char names[][20], char winner[][8]);
but you call it from main like this:
menu(names);
The winner parameter is missing. This shouldn't happen, but you have declared a prototype for this function, namely:
void menu();
Unfortunately, C treats the empty parens as meaning "whatever parameters you pass", not as function that takes no parameters. That means that your function call slips by. The fix is to provide the correct signature for the prototype and also to pass a suitable winner array from main.
Strangely, your enter function provides a local array winner. This array will always be a new array when you call enter. That's probably not what you want. As is, your program should have one names and one winner array. (You can pass these arrays around, but you should make sure that tese arrays are consistent. Don't create new arrays when you really want to operate on existing ones.)
You also call your menu recursively. That means the you go ever deeper into the call structure without real benefit. Dont do that; use a loop instead: do display the menu while the user hasn't chosen "quit". (There are applications for recursive functions, but this isn't one.)

Strange error while adding a feature to my little game (0xC0000005)

Hello everyone,
I decided some time ago to write my own version of Minesweepers as some practice and I did it. The game ran perfectly, but after deciding to add a "Choose difficulty" option the window freezes and I get an error message, saying that the program does not respond. Also the line 0xC0000005 appeares. I have tryed many, many things: moving code from main() to a seperate function(now all in int playGame()), allocating some more memory in the heap, even creating a seperate .c file to store some piece of the code, but nothing worked sofar. I came back to the code after a few weeks, but I still have no clue why it is happening.
Can anyone help me with this? I hope my code is not hard to read. I added some comments explaining what is what. I am still new to C.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "difLvl.c"
int displayFiled(char **field); //prints out the map of the field
int combine(char answer, int answer1); //combines user input and field numeration
int Randomizer(int **mineArray); //generates random mine map
int difficulty();
int playGame();
int main(){
int playGame();
playGame();
system("PAUSE");
return 0;
}
int Randomizer(int **mineArray){
int difficulty();
int i, j;
srand(time(NULL));
int mines;
int placeMine;
int totalMines;
//int difLvl=2;
int difLvl=difficulty();
for(i=0, totalMines=0; i<10; i++){
for(j=0, mines=0; j<10 && mines<difLvl; j++){
placeMine= rand() % 2;
mineArray[i][j] = placeMine;
if(placeMine==1){
++mines;
};
};
totalMines+=mines;
};
return totalMines;
}
int displayFiled(char **field){
int i, j;
printf(" A B C D E F G H I J\n");
printf(" --------------------\n");
for (i=0; i<10; i++){
if (i==9){
printf("%d |", i+1);
}else{
printf("%d |", i+1);
};
for (j=0; j<10; j++){
printf("%c ", field[i][j]);
if (j==9){
printf("\n");
};
};
};
printf("\n");
return 0;
}
int playGame(){
int displayFiled(char **field);
int combine(char answer, int answer1);
int Randomizer(int ** mineArray);
char Y_char; //column as character (a, b, c etc.)
int X; //row
int Y; //Y_char converted to a number
int **mineArray; //stores the map of mines
char **fieldDisplay; //prints out the map of the field
int i, j; //counters
int life=1;
int movePl=0; //no dying on the first move
int globalMines; //number of mines placed
int openedFields=0; //counts the number of fields opened
//int difLvl;
//int difficulty();
//difLvl= difficulty();
/*disabled the trhee lines above while I was trying some solutions*/
/*int difficulty() is now called from int Randomizer()*/
system("cls");
/*Allocates memory to mineArray*/
mineArray= (int*)calloc(10, sizeof(int));
for(i = 0; i < 10; i++){
mineArray[i] = calloc(10, sizeof(int));
};
/*Allocates memory to fieldDisplay*/
fieldDisplay= (int*)calloc(10, sizeof(int));
for(i = 0; i < 10; i++){
fieldDisplay[i] = calloc(10, sizeof(int));
};
/*default look of fields with ?*/
for (i=0; i<10; i++){
for (j=0; j<10; j++){
fieldDisplay[i][j]='?';
};
};
globalMines= Randomizer(mineArray);
while(life==1 && openedFields<(100-globalMines)){
/*for checking purposes only*/
/*for (i=0; i<10; i++){
for (j=0; j<10; j++){
printf("%d ", mineArray[i][j]);
if (j==9){
printf("\n");
};
};
};*/
//printf("\nDifficulty level %d\n", difLvl);
printf("Total number of mines is %d\n\n", globalMines);
printf("\tMove nr. %d\n\n", movePl+1);
displayFiled(fieldDisplay);
printf("Which field do You want to activate?\nType first the letter, space and then the number (A 1, B 10 etc.)\n");
scanf("%c %d", &Y_char, &X);
if (Y_char >= 'A' && Y_char <= 'Z'){
Y = Y_char - 'A';
}else if(Y_char >= 'a' && Y_char <= 'z'){
Y = Y_char - 'a';
};
/*checks if a field is a mine*/
/*X-1 because the player chooses from 1 to 10*/
if (mineArray[X-1][Y]==0 && fieldDisplay[X-1][Y]=='?'){
movePl++;
fieldDisplay[X-1][Y]='0';
openedFields=openedFields+1;
OPEN : if (((X-2)<10) && ((X-2)>=0)){
if (mineArray[X-2][Y]==0 && fieldDisplay[X-2][Y]=='?'){
fieldDisplay[X-2][Y]='0';
openedFields=openedFields+1;
};
};
if ((X<10) && (X>=0)){
if (mineArray[X][Y]==0 && fieldDisplay[X][Y]=='?'){
fieldDisplay[X][Y]='0';
openedFields=openedFields+1;
};
};
if (((Y+1)<10) && ((Y+1)>=0)){
if (mineArray[X-1][Y+1]==0 && fieldDisplay[X-1][Y+1]=='?'){
fieldDisplay[X-1][Y+1]='0';
openedFields=openedFields+1;
};
};
if (((Y-1)<10) && ((Y-1)>=0)){
if (mineArray[X-1][Y-1]==0 && fieldDisplay[X-1][Y-1]=='?'){
fieldDisplay[X-1][Y-1]='0';
openedFields=openedFields+1;
};
};
system("cls"); //clears console screen
}else if (mineArray[X-1][Y]==0 && fieldDisplay[X-1][Y]=='0'){
system("cls");
printf("You can't choose an already opened field!\n\n");
}else if(mineArray[X-1][Y]==1 && movePl==0){
/*only activates on the first turn if players hits mine*/
movePl++;
mineArray[X-1][Y]= 0;
fieldDisplay[X-1][Y]='0';
globalMines=globalMines-1;
goto OPEN;
system("cls");
}else{
system("cls");
printf("YOU DIED ! YOU DIED ! YOU DIED !\n\n");
printf("Moves successfully made: %d\n\n", movePl-1);
fieldDisplay[X-1][Y]='1';
displayFiled(fieldDisplay);
--life;
};
};
if(openedFields==(100-globalMines)){
printf("Congratulations! You won the game!\n\n");
displayFiled(fieldDisplay);
};
for(i = 0; i < 10; i++){
free(mineArray[i]);
};
free(mineArray);
for(i = 0; i < 10; i++){
free(fieldDisplay[i]);
};
free(fieldDisplay);
return 0;
}
The difLvl.c file:
#include <stdio.h>
#include <stdlib.h>
int difficulty(){
int difLvl;
while(1){
printf("Please choose a difficulty level:\n");
printf("Easy-1\nNormal-2\nNightmare-3\n");
printf("Your answer: ");
scanf(" %d", &difLvl);
if(difLvl>=1 && difLvl<=3){
break;
}else{
system("cls");
continue;
};
};
system("cls");
return difLvl;
}
I created it, because I thought that maybe main() had too many code in it and that maybe that was why the difficulty option wasnt working right.
EDIT
After the user is promped to enter the difficulty level, the mine map is created, but after choosing a filed, the program crashes.
SOLVED
scanf("%c %d", &Y_char, &X);
changed to
scanf(" %c %d", &Y_char, &X);
First, you don't allocate your two-dimensional fields correctly. The "outer" field must hold int *, not just int:
mineArray = calloc(10, sizeof(*mineArray));
for (i = 0; i < 10; i++) {
mineArray[i] = calloc(10, sizeof(*mineArray[i]));
}
Another potential source of the segmentation fault is that Y might end up uninitialised and therefore with a garbage value. The cause is the scanf:
scanf("%c %d", &Y_char, &X);
Most scanf formats skip white space before the conversion, but %c doesn't. It is very likely that you read the newline character as the char for %c when you expect to read a letter. Because the new-line character is white space, you can hot-fix the by placing a space before the %c? format:
scanf(" %c %d", &Y_char, &X);
(I say hot-fix, because it isn't a good solution. scanf doesn't treat new-line characters specially; they are just space. A better solution might be to read a line first with fgets and then scan that with sscanf. At least you can treat each line as frash input. (And your input really should ensure that bad input is ignored.)
Lastly, it is strange that you include a *.c file. If you want to spread ypur project over various files, which is basically a good idea, you should write a header file for each *.c, which has the file's interface. Include the header files in other *.c files; compile the *.c files into objects separately and then link them. This process is usually controlled by Makefiles or Projects.

Resources