I'm trying to learn how to program in C and have stumbled into a problem that seems like it should have been a simple fix, but it's giving me more issues then I anticipated. I'm trying to created a number guessing game, where you get three chances to guess the number, but my issue is that the Do While loop wont break when the right answer is guessed. Here is the function:
void Win_Search(int lucky[],const int MAX, int user_entry, int i)
{
int j=0;
do {
j++;
printf("Please enter a number between 0 and 100\n");
scanf("%d",&user_entry);
for(i = 0; i < MAX; i++)
{
if(user_entry==lucky[i])
{
printf("winner\n");
}
}
} while(user_entry==lucky[i]||j<3);
}
Basically it's supposed to loop through the array lucky[i] and check to see if the user_entry equals any of the 20 numbers in the array. As of right now it loops through, recognizes if a winning number has been selected from the array, but doesn't break from the array.
when I change it to
}while(user_entry!=lucky[i]||j<3);
it completely ignores the counter and just loops forever.
I don't want to use break because everything I've read about it talks about it's poor programming practice. Is there another way to break, or have simply just made a mistake thats causing this issue.
Thanks in advance.
Consider for a second where your index variable "i" comes from. What happens to it after you've found a correct user entry? Where does the control flow go?
I would suggest having a look at the "break" keyword.
You wrote while (user_entry == lucky[i]..) which translates to as long as user_entry is equal to lucky[i] keep on looping. Which is clearly not what you intend to do.
Transform your condition to } while (user_entry != lucky[i] && j < 3); and you should be fine. This will translate in plain english to as long as user_entry is different of lucky[i] AND j is inferior to 3, keep looping.
But using this, you test on the value of lucky[i] even when i means nothing ( when i is equal to max, you don't want to test it, and this goes in the domain of undefined behavior).
But if you realy dont want to use break keyword, one solution is to use a flag. Set it to 1 before you start to loop, and change it to 0 when the good answer is found. Your code will become
void Win_Search(int lucky[],const int MAX, int user_entry, int i)
{
int j=0;
char flag = 1;
do {
j++;
printf("Please enter a number between 0 and 100\n");
scanf("%d",&user_entry);
for(i = 0; i < MAX; i++)
{
if(user_entry==lucky[i])
{
printf("winner\n");
flag = 0;
}
}
} while(flag&&j<3);
}
}while(user_entry!=lucky[i]||j<3);
That is bad logic - loop while the user's entry isn't the lucky number OR j is below three? Surely you actually want this:
}while(user_entry!=lucky[i]&&j<3);
This is only the solution to your second issue of it ignoring the counter - the main problem is solved in the other answers.
The only independent condition is that the user has more guesses left. try this while"
while(j <= 3);
The less than should be obvious, but the equals belongs there because you increment your j before the loop so it will be
j = 1 => first guess
j = 2 => second guess
j = 3 => third guess
After that the user should have no more guesses
You should find this doesn't work, that is because we want to exit the loop if the user guesses correctly. To do this, you can use a int as a bool (0-false, 1-yes).
void Win_Search(int lucky[],const int MAX, int user_entry, int i)
{
int j=0;
int exitCase = 0;
do {
j++;
printf("Please enter a number between 0 and 100\n");
scanf("%d",&user_entry);
for(i = 0; i < MAX; i++)
{
if(user_entry==lucky[i])
{
exitCase = 1;
printf("winner\n");
}
}
} while(exitCase == 0 || j <= 3);
}
Related
(If you already know what the riddle is about just read the last 2 lines)
I saw a video about a riddle which is called "The 100 prisoners riddle" it essentially tells you that a bunch of prisoners (only one person at a time) get into a room, this room has boxes that are ordered correctly from 1 to a 100 but the numbers inside the boxes are random and each prisoner getting into the room is numbered from 1 to a 100 too, so each prisoner has to pick the box that has his number, each prisoner has a set of tries (50 tries) if he opened 50 boxes and he didn't find his number he loses! for example prisoner number 1 gets in the room and he has to find the box that has his number .. it might be box number 7 or 19 or 27 who knows! so it's just a game of luck .. or is it? the game has strategies and ways to mathematically solve the puzzle but that's not my problem here, I just wanna program the game in C and solve the puzzle for myself, the code has a lot of holes in it so look closely into it and find what's the problem, THANK YOU ALL :)!
#include <stdio.h>
#include <stdlib.h>
int main() {
int i, j = 0, k = 0, counter = 0;
int boxes[10];
int boxEntered;
for (i = 0; i <= 10; i++) \\ numbering the array
boxes[i] = i;
for (i = 0; i <= 10; i++) {
int temp = boxes[i];
int randomIndex = (rand() % 10); \\ shuffling the boxes to put random numbers
boxes[i] = boxes[randomIndex];
boxes[randomIndex] = temp;
}
for (i = 0; i <= 10; i++) {
printf("%d : (%d)\n", boxes[i], i); \\ print the boxes randomized and their index ordered
}
printf("You only have 5 tries!\n");
while (k != 5) {
while (j < 10) {
printf("Pick a box number between 0 and 10 (You are number %d)\n",counter);
scanf("%d",&boxEntered);
if (boxes[boxEntered] == boxes[counter]) {
printf("\nYou succeded, PROCEED TO NEXT PRISONER\n");
j++; \\ go to the next iteration
k = 0; \\ set tries back to 0
counter++;
} else
printf("Try again\nThe box you entered had number %d\n",boxes[boxEntered]);
k++;
if (k == 5) { \\ if player prisoner fails 5 times you break the loop
break;
}
}
}
if (counter == 10) { \\ if last prisoner was reached successfully then game is won
printf("You are freed!");
} else {
printf("You are going back heheheheheh!\n")
}
return 0;
}
As you can see in this picture the output doesn't make any sense at all and i have no idea what is wrong here..
From your code's logic, you should replace
boxes[boxEntered] == boxes[counter]
with
boxes[boxEntered] == counter
This is because counter here seems to represent a prisoner. Taking boxes[counter] will give you a box, which isn't what you want; you're trying to see if the box matches the current prisoner.
Another important note is the following code will go out of bounds for your array, causing undefined behaviour:
for (i = 0; i <= 10; i++) boxes[i] = i;
boxes is declared as having size 10, and therefore taking boxes[10] goes out of bounds; the maximum is boxes[9].
To fix this, you can index your arrays starting from 1. To do this in C, instead of declaring boxes[10], use boxes[11]. This will ensure you can access boxes[10].
You can then change your loops to start from 1, so something like:
for (i = 1; i <= 10; i++) boxes[i] = i;
Be sure to make this change for every array and for loop in your code.
I have an array, say 1,3,3,1,2 The output of the code must be 4(2 repetitions of 1 + 2 repetitions of 3=4). How can I do this in C? Here's my attempt.
#include <stdio.h>
int main(){
int n,i,j,temp;
scanf("%d",&n);
int arr[n];
for(i=0;i<n;i++){
scanf("%d",&arr[i]);
}
for(i=0;i<n;i++){
int min = i;
for(j=i+1;j<n;j++){
if(arr[j]<arr[min]) min=j;
}
temp= arr[min];
arr[min]=arr[i];
arr[i]=temp;
}
int count=1;
for(i=0;i<n;i++){
if(arr[i]==arr[i+1])count++;
else continue;
}
printf("%d",count);
}
What you need is to change this for loop.
int count=1;
for(i=0;i<n;i++){
if(arr[i]==arr[i+1])count++;
else continue;
}
It can look for example the following way
int count = 0;
for ( i = 0; i < n; )
{
int j = i;
while ( ++i < n && arr[i-1] == arr[i] );
if ( !( i - j < 2 ) ) count += i - j;
}
It looks like your loop has a couple of problems.
It indexes past the end of the array, which is undefined behavior
It doesn't understand when to count the first item in a group of duplicates
Regarding #1 it's nice to just start your loop at 1 instead of 0 and then check index i-1 against i.
Regarding #2 your code works but only when there's only one number that has duplicates. This is because you started the count at 1. However, when you encounter another group, that assumption breaks down. The simplest way is to just record whether you're starting a new group.
Let's put this all together:
int count = 0;
int first = 1;
for(i = 1; i < n; i++) {
if (arr[i-1] == arr[i]) {
count += first + 1;
first = 0;
} else {
first = 1;
}
}
As for the sorting step, it's using a wildly inefficient algorithm. This is fine for small datasets, but you'll have a problem if you have a very large number of inputs. It would be wise to use something like qsort instead. There are many examples out there for how to do this.
So, your runtime right now is O(N^2). With quicksort it becomes O(N.logN).
You can probably reduce runtime further with something like a hash table that simply stores how many of each value you've found, which you update as they arrive.
If your data ranges are well-defined and small enough, you might also benefit from using a large array instead of a hash table and store a single bit for each possible number representing when a number is seen. Actually for your case you'd need two of these because of the "first in the group" problem. Now, each number that arrives sets the "seen" bit. If it was already seen, set the "duplicate" bit and increment the count. If the "duplicate" bit is not set, increment the count. Now you pretty much guarantee blazing-fast O(N) runtime where testing for and counting a duplicate value is O(1).
I have an assignment where I must use a structure to put in student information. I must then order the credit hours from greatest to least. I am focused on the integer ordering loop, I just can't figure out why my program is outputting incorrectly.
#include <stdlib.h>
#include <stdio.h>
struct Student {
char name[21];
int credits;
} s[99];
int main()
{
int students;
int tempCred = 0;
char tempName[21];
printf("How many students?: ");
scanf_s("%d", &students);
for (int i = 0; i < students; i++)
{
printf("\nStudent Name?: ");
scanf_s("%s", &s[i].name, 21);
printf("\nCredits Taken?: ");
scanf_s("%d", &s[i].credits);
}
for (int i = 0; i < students; i++) {
for (int j = 0; j < students; j++) {
if (s[j].credits > tempCred) {
tempCred = s[j].credits;
s[i].credits = s[j].credits;
s[j].credits = tempCred;
}
}
printf("\n%d", s[i].credits);
}
}
For example, if I were to enter 2,6, and 8 when asked for credit hours, the program would output '8,6,8'. I am not unfamiliar with sorting, but for some reason something isn't making sense when I look at this code. Could anyone help me order the integers from greatest to least? Thanks!
NOTE: I am aware there are better ways to do this, but my professor is making us use strictly C, no C++ at all. I just need help ordering the integers.
There are various techniques used for sorting. For instance the bubble sort, quick sort, insertion sort, etc. The simplest one is the bubble sort - but it's not the most efficient one.
In your program you have an array of structs. You've done the inserting part of the structs into the array and that's fine. The problem lies in the second part - the sorting. You have a for loop that starts at the very first element (i.e. 0) and goes all the way up to the last element (i.e. students-1). And nested inside this loop is another for loop - that also has the same range???
No, that's wrong. Instead replace the first and second for loops with this:
for (int i = 0 ; i < students-1 ; i++)
{
for (int j = i+1 ; j < students ; j++)
{
...
}
}
Here, the outer for loop begins with element 0 and goes up to the element before the last. The inner for loop starts with the next element to what the outer for loop stores (i.e. j = i + 1). So if i = 0, j = 1. And this loop goes all the way up to the last element of the array of structs.
Now, inside the inner for loop specify the condition. In your case you want them sorted in descending order (highest to lowest) of the credits.
for (int i = 0 ; i < students-1 ; i++)
{
for (int j = i+1 ; j < students ; j++)
{
if(s[j].credits > s[i].credits) // then swap the credits
{
tempCred = s[j].credits ;
s[j].credits = s[i].credits ;
s[i].credits = tempCred ;
}
}
}
Note that j is one greater that i. So if i = 0, j = 1, then the if statement reads
If the credits held in the struct in element 1 of the array is greater than the credits stored in the struct in element 0 of the array, then...
If the condition is met, the credits in these 2 structs are swapped.
This an implementation of the "bubble sort". See this for more techniques and explanations.
Finally, you can display the credits:
for(int index = 0 ; index < students ; index++)
{
printf("\n%d", s[index].credits) ;
}
Like a lot of people in the comments have said, use debugger. It'll help you trace the logic of your programs.
Like #Barmar said use the qsort() function from glibc.
Not only is easier than writting your own method but it is much faster at O(N log N) on average.
Wrote this to find the prime numbers between 2 to 1000. But it stops after showing that 2 and 3 are prime numbers. I know I can find how to write a code for finding out prime numbers on the internet. But I really need to know what's going wrong here.
#include <stdio.h>
main() {
int i, j;
int ifPrime = 1;
for (i = 2; i < 1000; i++) {
for (j = 2; j < i; j++) {
if (i % j == 0) {
ifPrime = 0;
break;
}
}
if (ifPrime == 1) {
printf("%d is prime\n", i);
}
}
}
The line
int ifPrime=1;
must be inside the outer for loop. There it will be initialized for every i. This corresponds to the natural language words "to check whether a number i is prime, first assume it is. Then check if it is divisible". The code you had before said "to check whether the numbers 2 to 1000 are prime, first assume they are", and this wording was too broad.
The code should be:
int main()
{
for (int i = 2; i < 1000; i++)
{
int ifPrime = 1;
for (int j = 2; j < i; j++)
I replaced main with int main since that is required since 20 years. (You should not learn programming from such old books.)
I moved the int i and the int j into the for loops so that you cannot accidentally use these variables outside the scope where they have defined values.
To avoid this bug in the future, it's a good idea to extract the is_prime calculation into a separate function. Then you would have been forced to initialize the ifPrime in the correct place.
Another way of finding the cause of this bug is to step through the code using a debugger and ask yourself at every step: does it still make sense what the program is doing?
You are not setting ifPrime back to 1 after checking for the single number. So once you get a number that is non_prime, ifPrime is now 0 and hence if(ifPrime == 1) would never return true post that and hence you only see 2, 3 as prime
#include <stdio.h>
int main(void) {
for( int i=2;i<1000;i++)
{
int ifPrime = 1;
for(int j=2;j<i;j++)
{
if(i%j==0)
{
ifPrime=0;
break;
}
}
if(ifPrime==1)
{
printf("%d is prime\n",i);
}
}
return 0;
}
I apologize in advance for the length of the code and how tedious it may be to follow. I am trying to break a number down into individual digits and get the factorial of each one. I have successfully done that (with the help of paxdiablo) but I want to do this all the way from 99999 to 0. In order to do that I have placed all of the code in a loop starting indx at 99999 and decreasing value until it reaches 1. The reason I am trying to do this is because I need to compare the sum of the factorial of each individual digit to the number and if they are equal then I have a match. The program runs and the first run for the number 99999 works perfectly fine but the next loop SHOULD be 99998 and do the exact same thing but instead the next number is 4. I have no idea why it would do this. Any help would be appreciated.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num;
int indx;
int fact = 1;
int individualDigit[50];
int length;
for(indx = 99999; indx > 0; indx--)
{
num = indx;
for (length = 0; num > 0; length++, num /= 10)
{
individualDigit[length] = num % 10;
}
printf ("Digit count = %d, digits =", length);
for (indx = length - 1; indx >= 0; indx--)
{
printf (" %d", individualDigit[indx]);
}
for (indx = 0; indx < length; indx++)
{
while (individualDigit[indx] > 0)
{
fact = fact * individualDigit[indx];
individualDigit[indx]--;
}
printf("\n%d ", fact);
fact = 1;
}
printf("\n");
}
return 0;
}
The value in "indx" is being used by multiple for loops. The line
for (indx = 0; indx < length; indx++)
increments indx back up to 4, which is the value used by your outer loop. Just use some new variables to count the different loops
This seems like a homework question and your code quality seems to confirm that so I'm hesitant to write you actual code but I'll give you a few pointers.
As #Cody Braun said above your index variable is getting overwritten in line 23 where you calculate the factorial.
There is a much more efficient way to calculate factorials using dynamic programming
I don't know if you just didn't want to do it in the post but learning how to properly format your code will help you catch these errors quicker and keep yourself form making them. As well as make it easier for others to read your code.
Cheers