2016-04-01 24 views
0

Merhaba Bir pgm değerinin alt değerlerinde okuma ile ilgili bir sorum var. 2d dyanmik bir dizi yaptık ve bir arabellek oluşturabilmek için yükseklik ve genişlik için 2 fazla alan ekledik ancak 1. tamsayıya genişlik + 1 okumaya çalıştığımda işe yaramıyor. Kodun neden burada durduğuna dair ipuçları var mı?Bir pgm dosyasında okuma

FILE *pfile; //pointer to file 
pfile=fopen(input_pgm,"r"); 
int columns,rows,value,line_of_numbers; 
char pformat[50]; 
    if (pfile==NULL){ 
     printf("File is empty lame-o\n"); 
        } 
    else{         //Read from file 
     fscanf(pfile,"%s",pformat);  //Things like P2,P5 
     fscanf(pfile,"%d",&columns);  //Number of columns ,M, Need & or it will store it into address 
     fscanf(pfile,"%d",&rows);  //Number of rows , N 
     fscanf(pfile,"%d",&value);  //Number of value, W 
     //Allocating 2D array to store M numbers 
     //printf("Test"); 
     int **board; 
     board = (int **)malloc((rows + 2) * sizeof(int *)); 
     for (i=0;i<rows+2;i++){ 
      board[i]=(int*)malloc((columns+2)*sizeof(int)); 
      } 
     //printf("Test2"); 
     //INITILIZING TO 0 
     board=memset(board,0,((columns+2)*(rows+2))); 
     //printf("Test"); 
     //reading in numbers on to board from 1->/rows/columns+1 
     for(i=1;i<=rows+1;i++){ 
      for(j=1;j<=columns+1;j++){ 
       //printf("Test3"); /*does not work after this*/ 
       int scanned_num; 
       fscanf(pfile,"%d",&scanned_num); 
       board[i][j]=scanned_num;} 
     } 
+0

Sorun herhangi bir yerde olabilir. Lütfen [mcve] 'nin nasıl sağlanacağını okuyun. – user694733

+1

'fopen()' 'NULL' döndürdüğünde, dosyanın açılmayacağı, ** dosya ** nın boş olamayacağı anlamına gelir. Mevcut olmayabilir veya program buna erişmeye yetkili olmayabilir veya başka bir sorun olabilir. Boş bir dosya açmak mümkündür ve eğer 'fopen()' ile başarılı bir şekilde yaparsanız, döndürdüğü gösterici * değil * 'NULL'dur. –

+0

"Çalışmıyor" tanımını yapın. –

cevap

0

Bir 2D dizi işaretçiler dinamik bir dizi (yaniboard ait göndergesi) kafa karıştırıcı gibi görünüyor. Bunlar aynı şeyde değil. Eğer şöyle board için bellek ayrılamadı Özellikle şu Not:

int için rows + 2 işaretçiler tutmak için yeterli bellek ayırdıktan
board = (int **)malloc((rows + 2) * sizeof(int *)); 

. (Ve dökme gereksizdir ve birçok kişi tarafından fakir tarzı olarak kabul unutmayın.) Nasıl o zaman bunu yapmak için anlamı var mı ...

board=memset(board,0,((columns+2)*(rows+2))); 

? board sonucunu atamanın yararsız olmasının yanı sıra, rows + 2 işaretçilerinin int işaretçilerinin boyutunun en az ((columns+2)*(rows+2)) bayt olduğunu mu düşünüyorsunuz? columns'un değeri çok küçük değilse, *board sınırlarını aşacak ve böylece tanımlanmamış davranışlar üreteceksiniz. Üstelik

, da böylece, *board içinde sadece kayıtlı olan tüm satır işaretçileri üzerine yazarak bunları dayak ve böylece satır içeriği için tahsis ettiğini tüm bellek sızdırıyor. Bu noktada çökme yerine, program kodun geri kalanı için C semantiklerine göre yürütmeye devam ederse, daha sonra okuma döngünüzdeki (board[i][j]=scanned_num) işaretçilerden çıkarmayı denediğinizde daha tanımsız davranışlar çağırırsınız. Not, board bir 2B dizisi olsa bile, belirlediğiniz bayt sayısı doğru olmaz. Her bir int için tek bir bayttan daha büyüktür.

Bu mantıklı ve büyük bir blok gibi raster tahsis etmek daha kolaydır ve en azından kullanıyorsanız C99, bunu yapmak için zaman çok kolay yolu bir değişken uzunlukta dizinin yoluyladır:

int board[rows + 2][columns + 2]; 

memset(board, 0, sizeof(board)); 

Ardından, aynı belirtecin yanında, dizinin işlevinin yürütülmesinin sona ermesine rağmen, sonradan ayrılmanıza bile gerek yoktur. Eğer işlevinden dönebilirsiniz şey gerekiyorsa

, o zaman bunun yerine bunu yapabilirsiniz: Aksi böylece durumda

int (*board)[columns + 2]; 

board = calloc(rows + 2, sizeof(*board)); 

, calloc(), tümüyle sıfıra ayrılan alan otomatik başlatmayı gerçekleştirir Bunu kendin yapmalısın.

Her iki durumda da gerekli alanı elde eder ve sıfırlarla doldurur; Verileri almak için hazırlamak için başka bir şey yapılmamalıdır. Ayrıca, ikinci durumda sadece bir calloc() çağrısı kullanıldığında, dinamik olarak ayrılmış alanla işiniz bittiğinde tam olarak bir free() aramasının kullanılması gerektiğini unutmayın.

+0

Maalesef C'ye fazla aşina değilim, ancak memsetmeye çalıştığımda, her indeks tablosunu 0'a eşitlemeye çalışıyordum, o zaman indeks 1'den satır + 1'e okumaya çalıştım. –

+0

@ What_sarcasm, okudum ve görmezden geldiğiniz 'pformat 'dizesinin önemli olduğunu da belirtmeliyim. Bu, dosyanın "sihirli numarası" dır ve dosyanın hangi formatta yazıldığını söyler. Standart PGM, bu değer için "P5" değerine sahiptir. Piksel rasterini okumak için kullandığınız kod, sihirli numarası "P2" olan "düz" PGM formatını almak için görünür. Gerçekten sadece ikincisini desteklemeyi düşünüyorsanız, doğru sihirli numaraya sahip olmayan dosyaları reddetmelisiniz. Her ikisini de desteklemeyi düşünüyorsanız, P5 davası için ek kodlara ihtiyacınız vardır. –