printf不会打印双精度类型的数组值

时间:2018-09-04 04:43:05

标签: c arrays struct printf double

#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 :(得分:3)

您有很多小东西,每个小东西足以在程序中调用未定义行为。对于初学者,您可以正确地声明常量#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 format-specifier 调用 Undefined Behavior ) format-specifier调用未定义行为)。相反,在这里,为了避免打印double值的小数位数(除非存在),请使用%g format-specifier 而不是%d(仅用于整数转换,并且可能甚至与尝试打印的字节数不同)。

使用您定义的常量(并在修复了初始化和格式说明符之后),您可以执行以下操作:

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的标准编码样式避免使用camelCaseMixedCase变量名,而推荐使用所有 lower- case ,同时保留大写名称供宏和常量使用。)

此外,在C语言中,您将希望将 pointer 传递给结构,而不是结构本身。与传递整个结构本身的副本相反,这仅允许在每个函数调用中传递价值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);

您对Q50M的初始化都是错误的。您使用:

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]

要初始化2D数组,初始化为type array[N][N] = {{0 ... N-1}, {1 ... N-1}, ... {N-1 ... N-1}};,因此,结构内数组需要3个花括号,例如Array M = {{{0...N-1}, {1...N-1}, {...}}}

同时放置该结构的初始化及其包含的2D数组将导致类似于以下内容的初始化:

    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

仔细研究,并阅读我对启用编译器警告的评论,并让我知道您是否还有其他问题。

答案 1 :(得分:1)

通知:

  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