#c #do-while #break
#c #do-while #перерыв
Вопрос:
Я пишу программу, предназначенную для компьютерной игры mastermind. Когда я впервые написал это, учитель не сказал нам, что мы не можем использовать break, поэтому я это сделал. Но не разрешается использовать break. Я пытаюсь найти способ заменить разрыв, но мне трудно понять изменение логики. Вот мой рабочий исходный код:
//If number of matches is not equal to length, print the hints and check for pica's
if(matches != LENGTH) {
//First, print as many fermi hints as matches
for(int i = 0; i < matches; i ) {
printf("fermi ");
}
//Then, second loop to check for pica hints
for(int i = 0; i < LENGTH; i ) {
//We use the i index if not used before
if(!usedNum[i]) {
for(int j = 0; j < LENGTH; j ) {
//Check if the digit is the same for given indices if not used already on guess
if(!usedGuess[j] amp;amp; num[i] == guess[j]) {
//If so, we have a match but on incorrect position
usedNum[i] = true;
usedGuess[j] = true;
used ;
printf("pica ");
break;
}
}
}
}
//If no used numbers, we print "bagels"
if(used == 0) {
printf("bagels");
}
printf("n"); //line break after hints
}
//Finally, we return the num of matches
return matches;
}
И моя попытка превратить его в цикл do while.
if(matches != LENGTH) {
//First, print as many fermi hints as matches
for(int i = 0; i < matches; i ) {
printf("fermi ");
}
//Then, second loop to check for pica hints
for(int i = 0; i < LENGTH; i ) {
//We use the i index if not used before
if(!usedNum[i]) {
do {
//Check if the digit is the same for given indices if not used already on guess
int j = 0;
//If so, we have a match but on incorrect position
usedNum[i] = true;
usedGuess[j] = true;
used ;
printf("pica ");
} while (usedGuess[j] || num[i] == guess[j]);
}
}
}
//If no used numbers, we print "bagels"
if(used == 0) {
printf("bagels");
}
printf("n"); //line break after hints
}
//Finally, we return the num of matches
return matches;
}
Читаю об имплантациях. Мой исходный код может быть указан как do this until. Однако новый код, использующий цикл while, делает это, пока это утверждение верно. Итак, для исходного кода у меня были условия остановки для моего нового кода, я должен придумать условия продолжения, верно? Будет ли лучший логический цикл для использования?
Я видел, что в другом сообщении упоминаются вспомогательные функции, но мы никогда не рассматривали их в классе, поэтому я не думаю, что нам разрешено их использовать, независимо от того, я все еще не уверен, как будет происходить реализация.
Комментарии:
1. Кажется, ваш
break;
можно заменитьj = LENGTH;
. Каковы точные ограничения?2. Большинство требований к этому не имеют отношения. как будто нет глобальной переменной и только материал для этой последней лекции, так что основные вещи. но ваше предложение сработало, не знаю, почему я об этом не подумал. Большое спасибо, что вы работали над этим весь день, лол
Ответ №1:
Есть несколько способов, которые вы можете использовать вместо break;
. Поскольку ограничение использования break;
не кажется разумным, и могут быть некоторые другие ограничения, я не могу сказать, будут ли приняты все способы.
Изменение значения j
для выхода из цикла:
for(int j = 0; j < LENGTH; j ) {
if(!usedGuess[j] amp;amp; num[i] == guess[j]) {
/* snipped */
j = LENGTH;
}
}
Использование другого флага для выхода из цикла:
bool found = false;
for(int j = 0; !found amp;amp; j < LENGTH; j ) {
if(!usedGuess[j] amp;amp; num[i] == guess[j]) {
/* snipped */
found = true;
}
}
Использование goto
(возможно, некоторые люди не одобряют, но это допустимый синтаксис):
for(int j = 0; j < LENGTH; j ) {
if(!usedGuess[j] amp;amp; num[i] == guess[j]) {
/* snipped */
goto after_the_loop;
}
}
after_the_loop:;
Комментарии:
1. Спасибо, следите за тем, в чем преимущество break, если это можно сделать с помощью других методов? Или это единственный вариант из-за этой уникальной ситуации.
2.
break;
может немедленно выскочить из цикла. Первый и второй варианты здесь доступны, потому что после этого нет кода для выполнения, чтобы вызвать видимый эффект.goto
также можно немедленно выйти из цикла, но может быть сложнее понять намерение.3.
break
выражает намерение четко и лаконично. Часто это намного проще в использовании, чем опции, которые полагаются на выполнение условия завершения цикла, и оно более устойчиво к изменениям кода, чем такие методы.goto
Подход также обладает этими свойствами, хотя он может быть не таким понятным, какbreak
, иgoto
имеет незаслуженно плохую репутацию.break
здесь лучше, но иногда бывают случаи, когдаgoto
это правильный инструмент для работы.
Ответ №2:
Что-то не так с вашим циклом while, вы инициализируете j равным 0 внутри цикла.
for(int i = 0; i < LENGTH; i ) {
if (!usedNum[i]) {
int j=0, k=0;
while (j < LENGTH amp;amp; !k) {
if(!usedGuess[j] amp;amp; num[i] == guess[j]) {
usedNum[i] = true;
usedGuess[j] = true;
used ;
k ;
printf("pica ");
}
j ;
}
}
}
Я думаю, это должно сработать.
Ответ №3:
Для случая, подобного вашему, я бы уделил особое внимание объединению внутреннего условия с условием цикла:
int j;
for (j = 0; j < LENGTH amp;amp; (usedGuess[j] || num[i] != guess[j]); j ) /* empty */ ;
if (j < LENGTH) {
// we have a match, but on an incorrect position
usedNum[i] = true;
usedGuess[j] = true;
used ;
printf("pica ");
}
Цикл просто ищет индекс j
, который удовлетворяет всем требуемым условиям. Если он оставляет j
меньше, чем LENGTH
при его завершении, тогда вы знаете, что это конечное значение j
является тем, которое удовлетворяет и всем другим условиям.