Как запретить пользователю вводить одно и то же значение дважды?

#c

#c

Вопрос:

Я создаю программу на языке Си, которая предназначена для ввода чисел и хранения их в массиве, но у меня есть ограничение, что одно и то же число нельзя вводить дважды. Есть идеи, как это реализовать?

Вот мой код:

 #includelt;stdlib.hgt; #include lt;stdio.hgt;  int main(){ int n=0, num=0, i, j; int N[n];  printf("Write the amount of values that you will introducen");  do {  scanf("%d",amp;n);  if(nlt;0)  printf("Invalid number, try againn");  } while (nlt;0);  printf("Remember to use numbers between 0 and 50n");  for(i=0; ilt;n; i  ) {  do {  scanf("%d",amp;num); //If a repeated value is entered, show a message and request the number again   if(numlt;0 || numgt;50){  printf("Invalid number, try againn");  }else{  N[i]=num;  printf("- - - - -n");  }  } while (numlt;0 || numgt;50);  getchar();  getchar();  return 0;    }  }   

Комментарии:

1. Когда пользователь вводит номер, вам нужно будет выполнить поиск в массиве существующих номеров, чтобы узнать, используется ли это значение уже, и соответствующим образом обработать этот случай.

2. Ну, вы позволяете пользователю вводить значение и, если оно уже было в массиве, выводите сообщение и возвращаете запрос на ввод. Примечание: Массив длины 0 (ваш N[n], с n == 0) является нестандартным и в любом случае не позволяет присваивать значения каким-либо элементам, потому что их нет. Простой способ состоит в том, чтобы определить массив, достаточно большой, чтобы охватить все большинство случаев, и проверить максимальное количество входных данных.

3. Вместо поиска O(N^2) для каждого добавления следует отметить, что ваш диапазон ввода сильно ограничен значениями в диапазоне [0, 250]. Технически вы можете поддерживать четыре 64-разрядных целых числа и использовать побитовые операции для записи того, какое значение было добавлено.

4. Действительно… Магические числа нежелательны. Именованные константы лучше. Это также помогло бы с той частью вашей программы, которая уже отвлекается от логики, где она просит пользователя «использовать числа от 0 до 250» , но затем отклоняет все, что больше 50.

5. Если у вас небольшой (например, меньше миллиона) диапазон возможных чисел, которые может ввести пользователь, вы также можете просто создать массив bool или int, в котором вы храните флаг для каждого введенного числа… глупо, но просто.

Ответ №1:

Поскольку ваш диапазон значений очень мал, очень легко записать тот факт, что число находится в вашем списке, установив один бит.

Действительно, у вас есть 51 возможное значение в диапазоне [0, 50], поэтому вы можете представить их 64-разрядным целым числом. Стандартные целочисленные типы находятся там lt;stdint.hgt; , где вы найдете uint64_t .

 uint64_t in_list = 0; int numbers[51]; int count = 0;  for(int num; count lt;= 50 amp;amp; 1 == scanf("%d", amp;num); ) {  if (num gt;= 0 amp;amp; num lt;= 50) {  if (!(in_list amp; (1ULL lt;lt; num))) {  numbers[count  ] = num;  in_list |= (1ULL lt;lt; num);  } else {  printf("Value %d is already added.n", num);  }  } }  

Здесь все еще присутствует неприятное количество жестко закодированных значений, но их можно улучшить и даже расширить для более высоких диапазонов. Для простоты давайте предположим, что ноль всегда является минимумом. И поскольку нам понадобится массив для битов, нам даже не нужно использовать 64-разрядные значения. Просто персонажи прекрасны.

 #include lt;stdint.hgt; #include lt;stdio.hgt;  #define MAX_NUM 250  int main() {  uint8_t in_list[(MAX_NUM / 8)   1] = { };    int numbers[MAX_NUM   1];  int count = 0;    for(int num; count lt;= MAX_NUM amp;amp; 1 == scanf("%d", amp;num); )  {  if (num gt;= 0 amp;amp; num lt;= MAX_NUM) {  int char_select = num / 8;  int bit_mask = 1 lt;lt; (num % 8);  if (!(in_list[char_select] amp; bit_mask)) {  numbers[count  ] = num;  in_list[char_select] |= bit_mask;  } else {  printf("Value %d is already added.n", num);  }  } else {  printf("Enter a value between 0 and %d.n", MAX_NUM);  }  } }  

Ответ №2:

Когда пользователь вводит новый номер, используйте for цикл для просмотра всех номеров, уже содержащихся в массиве. Если вы обнаружите, что номер уже есть в массиве, то заставьте их ввести другой номер. Таким образом, ваш внутренний цикл будет выглядеть примерно так:

 while (1) {  scanf("%d",amp;num);   // Validation #1: value  if (num lt; 0 || num gt; 50) {  printf("Numero no valido, ingrese de nuevo el valorn");  continue;  }   // Validation #2: uniqueness  bool duplicate = false;  for (int k = 0; k lt; i; k  ) {  if (N[k] == num) {  printf("Number is a duplicate.n");  duplicate = true;  break;  }  }  if (duplicate) { continue; }   N[i] = num;  break;  }  

Обратите внимание, что мы используем continue , чтобы вернуться к началу текущего цикла и выпрыгнуть break из него. Нет простого способа break или continue цикла на один уровень выше текущего (если вы не разрешите использовать goto ), поэтому я должен использовать логический флаг с именем duplicate .

Кстати, вам, возможно, потребуется включить stdbool.h , чтобы использовать этот bool тип.

Ответ №3:

Как только пользователь добавит значение, переместите его в массив. Затем пользователь снова вводит значение, просматривает массив, чтобы проверить, существует ли оно уже. Если он существует, то пользователь уже вводил это значение ранее. В этом случае не позволяйте пользователю вводить одно и то же значение. Если нет, то пусть они. ПРОСТО 🙂