2015-06-26 2 views
0

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

for (i = 0; i < 5; i++) 
{ 
    for (j = 0; j < 5; j++) 
    { 
     printf("Number: "); 
     scanf("%d", &d[i][j]); 
     for (k = 0; k < i; k++) 
     { 
      for (l = 0; l < j; l++) 
      { 
       while (d[i][j] == d[k][l]) 
       { 
        printf("Number: "); 
        scanf("%d", &d[i][j]); 
       } 
      } 
     } 
    } 
} 

Оказывается, что это работает неправильно. Как я могу сделать эту проверку?

+0

Что вы имеете в виду «это не работает правильно»? Какая ошибка? – rost0031

+0

Не ошибка для каждого, но она не работает для каждой позиции. – Fuga

+0

Можете ли вы привести пример? – rost0031

ответ

1

Оператор while не должен находиться во внутреннем цикле, потому что он проверяет только против этого конкретного k, l, а не против других индексов.

Сплит из теста в отдельную функцию, чтобы проверить для дублирования до I, J:

int duplicateExists(float value, int i, int j) 
{ 
     for (k = 0; k <= i; k++) 
     { 
      for (l = 0; ((k < i) && (l < 5)) || (l < j); l++) 
      { 
       if(d[k][l] == value) 
        return 1; 
      }    
     } 
     return 0; 
} 

Затем вы можете проверить, как это:

for (i = 0; i < 5; i++) 
{ 
    for (j = 0; j < 5; j++) 
    { 
     printf ("Number: "); 
     scanf  ("%d", &d[i][j]); 
     while (duplicateExists(d[i][j], i, j)) 
     { 
     printf ("Number: "); 
     scanf  ("%d", &d[i][j]); 
     }  
    } 
} 
+0

Пробовал это, но он только начал работать, когда i = 1. До этого он принимает равные значения. Любая идея почему? Спасибо! Изменить: То же самое, что уже происходило, все еще происходит, но теперь с двумя отдельными функциями. – Fuga

0

Проблема в том, что вы не проверяете каждое ранее введенное значение. Поэтому, когда i == 2 и j == 3, значения были введены в D [0] [0 до 4 ], д [1] [0 до 4 ] и D [2] [0 до 2]. Однако из-за вашего for (l = 0; l < j; l++) вы проверяете d [0] [0 - ], d [1] [0 - ] и d [2] [0 - 2].

0

Скажем, ваш код достиг внутреннего контура, с некоторым значением i и j.

продукта «проверка» необходимо сравнить d[i][j] против следующих наборов значений

set1: for k = 0 to i-1 compare with d[k][l] for l = 0 to 5 

set2: compare with d[i][l] for l = 0 to j-1 

По существу set1 о сравнении всех строк ранее прочитанных и set2 сравнивает все предыдущие элементы в текущей строке.

Ваши две вложенные петли не сравниваются с комбинацией/объединением этих двух наборов.

Примечание: это не очень хорошая идея назвать переменную l, так как она выглядит как 1 (цифра первая), и легко сделать опечатки, которые трудно увидеть, но действительно испортить смысл вашего код.

0

Вы должны попытаться изменить ваш код вроде этого. Поместите «if», чтобы вы могли видеть, совпадает ли номер, который вы написали, конечно, вы должны изменить мой код, но это основа логики.

