printf не будет печатать значения массива двойного типа - PullRequest
0 голосов
/ 04 сентября 2018
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#define N 8

typedef struct Array {
    double element[N][N];
} Array;

void PrintArray(Array a) {
    int i;
    int j;
    for (i = 0; i < 64; i++) {
        for (j = 0; j < 64; j++) {
             printf("%d ", a.element);
        }
    } // for
} // PrintArray

int main(int argc, const char *argv[]) {
    Array M = {
        { 174, 143, 143, 143, 143, 143, 143, 156,
          192, 200, 156, 174, 174, 174, 156, 110,
          254, 198, 174, 174, 200, 174, 143, 143,
          239, 200, 156, 200, 200, 166, 143, 143,
          200, 174, 156, 167, 166, 149, 156, 156,
          128, 156, 143, 156, 174, 200, 198, 174,
          143, 105, 110, 149, 156, 156, 200, 166,
          110, 156, 143, 143, 143, 156, 174, 156 }
    };

    // need to implement PrintArray
    PrintArray(M);

    return EXIT_SUCCESS;
}

Ответы [ 2 ]

0 голосов
/ 04 сентября 2018

У вас есть много мелочей, для каждой из которых достаточно вызвать Неопределенное поведение в вашей программе. Для начала, вы должным образом объявляете константу #define N 8, но затем игнорируете константу при итерации по массиву внутри структуры для печати, например,

