Array changing its first letter without reason - c

I'm making a hangman and everything works fine if you win, but if you lose it doesn't print the word it was.
I was debugging it and I found that in one of the last iterations the first character is changed to '\000' so that is why it doesn't print, but I don't understand why because there is no line where the array word is changed.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define VOCABULARY_SIZE 8
#define MAX_STRING 32
#define MAX_GUESS 6
int random_number(int a, int b)
{
return a + rand() % (b - a + 1);
}
int main()
{
//random word selection
srand((unsigned)time(NULL));
const char VOCABULARY[VOCABULARY_SIZE][MAX_STRING] = {"vehicle", "building", "shirt", "pencil", "batman", "dromedary", "peach", "hangman"};
char word[MAX_STRING];
int i;
i = random_number(0, VOCABULARY_SIZE - 1);
strcpy(word, VOCABULARY[i]);
//user word
int guesses = 0, length = strlen(word);
char letters[MAX_GUESS+1];
char input[MAX_STRING];
char temp_char;
char temp_input[MAX_STRING];
do
{
printf("\nYour entered letters are: ");
printf("%s", letters);
printf("\nYour letters found are: ");
for (int j = 0; j < length; j++)
{
if (word[j] == input[j])
{
printf("%c", word[j]);
}
else
{
printf("_");
}
}
printf("\n%d-letter word. %d out of %d failures. Enter a letter: ", length, guesses, MAX_GUESS);
scanf(" %c", &temp_char);
letters[guesses] = temp_char;
letters[guesses+1] = '\0';
for (int j = 0; j < length; j++)
{
if (word[j] == temp_char)
{
input[j] = word[j];
}
}
guesses++;
printf("\nWhat is the word to guess? ");
scanf(" %s", temp_input);
} while ((strcmp(input, word) != 0 && strcmp(temp_input, word) != 0) && guesses <= MAX_GUESS);
if (strcmp(input, word) == 0 || strcmp(temp_input, word) == 0)
{
printf("\nCongratulations, the word was %s!", word);
}
else
{
printf("\nBetter luck next time... The word was %s", word);
}
}

You're writing to letters out of bounds
char letters[MAX_GUESS+1];
int guesses = 0;
do {
//...
letters[guesses+1] = '\0'; // OOPS
//...
guesses++;
//...
} while (... && guesses <= MAX_GUESS);

Nicely written code, but errors in string management.
Initialize
First time printf("%s", letters); called, letters[] is junk. Initialize it.
// char letters[MAX_GUESS + 1];
char letters[MAX_GUESS + 1] = { 0 };
Too many guess
Off by 1, lower limit.
// ... && guesses <= MAX_GUESS);
... && guesses < MAX_GUESS);
Missing '\0'
strcmp(input, word) uses input as a string, yet it lacks a null character.
Flush
Best to insure output is seen before asking for input.
fflush(stdout); // add
scanf(" %c", &temp_char);
fflush(stdout); // add
scanf(" %s", temp_input);
Unbounded input
scanf(" %s", temp_input); is worse than gets(). Research fgets().
Perhaps more issues.

Related

How can I pass a stdin as an argument for my function?

