2016-07-13 4 views
-1

配列の最終的な値では、最初の要素のみがゼロになり、再びforループに移動すると(gdbを使ってチェックされます)コードの最下部にあります。私を助けてください。私は何がうまくいかないのか分からない。行列の回転..forループはポインタの値を変更します

#include<stdio.h> 
    #include<stdlib.h> 
    int main() 
    { 
     int a, b, c; 
     printf("enter the size of matrix"); 
     scanf("%d%d",&a,&b); 
     printf("enter the number of rotations"); 
     scanf("%d",&c); 
     int *arr = malloc (sizeof(int) * a * b); 

     int x = (a >= b)? a : b; 
     printf("enter the values of matrix"); 
     // scanning the values 

     for(int i = 0; i < a; i++) 
     { 
      for(int j = 0; j < b; j++) 
      { 
       scanf("%d",(arr + i * b + j)); 
      } 
      printf("\n"); 
     } 

     // main code starts 

     for(int y = 0; y < c; y++) 
     { 
      // declared a new array 

      int *arr1 = malloc (sizeof(int) * a * b); 
      for(int k = 0; k < x/2; k++) 
      { 
       for(int i = k; i < a - k; i++) 
       { 
        for(int j = k; j < b - k; j++) 
        { 
         if (i == k && j > k) 
         { 
          *(arr1 + i * b + j - 1) = *(arr + i * b + j); 

         } 

         else if (i == a - k - 1 && j < b - k - 1) 
         { 
          *(arr1 + i * b + j + 1) = *(arr + i * b + j); 

         } 

         else if (j == k && i < a - k - 1) 
         { 
          *(arr1 + i * b + j + b) = *(arr + i * b + j); 

         } 

         else if (j == b - k - 1 && i > k) 
         { 
          *(arr1 + i * b + j - b) = *(arr + i * b + j); 

         } 
        } 
       } 
       if (x % 2 != 0 && a == b) 
       *(arr1 + x/2 * b + (b/2)) = *(arr + x/2 * b + (b/2)); 
      } 

      // changing the old array to new array 


      arr = arr1; 
      // first value is getting printed correctly here 
      printf("%d\n",*(arr)); 
      printf("%p\n",&(*arr)); 
      free(arr1); 


     } 

     // printing the output 
     for(int i = 0; i < a; i++) 
     { 
      for(int j = 0; j < b; j++) 
      { 
       printf("%d ",*(arr + i * b + j)); 
      } 
      printf("\n"); 
     } 

     // first value is getting printed incorrectly here, outside the loop 
      printf("\n%d\n",*(arr)); 
      printf("%p",&(*arr)); 

    } 
+0

コードが何を達成しようとしているかについての説明は役に立ちます(「行列回転」は多くの異なることを意味します)。サンプルの入力と期待される出力との比較は非常に価値があります。コードのコメントや散文の中でアルゴリズムがどのように動作するかについての説明は、いいかもしれません。 –

+0

Jonathanによると、Cは配列割り当てをサポートしていません。しかし、それは本当に問題ではありません。あなたは配列を割り当てていません。あなたはポインタを割り当てています。それは割り当てられたメモリのアドレスだけをコピーし、そこに格納されているデータはコピーしません。 –

+0

[0] [0]が[1] [0]、a [0] [1]が[0] [0]になるように反時計回りに回転するなど@JohnBollinger –

答えて

0

Cは配列割り当てをサポートしていません。あなたは持っている:

int *arr = malloc (sizeof(int) * a * b); 
    … 
     int *arr1 = malloc (sizeof(int) * a * b); 
     … 
     arr = arr1; 
     … 
     free(arr1); 

割り当てがあなたの元の配列(メモリリーク)を失ってしまった、あなたはその後、free()を使用して新しい配列を無効を意味します。

アレイコピーには、多くのコードが必要です。通常、関数にラップされたmemmove()memcpy()などの関数呼び出しが必要です。

例えば、#include <string.h>を追加し、arr = arr1;割り当ての代わりにこれを使用する:GCCを搭載したMac OS X 10.11.5にきれいvalgrind

free(arr); 
    arr = arr1; 

このコードが実行されます。また

memmove(arr, arr1, sizeof(int) * a * b); 
    free(arr1); // No longer needed 

配列の割り当てを処理するための 'Either'オプションまたは 'Or'オプション付きの6.1.0。

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

static void dump_matrix(const char *tag, int *arr, int a, int b) 
{ 
    printf("Matrix: %s\n", tag); 
    for (int i = 0; i < a; i++) 
    { 
     for (int j = 0; j < b; j++) 
      printf(" %3d", arr[i * b + j]); 
     putchar('\n'); 
    } 
} 