#define N 8
...
void PrintArray(Array a){
...
    for (i=0; i<64; i++){
        for (j=0; j<64; j++){

У вас есть только массив 8x8 с двойными числами. Когда вы затем пытаетесь выполнить итерацию 4096 раз вместо 64 раз - вы находитесь за пределами вашего массива (за исключением того, что ваш a.element фактически не имеет доступа ни к какому элементу массива - так что вы избежали неопределенного поведения из-за полной глупости хм ...)

Однако вы вызываете Неопределенное поведение с вашим спецификатором формата из %d при передаче указателя на массив значений типа double (передача неверного типа для спецификатора формата вызывает Неопределенное поведение ). Вместо этого здесь, чтобы избежать печати десятичных разрядов для значений double (если они отсутствуют), используйте спецификатор формата %g вместо %d (для integer только преобразования и, вероятно, даже не такое количество байтов, как вы пытались напечатать).

Используя определенную вами константу (и после исправления инициализации и спецификатора формата), вы можете сделать:

void print_array (Array a)
{
    int i, j;

    for (i = 0; i < N; i++) {
        for (j = 0; j < N; j++) 
            printf (" %3g ", a.element[i][j]);  /* note the use of i & j */
        putchar ('\n');
    }
}

( примечание: Хотя это и не ошибка, стандартный стиль кодирования для C позволяет избежать использования camelCase или MixedCase имен переменных в пользу всех строчных букв , в то время как резервирование заглавных букв имен для использования с макросами и константами.)

Кроме того, в C вы захотите передать указатель на структуру вместо самой структуры. Это позволяет передавать только информацию о sizeof (a_pointer) при каждом вызове функции, а не передавать копию всей структуры. Таким образом, ваша print_array функция может быть более правильно записана как:

void print_array (Array *a)
{
    int i, j;

    for (i = 0; i < N; i++) {
        for (j = 0; j < N; j++) 
            printf (" %3g ", a->element[i][j]);  /* note the use of -> */
        putchar ('\n');
    }
}

( примечание: для передачи адреса структуры в main() вы бы назвали print_array как, например, print_array (&M);)

Ваша инициализация Q50 и M неверна. Вы используете:

Array Q50 = {{18, 11, 10, 18, 26, 40, 51, 61,
    12, 12, 14, 19, 26, 58, 60, 55,
    14, 13, 18, 26, 40, 57, 69, 56,
    14, 17, 22, 29, 51, 87, 80, 62,
    18, 22, 37, 56, 68,109,103, 77,
    26, 35, 55, 64, 81,104,113, 92,
    49, 64, 78, 87,103,121,120,101,
    72, 92, 95, 98,112,100,103, 99}
};

(ваш компилятор должен выкрикивать на вас предупреждения - которые вам нужно прочитать, понять и исправить - и не принимать код, пока он не скомпилируется чисто - без предупреждения)

Базовая инициализация для struct foo - это struct foo = { .... }, где содержимое { ... } может использовать named-initializer или предоставлять значения для некоторых или всех членов вашей структуры. Здесь у вас есть один член для вашего struct или типа double [N][N].

Чтобы инициализировать двумерный массив, нужно инициализировать type array[N][N] = {{0 ... N-1}, {1 ... N-1}, ... {N-1 ... N-1}}; Таким образом, у вас есть 3 скобки, необходимые для вашего массива в структуре, например, Array M = {{{0...N-1}, {1...N-1}, {...}}}.

Помещение как инициализации структуры, так и двумерного массива, который она содержит, приведет к инициализации, аналогичной:

    Array M = {{{174, 143, 143, 143, 143, 143, 143, 156},
                {192, 200, 156, 174, 174, 174, 156, 110},
                {254, 198, 174, 174, 200, 174, 143, 143},
                {239, 200, 156, 200, 200, 166, 143, 143},
                {200, 174, 156, 167, 166, 149, 156, 156},
                {128, 156, 143, 156, 174, 200, 198, 174},
                {143, 105, 110, 149, 156, 156, 200, 166},
                {110, 156, 143, 143, 143, 156, 174, 156}}};

В целом, вы можете сделать что-то похожее на следующее:

#include <stdio.h>

#define N 8

typedef struct Array {
    double element[N][N];
} Array;


void print_array (Array a)
{
    int i, j;

    for (i = 0; i < N; i++) {
        for (j = 0; j < N; j++) 
            printf (" %3g ", a.element[i][j]);
        putchar ('\n');
    }
}


Array Q50  =  {{{18, 11, 10, 18, 26, 40, 51, 61},
                {12, 12, 14, 19, 26, 58, 60, 55},
                {14, 13, 18, 26, 40, 57, 69, 56},
                {14, 17, 22, 29, 51, 87, 80, 62},
                {18, 22, 37, 56, 68,109,103, 77},
                {26, 35, 55, 64, 81,104,113, 92},
                {49, 64, 78, 87,103,121,120,101},
                {72, 92, 95, 98,112,100,103, 99}}};

int main (void)
{
    Array M = {{{174, 143, 143, 143, 143, 143, 143, 156},
                {192, 200, 156, 174, 174, 174, 156, 110},
                {254, 198, 174, 174, 200, 174, 143, 143},
                {239, 200, 156, 200, 200, 166, 143, 143},
                {200, 174, 156, 167, 166, 149, 156, 156},
                {128, 156, 143, 156, 174, 200, 198, 174},
                {143, 105, 110, 149, 156, 156, 200, 166},
                {110, 156, 143, 143, 143, 156, 174, 156}}};

    puts ("\nprinting M\n");
    print_array (M);

    puts ("\nprinting Q50\n");
    print_array (Q50);

    return 0;
}

Пример использования / вывода

$ ./bin/structarrayq50

printing M

 174  143  143  143  143  143  143  156
 192  200  156  174  174  174  156  110
 254  198  174  174  200  174  143  143
 239  200  156  200  200  166  143  143
 200  174  156  167  166  149  156  156
 128  156  143  156  174  200  198  174
 143  105  110  149  156  156  200  166
 110  156  143  143  143  156  174  156

printing Q50

  18   11   10   18   26   40   51   61
  12   12   14   19   26   58   60   55
  14   13   18   26   40   57   69   56
  14   17   22   29   51   87   80   62
  18   22   37   56   68  109  103   77
  26   35   55   64   81  104  113   92
  49   64   78   87  103  121  120  101
  72   92   95   98  112  100  103   99

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

0 голосов
/ 04 сентября 2018

Примечание:

  1. Для печати вашего массива вы должны использовать следующие спецификаторы, а не "%d" или "%i":
    • %e (%E) формат с плавающей запятой или двойная экспонента
    • %f число с плавающей запятой или десятичное число с двойным знаком
    • %g (%G) с плавающей запятой или двойное использование %f или %e при необходимости
  2. У вас есть двумерный массив с размером 8x8, поэтому в вашем цикле используйте константу N.
  3. Также выберите элемент массива, чтобы напечатать его, используя [i][j].

Попробуйте это:

void PrintArray(Array a){
      int i;
      int j; 
        for (i=0; i<N; i++)
        {
            for (j=0; j<N; j++)
            {
                printf("%g ", a.element[i][j]);
            }
            printf("\n");
        }
}

Вывод выглядит следующим образом:

174 143 143 143 143 143 143 156
192 200 156 174 174 174 156 110
254 198 174 174 200 174 143 143
239 200 156 200 200 166 143 143
200 174 156 167 166 149 156 156
128 156 143 156 174 200 198 174
143 105 110 149 156 156 200 166
110 156 143 143 143 156 174 156

Вывод при использовании "%d" вместо "%g" для double числа имеет неопределенное поведение, поэтому может выводить 0 или действительные значения:

0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
...