Simon Asks (Comparing Character in Two Strings) Kill an Infinite loop - loops

The rule of the game Simon Says compares the individual character of the user input character sequence with each corresponding character sequence in Simon says. (assuming both sequences have the same length). Whenever the user has the same character at the same position as "Simon Says", the user increments their score by one.
I have set up the for and while loop that compares both sequences of character individually from i=0, however, I have some issue in killing the loop.
Any comments are appreciated. Thank you.
Here's what I have:
public class SimonSays {
public static void main (String [] args) {
Scanner scnr = new Scanner(System.in);
String simonPattern;
String userPattern;
int userScore;
int i;
userScore = 0;
simonPattern = scnr.next();
userPattern = scnr.next();
for (i=0; i<=simonPattern.length();i++) {
while(userPattern.charAt(i) == simonPattern.charAt(i)){
userScore += userScore;
continue;
}
while(userPattern.charAt(i)!=simonPattern.charAt(i)){
break;
}
}
System.out.println("userScore: " + userScore);
return;
}
}

When using continue and break in loop scope its refer to the nearest loop (as you can see here) - so when you use them in the while loop they refer to it.
This what cause the infinity loop:
while(userPattern.charAt(i) == simonPattern.charAt(i)){
userScore += userScore;
continue; // this cause your infinity loop
}
The continue is execute on the while loop and the condition neer changes therefor - infinity loop.
In order to fix your issue, consider using the following code:
int userScore = 0;
for (; userScore < simonPattern.length(); userScore++) {
if (userPattern.charAt(userScore) != simonPattern.charAt(userScore))
break;
}
//Value of userScore here is the number of times the if statement return false -> which mean mumber of same chars
As the userScore is the number of char we already check in the pattern.
Hope that helps!

Related

whats the logic behind the following loop?

please anyone explain me the logic behind this piece of looping.
public static void main(String[] args) {
int number = 0;
while (true) {
number = number + 1;
if (number >= 5) {
break;
}
if (number < 5) {
continue;
}
System.out.print(number + " ");
}
System.out.print(number + " ");
}
while(true) means an infinite loop and it will only break; the loop if(number >= 5) is true.
continue; means to ignore the succeeding commands and proceed to the next loop, therefore print function at the bottom of the loop will only execute if(number<5) is false (but will never happen because of the break; command above)
when the loop exits, the number's last value will be printed.

Count all characters in a string but spaces