int main(void) 
{ 
    int a, b, c; 
    printf("enter the size of matrix: "); 
    scanf("%d%d", &a, &b); 
    printf("enter the number of rotations: "); 
    scanf("%d", &c); 
    int *arr = malloc(sizeof(int) * a * b); 

    int x = (a >= b) ? a : b; 
    printf("enter the values of matrix: "); 
    // scanning the values 

    for (int i = 0; i < a; i++) 
    { 
     for (int j = 0; j < b; j++) 
     { 
      if (scanf("%d", (arr + i * b + j)) != 1) 
      { 
       fprintf(stderr, "failed to read value arr[%d][%d]\n", i, j); 
       return EXIT_FAILURE; 
      } 
     } 
     printf("\n"); 
    } 

    dump_matrix("Initial input", arr, a, b); 

    // main code starts 

    for (int y = 0; y < c; y++) 
    { 
     // declared a new array 
     int *arr1 = malloc(sizeof(int) * a * b); 
     for (int k = 0; k < x/2; k++) 
     { 
      for (int i = k; i < a - k; i++) 
      { 
       for (int j = k; j < b - k; j++) 
       { 
        if (i == k && j > k) 
        { 
         *(arr1 + i * b + j - 1) = *(arr + i * b + j); 
        } 
        else if (i == a - k - 1 && j < b - k - 1) 
        { 
         *(arr1 + i * b + j + 1) = *(arr + i * b + j); 
        } 
        else if (j == k && i < a - k - 1) 
        { 
         *(arr1 + i * b + j + b) = *(arr + i * b + j); 
        } 
        else if (j == b - k - 1 && i > k) 
        { 
         *(arr1 + i * b + j - b) = *(arr + i * b + j); 
        } 
       } 
      } 
      if (x % 2 != 0 && a == b) 
       *(arr1 + x/2 * b + (b/2)) = *(arr + x/2 * b + (b/2)); 
     } 

     // Changing the old array to new array 
     // Either: 
     // memmove(arr, arr1, sizeof(int) * a * b); 
     // free(arr1); 
     // Or: 
     free(arr); 
     arr = arr1; 

     dump_matrix("After rotation", arr, a, b); 
    } 

    dump_matrix("Finished", arr, a, b); 

    free(arr); 
    return 0; 
} 

dump_matrix()機能の使用に注意してください。そのような関数を書くことは、コード内の複数の場所で使用できることを意味します。 tag引数は、使用を簡略化します。 「商用グレード」バリアントもFILE *fp引数をとり、指定されたファイルストリームに書き込みます。

メイン入力ループscanf()のエラーチェックに注意してください。私はまた、他の2つのscanf()ステートメントをチェックしておく必要があります。もちろん、エラーは標準エラーで報告されます。

例の実行:出力はあなたが意図したものである

$ ./mat31 
enter the size of matrix: 3 4 
enter the number of rotations: 2 
enter the values of matrix: 1 2 3 4 10 11 12 13 99 98 97 96 



Matrix: Initial input 
    1 2 3 4 
    10 11 12 13 
    99 98 97 96 
Matrix: After rotation 
    2 3 4 13 
    1 12 11 96 
    10 99 98 97 
Matrix: After rotation 
    3 4 13 96 
    2 11 12 97 
    1 10 99 98 
Matrix: Finished 
    3 4 13 96 
    2 11 12 97 
    1 10 99 98 
$ 

かどうかは、完全に独立した議論です。これは単にメモリを乱用していないだけです。

+0

m配列自体ではなく配列のアドレスを割り当てています... arr1とarr1は2つの異なる配列とmのアドレスを格納している2つのポインタですarrはarr1と同じ配列を指しています@Jonathan Leffler –

+1

OK。あなたはそれを行うことができます - 実際には、表示されているコードは、2つのポインタと割り当てを切り替えると動作しています。 'arr'が指し示す場所を指すように変更する前に、' arr'に割り当てられていたメモリを追跡して解放しなければなりません。そうしないと、元々 'arr'に割り当てられたメモリがリークします。そして、最後に、あなたはメモリ 'arr'ポイントを解放する必要があります。プログラムを終了しようとすると実際には重要ではありませんが、このコードのように、単純に割り当てられたメモリを解放することは良いことです。 Cでは、割り当てられたすべてのメモリを追跡し、どのコードがそれを解放するかを知る必要があります。 –

+1

あなたが安全に行うことはできませんが、質問にあるコードはポインタ 'arr1'のポインタを' arr'にコピーしてから 'arr1'を解放し、再度配列を参照します。配列が解放されると、 'arr'または' arr1'という名前で解放されるかどうかにかかわらず、データへのそれ以上のアクセスは無効です - 未定義の動作 - 'arr'または' arr1'という名前でアクセスされます。 –