BG MVC Model View Controller eğitim serisi yayında...

Ana sayfa > Programlama > C Programlama > C örnek kodlar > c_ornek00006

C örnek kodlar

Bir ikili (binary) dosyada bir karakter dizisinin başlangıç sırasını bulma

Aşağıdaki program, oluşturduğu bir ikili dosyaya 0-255 arasında rastgele seçilmiş 4000 adet karakter yazar. Dosyanın başlangıcından itibaren 350.byte konumunu aktifleştirdikten sonra, aynı konuma "Aranan karakter dizisi" ifadesini yazar ve dosyayı kapatır. Sonra getStrIndexFromFile() fonksiyonu ile dosya boyutunu alır, bu boyutun bir fazlası değerde dinamik bellek tahsisi yaparak, fread() fonksiyonu ile dosyanın tamamını bir defada okur, dosyadan okunan karakter sayısını ekrana yazar. Dosyanın içeriğinde findStrInMem() fonksiyonu ile dosyaya kaydedilen karakter dizisinin başlangıç bellek adresini alır. Dizi başlangıç bellek adresi ile dosya başlangıç adresinin farkını alarak strindex değişkenine atar ve fonksiyonun geri döndürdüğü bu değeri ekrana yazar. Bu programda strstr() fonksiyonunun kullanılmamasının nedeni ikili dosyadan okunan değerler arasında '\0' karakterinin bulunma olasılığıdır.


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

long int getStrIndexFromFile(const char* file, const char* str);
void *findStrInMem(const void *bellek, size_t blen, const void *str, size_t slen);

int main(void)
{
  FILE *fp;
  int id;
  char cdizi[25];
  long int strindex=0;

  /* Bir metin dosyası oluşturma */
  fp = fopen ("deneme.bin", "wb");
  srand(time(NULL));
  /* İkili dosyaya 4000 adet rastgele karakter (0-255) yazma */
  for (id=0; id<4000; id++) fputc (rand()%255, fp);

  /* Dosya başlangıcından itibaren 300.byte konumunu aktifleştirme */
  fseek(fp, 350, SEEK_SET);
  strcpy(cdizi, "Aranan karakter dizisi");
  /* Karakter dizisini dosyaya yazma */
  fwrite(cdizi, sizeof(cdizi), 1, fp);
  /* Dosya kapatma */
  fclose(fp);

  /* Karakter dizisinin dosyadaki başlangıç adresini alma */
  strindex = getStrIndexFromFile("deneme.bin", cdizi);
  if (strindex!=-1) {
      printf("Karakter dizisinin dosyadaki başlangıç adresi: %ld", strindex);
  }
  else printf("Karakter dizisi dosyada bulunamadı!");

  return 0;
}

long int getStrIndexFromFile(const char* file, const char* str)
{
  FILE *fp;
  long int fsize=0, rsize=0;
  char *pfile, *pos;
  long int strindex=0;

  /* Dosyayı okuma için açma */
  fp=fopen(file, "rb");
  /* Dosya sonuna erişme */
  fseek(fp, 0, SEEK_END);
  /* Dosyanın aktif konum yani dosya sonu değerini alma */
  fsize=ftell(fp);
  if(fsize==-1) return -1;
  /* Dosya aktif konumunu başa alma */
  fseek(fp, 0, SEEK_SET);
  pfile = (char *) malloc((fsize) * sizeof(char));
  rsize = fread (pfile, sizeof(char), fsize, fp);

  printf("Dosyadan okunan karakter sayısı: %ld\n", rsize);

  // pos = strstr(pfile, str);pos = strstr(pfile, str);
  pos = findStrInMem(pfile, fsize, str, strlen(str));

  if(pos) {
     strindex = pos - pfile;
  }
  else strindex=-1;

  /* Dosya kapatma */
  fclose (fp);
  /* Bellek boşaltma */
  free(pfile);

  return strindex;
}

/* findStrInMem() fonksiyonu belirli uzunlukta bir bellek bölgesinde yine belirli
uzunlukta bir karakter dizisi arar. '\0' karakterini de arama işlemine dahil
ettiğinden exe dosyalar gibi ikili sistem (binary) dosyaları ile kolaylıkla
kullanılabilir.
Fonksiyon aranan karakter dizisinin başlangıç adresini, dizi bulunamazsa
NULL bir değer geri döndürür. */

void *findStrInMem(const void *bellek, size_t blen, const void *str, size_t slen)
{
  int str_first;
  const void *p = bellek;
  size_t plen = blen;

  if (!slen) return NULL;

  str_first = *(unsigned char *)str;

  while (plen >= slen && (p = memchr(p, str_first, plen - slen + 1))) {
     if (!memcmp(p, str, slen)) return (void *)p;
     p++;
     plen = blen - (p - bellek);
  }

  return NULL;
}

Yukarıdaki örnekte, program aşağıdaki satırları ekrana yazar:

Dosyadan okunan karakter sayısı: 4000
Karakter dizisinin dosyadaki başlangıç adresi: 350