printf("Number: "); 
      scanf  ("%d", &numb);    
      for (k = 0; k < i; k++) 
      { 
       for (l = 0; l < j; l++) 
       { 
        if (numb == d[k][j]) 
        { 
         printf("Same number, try again\n"); 
        } 
        else 
        { 
         d[i][j] = numb; 
        } 

       }    
0

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

int had; 
for (i = 0; i < 5; i++) 
{ 
    for (j = 0; j < 5; j++) 
    { 
     do 
     { 
      had = 0; 
      printf ("Number: "); 
      scanf  ("%d", &d[i][j]); 

      // check previous rows 
      for (k = 0; k < i; k++) 
      { 
       for (l = 0; l < 5; l++)  // <--- change end condition 
       { 
        if (d[i][j] == d[k][l]) 
        { 
         had = 1; 
         continue; 
        } 
       }    
      } 

      //check this row 
      for (l = 0; l < j; l++) 
      { 
       if (d[i][j] == d[i][l]) 
       { 
        had = 1; 
        continue; 
       } 
      }    
     } while (had); 
    } 
} 
0

Это принесет пользу, если вы нарушите задачу до нескольких функций, как указано другими. Это устраняет, как минимум, 4 независимые переменные итерации для индексов во вложенном цикле.После того, как у вас есть свой начальный массив, ваша основная цель - перебрать каждое значение в вашем оригинале и убедиться, что новое значение, которое вы пытаетесь добавить ко второму, не существует в первом.

Возьмем в качестве примера существующего массива и пустой второй массив (a и b ниже):

int a[][ASZ] = {{19, 1,38,51,37}, 
       {95,74,42,23,76}, 
       {17,24,14,22,25}, 
       {11,50,10,84,45}, 
       {78,44,66,46,98}}; 
int b[ASZ][ASZ] = {{0}}; 

(Примечание: любой значительно большой массив, итерации каждого значения для каждого дополнение к второй очень неэффективно. Для повышения эффективности было бы целесообразно отсортировать оригинал (даже в массиве temp), позволяющий поиск типа бисекции/брекетинга резко сократить итерации, необходимые для проверки повторяющихся значений)

Проверка на наличие d uplicates, в простейшем смысле может быть целочисленной функцией, принимающей исходный массив и предлагаемое значение в качестве аргументов (вместе с размером массива), а затем сравнивая значения, возвращая 1 или 0 для unique или non-unique. Что-то вроде следующего:

int check_uniq (int a[][ASZ], size_t n, int v) 
{ 
    size_t i, j; 

    for (i = 0; i < n; i++) 
     for (j = 0; j < ASZ; j++) 
      if (a[i][j] == v) 
       return 0; 

    return 1; 
} 

(где:ASZ просто константа для ряда размера массива)

С таким образом, чтобы проверить для уникальных значений, заполнение массива сводится к вашему основной подход:

/* fill second array with values unique to values in a[][] */ 
    for (i = 0; i < n; i++) { 
     for (j = 0; j < ASZ; j++) { 
      for (;;) { 
       tmp = rand() % 100 + 1; 
       if (check_uniq (a, n, tmp)) 
        break; 
      } 
      b[i][j] = tmp; 
     } 
    } 

(примечание: вы можете использовать любой тип внутренней петли вы предпочитаете for,. 210, или do .. while. Простая непрерывная итерация с break после того, как найденное значение найдено так же просто, как и все остальное).

И наконец, тестирование. Вместо того, чтобы неоднократно вводить предлагаемые значения во время тестирования, иногда имеет смысл создать простой способ заполнить второй массив случайными числами, чтобы обеспечить тщательную проверку. Ниже приведен краткий пример, в котором собраны все части. Надеюсь, это поможет. Дайте мне знать, если у вас есть какие-либо вопросы:

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 

#define ASZ 5 

int check_uniq (int a[][ASZ], size_t n, int v); 
void prn_array (int a[][ASZ], size_t n); 
void prn_array_1d (int a[][ASZ], size_t n); 
void quick_sort (int *a, size_t n); 

int main (void) { 

    int a[][ASZ] = {{19, 1,38,51,37}, 
        {95,74,42,23,76}, 
        {17,24,14,22,25}, 
        {11,50,10,84,45}, 
        {78,44,66,46,98}}; 
    int b[ASZ][ASZ] = {{0}}; 
    int tmp = 0; 
    size_t i, j; 
    const size_t n = sizeof a/sizeof *a; 

    srand (time (NULL)); 

    /* fill second array with values unique to values in a[][] */ 
    for (i = 0; i < n; i++) { 
     for (j = 0; j < ASZ; j++) { 
      for (;;) { 
       tmp = rand() % 100 + 1; 
       if (check_uniq (a, n, tmp)) 
        break; 
      } 
      b[i][j] = tmp; 
     } 
    } 

    printf ("\n the original array is:\n\n"); 
    prn_array (a, n); 

    printf ("\n the second array with unique values is:\n\n"); 
    prn_array (b, n); 

    printf ("\n comparison in sorted 1D array format (easier to check):\n\n"); 
    prn_array_1d (a, n); 
    printf ("\n"); 
    prn_array_1d (b, n); 
    printf ("\n\n"); 

    return 0; 
} 

int check_uniq (int a[][ASZ], size_t n, int v) 
{ 
    size_t i, j; 

    for (i = 0; i < n; i++) 
     for (j = 0; j < ASZ; j++) 
      if (a[i][j] == v) 
       return 0; 

    return 1; 
} 

void prn_array (int a[][ASZ], size_t n) 
{ 
    size_t i, j; 
    for (i = 0; i < n; i++) { 
     for (j = 0; j < ASZ; j++) 
      printf (" %3d", a[i][j]); 
     printf ("\n"); 
    } 
} 

void prn_array_1d (int a[][ASZ], size_t n) 
{ 
    size_t i, j; 
    int tmp [n * ASZ]; 

    for (i = 0; i < n; i++) 
     for (j = 0; j < ASZ; j++) 
      tmp [i * ASZ + j] = a[i][j]; 

    quick_sort (tmp, n * ASZ); 

    for (i = 0; i < n * ASZ; i++) 
     printf (" %3d", tmp[i]); 
} 

void quick_sort (int *a, size_t n) 
{ 
    int pvt, tmp; 
    size_t i, j; 

    if (n < 2) return; 

    pvt = a[n/2]; 
    for (i = 0, j = n - 1;; i++, j--) 
    { 
     while (a[i] < pvt) i++; 
     while (pvt < a[j]) j--; 

     if (i >= j) 
      break; 

     tmp = a[i]; 
     a[i] = a[j]; 
     a[j] = tmp; 
    } 

    quick_sort (a, i); 
    quick_sort (a + i, n - i); 
} 

Выходные

$ ./bin/array_2d_fill_uniq 

the original array is: 

    19 1 38 51 37 
    95 74 42 23 76 
    17 24 14 22 25 
    11 50 10 84 45 
    78 44 66 46 98 

the second array with unique values is: 

    81 16 34 69 65 
    87 88 35 67 79 
    89 43 55 18 12 
    77 83 93 9 99 
    34 94 75 2 72 

comparison in sorted 1D array format (easier to check): 

    1 10 11 14 17 19 22 23 24 25 37 38 42 44 45 46 50 51 66 74 76 78 84 95 98 
    2 9 12 16 18 34 34 35 43 55 65 67 69 72 75 77 79 81 83 87 88 89 93 94 99 
+0

Удивительный ответ, я узнал даже больше, чем мне нужно. Спасибо! – Fuga