C语言 如何检查一个数组的元素是否已经以一种“时髦”的方式插入到那个数组中?

0yg35tkg  于 2023-01-12  发布在  其他
关注(0)|答案(2)|浏览(106)

**背景:**一个练习要求我:

  • 创建一个包含20个元素的数组;
  • 在所述数组中手动插入20个数字,范围从10到100(包括10和100);
  • 如果插入的数字(例如:x)不是10 <= x <= 100,则打印它不是有效数字并提示用户重新插入- valid - number;
  • 如果- valid - inserted数字是第一次插入(即,如果插入的数字尚未作为数组的元素出现),则打印该数字。如果该数字已经插入,则不要将其视为“待插入”的20个数字之一。
    问题:问题是,正如您在查看代码时可能注意到的,它难以置信地未经优化,如“我想不出更好的方法来解决这个问题,但我知道一定有一个整体上更好的方法来做到这一点”。* 特别是 *,我无法设计一个更好的方法来检查新插入的数字在打印之前是否已经插入(因此我的问题)。

我编写了下面的代码,我认为我已经处理了所有给定的任务。

//Esercizio 6.15  ||| Pag. 277

#include <stdio.h>
#define SIZE 20

int main()
{
    int a[SIZE];
    int nums_left = 20;

    for_cycle:
    for(int i=0; i<SIZE; ++i){
        printf("Please insert %d numbers (whole)\n", nums_left);
        scanf("%d", &a[i]);

        //Managing Errors
        if(a[i]<10 || a[i]>100){
            printf("You have inserted a non valid value!\n");
            goto for_cycle;     //heresy! I know
        }

        //Effective execution of the printing  |  The Issue
        if(a[i]!=(a[i-1])){
            if(a[i]!=a[i-2]){
            if(a[i]!=a[i-3]){
            if(a[i]!=a[i-4]){
            if(a[i]!=a[i-5]){
            if(a[i]!=a[i-6]){
            if(a[i]!=a[i-7]){
            if(a[i]!=a[i-8]){
            if(a[i]!=a[i-9]){
            if(a[i]!=a[i-10]){
            if(a[i]!=a[i-11]){
            if(a[i]!=a[i-12]){
            if(a[i]!=a[i-13]){
            if(a[i]!=a[i-14]){
            if(a[i]!=a[i-15]){
            if(a[i]!=a[i-16]){
            if(a[i]!=a[i-17]){
            if(a[i]!=a[i-18]){
            if(a[i]!=a[i-19]){
            if(a[i]!=a[i-20]){
                printf("You have inserted: %d\n", a[i]);
            }}}}}}}}}}}}}}}}}}}

            //Updates of the variable 'numbers left to insert' accordingly
            nums_left--;

        }else{i--;}         //decrements the counter
    }
    return 0;
}
68bkxrlz

68bkxrlz1#

对于已经添加有效号码的跟踪和测试,有两种主要的替代方法:

  • 搜索数组本身
  • 维护并使用外部数据结构来跟踪存储值

你已经实现了第一种形式的一个小错误和不优雅的形式。另一个答案,现在删除,演示了这个主题的一个正确和更优雅的变化,使用嵌套循环迭代已经赋值的数组元素。
然而,在速度与空间的权衡类别中,有第二种类型的解决方案。例如,您可以使用二叉搜索树来记录到目前为止添加的值,然后搜索该值而不是主数组。然而,对于如此少的总值和如此小的有效值范围,一个很好的替代方案是维护一个简单的查找表,其中的值已经被记录下来。2例如:

#include <stdio.h>

#define SIZE 20
#define MIN_VALID 10
#define MAX_VALID 100

int main(void) {
    int a[SIZE];
    _Bool seen[MAX_VALID + 1] = { 0 };

    for (int next_position = 0; next_position < SIZE; ) {
        printf("Please insert %d numbers (whole)\n", SIZE - next_position);
        scanf("%d", &a[next_position]);

        if (a[next_position] < MIN_VALID || a[next_position] > MAX_VALID){
            printf("%d is not a valid value!\n", a[next_position]);
        } else if (seen[a[next_position]]) {
            printf("You already inserted %d!\n", a[next_position]);
        } else {
            printf("You have inserted: %d\n", a[next_position]);
            seen[a[next_position]] = 1;
            next_position += 1;
        }
    }

    return 0;
}
w8biq8rn

w8biq8rn2#

假设数字范围限制为91个选项,则创建一个初始化为falsebool数组来存储用于确定是否输入了数字的标志是合理的。
在添加每个数字时,如果相应的标志为false,则接受该数字并将该标志更改为true
这个想法的一个简单实现可能如下所示:

#include <stdio.h>
#include <stdbool.h>

#define N 20
#define LOWER 10
#define UPPER 100

int main(void) {
    bool flags[UPPER - LOWER + 1] = { false };
    int input_numbers[N];

    for (size_t i = 0; i < N; i++) {
        while (true) {
            int n;

            if (scanf("%d", &n) != 1) {
                printf("Please enter a number.\n");
                while (getchar() != '\n');
                continue;
            }
       
            if (n >= LOWER && n <= UPPER && !flags[n-LOWER]) {
                input_numbers[i] = n;
                flags[n-LOWER] = true;
                break;
            }
            printf("Invalid input.\n");
        }
    }

    return 0;
}

相关问题