My first program. I would like it if the user enters a word made of letters and then it uses my loop function to output mixed up even and odd characters. Currently I cannot get it to compile. Bonus points if someone can show me how to loop the users input so after it asks the size to make the array, it prompts the user that many times for an "element" or word so that the function can scramble it and output it.
#include <stdio.h>
char transform(char str[]);
int main()
{ //Declare an array and size variable
int size = 0;
char str[size];
printf("How many elements?");
scanf("%d", &size);
printf("Please type an element: ");
//Get input from user
str[0] = scanf("%s", str);
transform(str);
printf("Please type another element: ");
//Get another input from user
str[1] = scanf("%s", str);
transform(str);
//This is the loop function that I programmed
char transform(char str[]);
{
//Loop that prints even characters
for (int i = 0; str[i] != '\0'; i++)
{
if(i % 2 == 0)
{
printf("%c", str[i]);
}
} //Space between even/odd characters
printf(" ");
//Loop that prints odd characters
for (int i = 0; str[i] != '\0'; i++)
{
if(i % 2 != 0)
{
printf("%c", str[i]);
}
}
printf("\n");
return 0;
}
}
#include <stdlib.h>
#include <stdio.h>
char transform(char str[]);
int main()
{ //Declare an array and size variable
int size = 0;
printf("How many elements?");
scanf("%d", &size);
for (int i = 0; i < size; ++i)
{
printf("Please type an element: ");
char str[2048]; //declare a wide buffer to be able to store lots of chars
scanf("%s", str);
transform(str);
}
return 0;
} //end your main here, by putting closing brace
char transform(char str[]) //define transform without semicolon, and outside of main
{ //This is the loop function that I programmed
//Loop that prints even characters
for (int i = 0; str[i] != '\0'; i++)
{
if (i % 2 == 0)
printf("%c", str[i]);
} //Space between even/odd characters
printf(" ");
//Loop that prints odd characters
for (int i = 0; str[i] != '\0'; i++)
{
if (i % 2 != 0)
printf("%c", str[i]);
}
printf("\n");
return 0;
}

Problem with Hangman game letters changing order, or solution changing to just one letter

I'm trying to make a hangman game and everything looks fine until I reach the end where sometimes the game says that the solution is just one character, or if I guess a letter they start changing places to the right. I leave you here with the code and I hope that someone can help me to find my error, thank you!
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define VOCABULARY_SIZE 8
#define MAX_STRING 32
#define MAX_GUESS 6
int random_number(int a, int b)
{
return a + rand() % (b - a + 1);
}
int main()
{
//random word selsection
srand((unsigned)time(NULL));
const char VOCABULARY[VOCABULARY_SIZE][MAX_STRING] = {"vehicle", "building", "shirt", "pencil", "batman", "dromedary", "peach", "hangman"};
char word[MAX_STRING];
int i;
i = random_number(0, VOCABULARY_SIZE - 1);
strcpy(word, VOCABULARY[i]);
//user word
int guesses = 0, length = strlen(word);
char letters[MAX_GUESS];
char input[MAX_STRING];
char temp_char;
char temp_input[MAX_STRING];
do
{
printf("\nYour entered letters are: ");
printf("%s", letters);
printf("\nYour letters found are: ");
for (int j = 0; j < length; j++)
{
if (word[j] == input[j])
{
printf("%c", word[j]);
}
else
{
printf("_");
}
}
printf("\n%d-letter word. %d out of %d failures. Enter a letter: ", length, guesses, MAX_GUESS);
scanf(" %c", &temp_char);
letters[guesses] = temp_char;
letters[guesses+1] = '\0';
for (int j = 0; j < length; j++)
{
if (word[j] == temp_char)
{
input[j] = word[j];
}
}
guesses++;
printf("\nWhat is the word to guess? ");
scanf(" %s", temp_input);
} while ((strcmp(input, word) != 0 || strcmp(temp_input, word) != 0) && guesses <= MAX_GUESS);
if (strcmp(input, word) == 0 || strcmp(temp_input, word) == 0)
{
printf("\nCongratulations, the word was %s!", word);
}
else if (guesses > MAX_GUESS)
{
printf("\nBetter luck next time... The word was %s", word);
}
}
Your letters array is one entry too small to hold the terminating nul character that you apply in this line:
letters[guesses+1] = '\0';
You also have an off-by-one error since guesses starts at zero and your loop tests if it's <= MAX_GUESS.
These two errors in combination mean that your letters array is two bytes too small. Likely it spills over into your word array, leaving the last guess and the terminating nul in there when you go to print it.

Second printf is not coming up and I am unsure why