I have so far, in my C code where it counts everything in a user given string, however, I only want it to count letters.
Whenever I try and take out or change the spaces counter my code ends up breaking and forces me to manually stop it.
I would like to use the spaces sometime later as a method to count words but I'd rather try and get the letters done first.
What I mean by it breaks is that the code will proceed to infinitely do nothing. I found this out when instead of putting something down I had it printed and it constantly repeated what was given with no stopping.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int main(void)
{
string s = get_string("Text: ");
int n = 0;
while (s[n] != '\0')
{
if (isalpha(s[n])) //counts letters
{
n++;
}
else
{
}
}
I would like to try and keep the code similar, but if its easier, a different way.
Also I would like to keep it to where it will be able to process a string given by the user.
If you look closely at the cycle:
while (s[n] != '\0')
{
if (isalpha(s[n])) //counts letters
{
n++;
}
}
you will notice that when s[n] is not alpha, n is not incremented, so you're stuck in an infinite loop.
The counter and the iterator should be different variables:
int count = 0;
//...
while (s[n] != '\0')
{
if (isalpha(s[n]))
{
count++; //counts letters
}
n++; //increment iterator
}
You have an infinite loop as soon as a non letter character is encountered due to the else statement
int n = 0;
while (s[n] != '\0')
{
if (isalpha(s[n])) //counts letters
{
n++;
}
else
{
}
}
You have to use two variables. The first one is to store the number of letters and the second one is to traverse a character array.
In such a case it is better to use the for loop instead of the while loop.
For example
size_t n = 0;
for ( size_t i = 0; s[i] != '\0'; i++ )
{
if ( isalpha( ( unsigned char )s[i] ) ) //counts letters
{
n++;
}
}
Pay attention to that there is no sense to declare the variable n as having the signed integer type int. It is better to declare it as having the unsigned integer type size_t. It is the type that for example the string function strlen has.

How can I loop a string?

In an attempt to familiarize myself with fundamentals, I've been trying to write a simple program for choosing a password. The password is suppose to conform to the 5 listed conditions. The code is designed to loop through the password to determine if the conditions are satisfied and prompt users of any issues.
If the conditions are satisfied its coinciding variable is set to 1. Any variable left 0 is intended to prompt an invalid password. Unfortunately, it would appear that only the first character is being identified. All other conditions, aside from the first character, will fail regardless of the string.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
int main(void) {
char password[21];
int loop;
int dollar = 0;
int digit = 0;
int upperCase = 0;
int lowerCase = 0;
printf("Requirements for a valid password:\n\n");
printf("1. Contain at least one $ sign.\n");
printf("2. Contain at least one number.\n");
printf("3. Contain at least one uppercase letter.\n");
printf("4. Contain at least one lowercase letter.\n");
printf("5. Contain no more than 20 characters.\n\n");
printf("Enter password: ");
scanf(" %s", &password);
printf("\n");
for (loop = 0; loop < 21; loop++) {
if (password[loop] == '$') {
dollar = 1;
break;
}
else {
printf("Invalid password, recheck for condition 1.\n\n");
break;
}
}
for (loop = 0; loop < 21; loop++) {
if (isdigit(password[loop])) {
digit = 1;
break;
}
else {
printf("Invalid password, recheck for condition 2.\n\n");
break;
}
}
for (loop = 0; loop < 21; loop++) {
if (isupper(password[loop])) {
upperCase = 1;
break;
}
else {
printf("Invalid password, recheck for condition 3.\n\n");
break;
}
}
for (loop = 0; loop < 21; loop++) {
if (islower(password[loop])) {
lowerCase = 1;
break;
}
else {
printf("Invalid password, recheck for condition 4.\n\n");
break;
}
}
if ((dollar * digit * upperCase * lowerCase) != 0) {
printf("Password saved!");
}
system("pause");
return(0);
}
So, let's do a simple dry run here. Let's take your code for the first condition (and as remaining all same in logic, so that should do).
for (loop = 0; loop < 21; loop++) {
if (password[loop] == '$') {
dollar = 1;
break;
}
else {
printf("Invalid password, recheck for condition 1.\n\n");
break;
}
}
Let's begin with loop value equals zero. Now the following conditions exist:
The first character is a $. In this case the if condition is satisfies, and we exit out after setting the dollar flag.
The first character is not a $ (this is where we primarily go wrong). The if condition fails, as expected - and so we move to the else straightaway. Here we go on to print the error message and break out of the loop, without checking the remaining characters! Logically, we should wait to print the error till we have processed ALL the characters and not found the condition to be satisfied.
So, now we understand the problem - we are printing the error and breaking out after just checking for the first character. But, how can we fix this?
Well, for starters we should wait till we search through all the characters. So the else part must move out of the loop. Also, we know that if we do indeed have the condition satisfied, we will set the dollar variable, and exit the loop. What if we don't find the condition satisfied? Well, in that case dollar will remain zero - and that's how we detect the error!
So, we could possibly do something like:
// Loop through the characters, and as soon as we find $ we set the dollar variable and break
for (loop = 0; loop < 21; loop++) {
if (password[loop] == '$') {
dollar = 1;
break;
}
}
// If dollar is still zero, we didn't encounter the $ character
if (dollar == 0) {
printf("Invalid password, recheck for condition 1.\n\n");
}
There are a couple of other simple mistakes in the code you posted, but primarily the logical flaw is the above. Look out for the comments to understand the other possible loopholes. Cheers!

Print output just beside the user input

According to the question, The user needs to enter the no of hours the vehicle is parked and the total charge for the hours should get printed beside it.
for example:
I created this simple program
#include<stdio.h>>
#include<math.h>
float calculateCharges(float hurs);
int main()
{
float hours;//total no of hours vehicle is parked
int i;
printf("%s%10s%10s", "Car", "Hours", "Charges");
for (i = 1; i <= 3; i++)
{
printf("\n%d\t", i);
scanf("%f", &hours);
printf("\t%f\n", calculateCharges(hours));
}
getch();
return 0;
}
float calculateCharges(float hurs)
{
float charges;
hurs = ceil(hurs);
if (hurs >= 24) charges = 10;
else
{
if (hurs <= 3) charges = 2;
else
{
hurs = hurs - 3;
charges = 2 + 0.5*hurs;
}
}
return charges;
}
But now every time I enter hours the charges are getting printed below it instead of beside it. As shown in the image:
Is there is a way to consume the newline after scanf? So that charges can be printed beside the scanf?
I have modified my code this way too, but it didn't make any difference.
printf("%s%10s%10s", "Car", "Hours", "Charges");
for (i = 1; i <= 3; i++)
{
printf("\n%d\t", i);
printf("\t%f\n",(scanf("%f", &hours),calculateCharges(hours)));
}
Let me know if the original question is required. I'm using Visual studio 2017 RC.
You can use something like this:
#include <iostream>
#include <windows.h>
//This will set the position of the cursor
void gotoXY(int x, int y) {
//Initialize the coordinates
COORD coord = {x, y};
//Set the position
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
return;
}
void getCursorXY(int &x, int&y) {
CONSOLE_SCREEN_BUFFER_INFO csbi;
if(GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
x = csbi.dwCursorPosition.X;
y = csbi.dwCursorPosition.Y;
}
}
I found it here.
As already written in one of the answers this solution is not platform independent.
But i guess there are similar solutions on other platforms and you can easy set the cursor on the position you want.
Example usage in your main:
for (i = 1; i <= 3; i++)
{
printf("\n%d\t", i);
scanf("%f", &hours);
gotoXY( 20, i + 1);
printf("\t%f\n", calculateCharges(hours));
}
Workarounds for scanf can be found here.
scanf_s always generates a new line upon enter and unfortunately other user input capturing platform independent functions I know of (getc & getchar) do so too. Anyway on Windows it could be done using _getch() from conio header.
#include <conio.h>
#include <stdlib.h>
#include <stdio.h>
int getIntFromUser()
{
char readCharacters[10];
int index = 0;
for (int currentChar = _getch(); currentChar != '\r'; currentChar = _getch())
{
if (currentChar == EOF)
{
// Some error that shouldn't occour in your simple homework program
}
if (index > 9)
{
// Another possible error case where you would start to write beyond 'readCharacters' array
}
// We might as well disallow anything but digits, enter & backspace (You don't need anything else, do you?)
if ((currentChar < '0' || currentChar > '9') && currentChar != '\b')
{
continue;
}
else if (currentChar == '\b')
{
if (index > 0)
{
// Delete last character
printf("\b \b");
readCharacters[index] = '\0';
--index;
}
}
else
{
printf("%c", currentChar);
readCharacters[index] = currentChar;
++index;
}
}
if (index == 0)
{
// User pressed enter without having entered a number, let's give him a zero then
return 0;
}
readCharacters[index] = '\0';
int retVal = atoi(readCharacters);
// Worth noting that the value of converted user given string shouldn't be greater than what a signed int can hold
return retVal;
}
int main(int argc, char* argv[])
{
// Unlike scanf_s this will not generate a new line on enter
printf("getIntFromUser() sample (enter a number)\n");
int someValue = getIntFromUser();
printf(" -- This will be printed on the same line. (someValue is %d)\n\n", someValue);
// scanf_s sample
int anotherValue;
printf("scanf_s() sample (Insert a number.)\n");
scanf_s("%d", &anotherValue);
printf("This will be printed on a new line\n\n");
printf("Press any key to exit.");
_getch();
return 0;
}
EDIT
I feel like the above would become less readable if I were to add a comment over every code line. Instead I'm going to paste some blocks of code 1 by 1.
But first about the _getch function: It waits for the user to type something into the console and then returns the user given char as an int. char implicitly converts to int, so you may compare the _getch result to a character as I did many times in getIntFromUser (e.g. if (currentChar == '\b') { ... }).
You should also know about the values a char can hold and what their values are as an int (check out http://en.cppreference.com/w/cpp/language/ascii).
Going by the table the char '0' would be value 48 as an int, which is what _getch would return if the user were to type a 0.
First declare an array/string of 10 elements. Hope you know about them already. In this case the array is basically a chain of 10 elements that are all of type char, which are also referred to as string.
char readCharacters[10];
An indexer for the string is required.
int index = 0;
Below we have the usual for loop that...
1st: creates a variable of type int and assigns the result of _getch to it.
2nd: will determine if the loop shall keep executing. In this case the loop will break when currentChar is not '\r', which is an escape sequence that represents enter as a character.
3rd: will execute stuff inside once and then update currentChar with a new _getch.
for (int currentChar = _getch(); currentChar != '\r'; currentChar = _getch())
Checks if the user input (retrieved via _getch) is smaller than '0' (value 48 as an int) and greater than '9' (value 57 as an int). If either of them is true it will additionally check if the value of currentChar is not '\b' (value 8 as an int), which is the escape sequence for a backslash.
When that additional check evaluated to true as well then the keyword continue is used. Meaning that the rest of the block in the loop is not executed and instead the loop will start at the top again by getting a new user input and evaluating if the loop is to be continued by checking if obtained currentChar was enter.
if ((currentChar < '0' || currentChar > '9') && currentChar != '\b')
{
continue;
}
NOTE: You might want to read the comments on the else statement before you read these.
When the above if statement was false we get to the next if-statement (actually else if) that we see below.
As mentioned above: '\b' is backslash and if this is the user given char as well as string/array index being greater than 0 we move one character backwards in the console by "printing" '\b' and then write an empty character in order to delete what was written at that place previously. That puts us back to the position we were before so we print another backslash. At this point you might wonder why not just go back to the previous line that scanf_s causes, but that won't work. We must also not forget to replace the last string character with a null terminator and then set the index back by 1.
else if (currentChar == '\b')
{
if (index > 0)
{
// Delete last character
printf("\b \b");
readCharacters[index] = '\0';
--index;
}
}
When we hit this point we know that currentChar is something between 48 and 57 ('0' and '9').
_getch told the program what the user's input was, but we cannot see it in the console unless we print it there. So let's do that.
Also append the user's given character to the string as well as incrementing the index by 1.
else
{
printf("%c", currentChar);
readCharacters[index] = currentChar;
++index;
}
Lastly we call the atoi function that will convert our string/array to an integer.
int retVal = atoi(readCharacters);

Infinite loop on do while

I'm trying to do a simple method that ask for a number, but I'm having troubles with the condition, here is my code:
private static int rows(){
int w = 0;
Scanner sc = new Scanner(System.in);
do {
System.out.println("What is the number of rows?");
if(sc.hasNextInt()) {
w = sc.nextInt();
if (w <= 0){
System.out.println("Error: the rows can't be 0 or negative number.");
}
}
else {
System.out.println("Error: please only use digits.");
}
}
while (w<=0);
return w;
}
So, when I introduce a negative number or zero the code works fine, but if I try to introduce a letter or a invalid character like a dot or comma, the program enter in a infinite loop repeating this:
System.out.println("What is the number of rows?");
System.out.println("Error: please only use digits.");
You are not refreshing w's value. Re-enable the use to enter a new value for w. Something like:
int w = 0;
Scanner sc = new Scanner(System.in);
do {
System.out.println("What is the number of rows?");
if(sc.hasNextInt()) {
w = sc.nextInt();
if (w <= 0){
System.out.println("Error: the rows can't be 0 or negative number.");
}
}
else {
System.out.println("Error: please only use digits.");
sc.next(); // Clear default input on invalid input
continue; // Restart the loop so it gets newer value again
}
}
while (w<=0);
return w;
w only gets changed in the case of sc.hasNextInt(). If you enter a letter / invalid character, w never gets changed, and your loop cannot end.

Resources