This is my code. The second printf and getchar does not pop up after hitting enter for the first scanf. I am unsure why the second printf and getchar are not working and what the fix would be.
#include <stdio.h>
int main()
{
int choice;
int i;
i = 0;
int n;
n = 1;
int p;
char message[1000];
printf("Would you like to (1) encrypt or (2) decrypt?: ");
scanf("%i\n", choice);
printf("\nType your message: ");
message[p] = getchar();
for (i = 1; (i < 1000 && message[p] != '\0');) {
message[p] = message[p] + n;
n + 1;
}
for (i = 0; (i < 1000 && message[p] != '\0');) {
message[p] = message[p] - n;
n + 1;
}
return 0;
}
Your encription method works for encription and decription. This compiles and takes in a string including spaces modifies it and prints it out.
#include <stdio.h>
int main() {
int choice;
char temp;
int i = 0;
int n = 1;
int p, b;
char message[1000];
char endmessage[1000];
printf("Would you like to (1) encrypt or (2) decrypt?: ");
scanf("%i", &choice); // change as per comment above
scanf("%c", &temp); /* temp statement to clear buffer otherwise a second character has to be typed before the next print statement is executed */
printf("Type your message: "); //prompt added for user clarity
scanf("%[^\n]", message); /* this scanf line allows for spaces in the message */
printf("\nmessage typed is: %s \n", message);
p = (sizeof( message) + 1); /* strings need to have an ending '\0'
message[p] = '\0';
if (choice == 1) {
for (i = 0; (i < 1000 && message[i] != '\0');) {
endmessage[i] = (message[i] + n);
i +=1;
}
b = (sizeof( endmessage)); // replace encripted \0 with '\0'
endmessage[b] = putchar('\0');
printf("\nYour message encripted is: %s\n\n", endmessage);
}
if (choice == 2) {
for (i = 0; (i < 1000 && message[i] != '\0');) {
endmessage[i] = message[i] - n;
i += 1;
}
b = (sizeof(endmessage) -2); // replace decripted \0 with '\0'
endmessage[b] = putchar('\0');
printf("\nYour message decripted is: %s\n\n", endmessage);
}
}

Keep characters in an array

I want to do a program that ask to the user to give one character, then enter... until he wants to stop by pressing enter and no caracters.
Then, the program will say: "you gave the caracters ...."
for example:
give the caracter 1: k + enter
give the caracter 2: l + enter
give the caracter 3: just enter ('\n')
result: You gave the caracters: kl
My code doesnet work because when i just press enter, nothing happen. Here is the code:
#include <stdio.h>
#define N 1000
int main() {
int i = 0;
int j = 0;
char str[N];
while (str[i] != '\n') {
printf("element number str[%d] : ", i);
scanf("%s", &str[i]);
i++;
}
printf("The string is: ");
while (j < i) {
printf("%s", str[j]);
j += 1;
}
return 0;
}
You can do it with c = getchar(); or c = fgetc(stdin) function:
#include <stdio.h>
#define N 1000
int
main ()
{
int i = 0;
int j = 0;
int c;
char str[N];
while (1)
{
c = fgetc(stdin); // or c = getchar();
if ( (c != EOF) && (c != 0x0A ) ) // 0x0A = 'nl' character
{
str[i] = (char) c;
printf ("element number str[%d]=%c \n", i, str[i++] );
}
else
{
str[i] = 0;
break;
}
}
printf ("The string is: %s", str);
return 0;
}
OUTPUT:
This is my string!
element number str[1]=T
element number str[2]=h
element number str[3]=i
element number str[4]=s
element number str[5]=
element number str[6]=i
element number str[7]=s
element number str[8]=
element number str[9]=m
element number str[10]=y
element number str[11]=
element number str[12]=s
element number str[13]=t
element number str[14]=r
element number str[15]=i
element number str[16]=n
element number str[17]=g
element number str[18]=!
The string is: This is my string!
Or you can use your original scanf("%s", &str1);
#include <stdio.h>
#define N 1000
int main ()
{
int i = 0;
int k = 0;
int c;
int len;
char str[N];
char str1[N];
scanf("%s", &str1);
len = strlen(str1);
for(k = 0; k < len; k++)
{
c = str1[k];
if ( (c != EOF) && c != '\n') // EOF will work for ^D on UNIX
{
str[i] = (char) c;
printf ("element number str[%d]=%c \n", i, str[i++] );
}
else
{
str[i] = 0;
break;
}
}
printf ("The string is: %s", str);
return 0;
}
OUTPUT:
12345
element number str[1]=1
element number str[2]=2
element number str[3]=3
element number str[4]=4
element number str[5]=5
The string is: 12345
As stated in this answer scanf will not return until you give it a string, i.e. it skips whitespace.
As suggested in the answer and in general, using fgets is the better option.
Edit: A way to accomplish what you want would look like this:
#include <stdio.h>
#define N 1000
int main() {
int i = 0;
int j = 0;
char str[N];
do {
printf("element number str[%d] : ", i);
fgets(&str[i], 3, stdin);
i++;
} while (str[i - 1] != '\n');
printf("The string is: ");
while (i > j) {
printf("%c", str[j]);
j++;
}
return 0;
}
In the fgets you use the number 3 because pressing enter gives both a newline character [/n] and a return carriage [/r].

Checking if all elements in array are zero

I'm having trouble determining if two words entered are anagrams.
#include <stdio.h>
#include <string.h>
int main() {
char ch;
int letter_count[26] = {0};
int i;
int sum = 0;
printf("Enter first word: ");
do
{
scanf("%c", &ch);
letter_count[ch - 'a']++;
} while (ch != '\n');
for(i = 0; i < 26; i++)
printf("%d ", letter_count[i]);
printf("\n");
printf("Enter second word: ");
do
{
scanf("%c", &ch);
letter_count[ch - 'a']--;
} while (ch != '\n');
for(i = 0; i < 26; i++)
printf("%d ", letter_count[i]);
for(i = 0; i < 26; i++)
if(letter_count[ch] != 0)
sum++;
if (sum == 0)
printf("anagrams");
else
printf("not anagrams");
}
I have to use the do while part of the code. I can enter the two words, and it prints out the elements in the array, so that "Mattress" and "Smartest" together would have all the elements be zero. However, I'm having trouble with the last part, which is to use a third loop to check whether all the elements are zero.
I figured I could declare an int before hand and have it increment whenever an element wasn't zero, and I could just have any sum greater than zero not be an anagram. However, it always prints out anagram for me.
In your third loop, using letter_count[ch] will not check the entire array. You should iterate through the array using the loop variable i. That part of the code should be:
for (i=0; i<26; i++)
if (letter_count[i] != 0)
sum++;
To handle both upper case and lower case letters, use topper() or to lower() in <ctype.h> to avoid out-of-bound access.
#include <stdio.h>
#include <string.h>
#include <ctype.h> // <---
int main() {
char ch;
int letter_count[26] = {0};
int i;
_Bool bad = 0;
printf("Enter first word: ");
do
{
scanf("%c", &ch);
if(!isalpha(ch)) // <---
{
puts("Not a letter");
continue;
}
letter_count[tolower(ch) - 'a']++; // <---
} while (ch != '\n');
for(i = 0; i < 26; i++)
printf("%d ", letter_count[i]);
printf("\n");
printf("Enter second word: ");
do
{
scanf("%c", &ch);
if(!isalpha(ch)) // <---
{
puts("Not a letter");
continue;
}
letter_count[tolower(ch) - 'a']--; // <---
} while (ch != '\n');
for(i = 0; i < 26; i++)
printf("%d ", letter_count[i]);
printf("\n"); // <---
for(i = 0; i < 26; i++)
if(letter_count[i] != 0)
{
bad = 1;
break; // <---
}
if (bad == 0)
printf("anagrams");
else
printf("not anagrams");
}
Take a look at all places marked // <---.

Resources