C
Bir dosyada "x" harfi kayboldu. Onu bulmak için bir program yazılmıştır:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
FILE* fp = fopen("desert_file", "r");
char letter;
char missing_letter = argv[1][0];
int found = 0;
printf("Searching file for missing letter %c...\n", missing_letter);
while( (letter = fgetc(fp)) != EOF ) {
if (letter == missing_letter) found = 1;
}
printf("Whole file searched.\n");
fclose(fp);
if (found) {
printf("Hurray, letter lost in the file is finally found!\n");
} else {
printf("Haven't found missing letter...\n");
}
}
Derlendi, kaçtı ve sonunda bağırdı:
Hurray, letter lost in the file is finally found!
Yıllarca mektuplar, yeni adam gelip kodu optimize edene kadar bu şekilde kurtarıldı. Veri tiplerine aşina idi ve daha geniş bir yelpazeye sahip olduğu ve taşmalara karşı bir miktar koruma sağladığı için negatif olmayan değerler için imzasız olanların imzasız kullanmanın daha iyi olduğunu biliyordu. Bu yüzden int'yi imzasız int olarak değiştirdi . Ayrıca, Ascii'yi her zaman negatif olmayan bir değere sahip olduğunu bilecek kadar iyi tanıyordu. Bu yüzden de karakterini imzasız karaktere dönüştürdü . Kodu derledi ve yaptığı iyi işle eve gurur duydu. Program şöyle görünüyordu:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
FILE* fp = fopen("desert_file", "r");
unsigned char letter;
unsigned char missing_letter = argv[1][0];
unsigned int found = 0;
printf("Searching file for missing letter %c...\n", missing_letter);
while( (letter = fgetc(fp)) != EOF ) {
if (letter == missing_letter) found = 1;
}
printf("Whole file searched.\n");
fclose(fp);
if (found) {
printf("Hurray, letter lost in the file is finally found!\n");
} else {
printf("Haven't found missing letter...\n");
}
}
Ertesi gün bir tahribata geri döndü. "A" harfi eksikti ve "abc" içeren "desert_file" içinde olması gerekiyordu bile olsa, program sonsuza dek yazdırıyordu:
Searching file for missing letter a...
Adamı kaçırdılar ve çalışma kodunda veri türlerini asla optimize etmemesi gerektiğini hatırlayarak önceki sürüme geri döndüler.
Fakat burada öğrenmeleri gereken ders nedir?
Öncelikle, ascii tablosuna bakarsanız EOF olmadığını fark edeceksiniz. Bunun nedeni, EOF bir karakter değil, fgetc () işlevinden döndürülen özel bir değerdir;
İmzalı karakterleri kullandığımız sürece her şey iyi çalışır - 50'ye eşit karakter fgetc () ile int'ye de eşitlenir. Sonra onu tekrar char'e çeviririz ve hala 50'ye sahibiz. Aynı şey -1 veya fgetc () 'den gelen diğer herhangi bir çıktı için olur.
Ama imzasız karakter kullandığımızda neler olduğuna bakın. Fgetc () içindeki bir char ile başlıyoruz, int'ye genişletiyoruz ve ardından imzasız bir karaktere sahip olmak istiyoruz. Tek sorun, imzasız karakterde -1'i koruyamamamızdır. Program artık EOF'ye eşit olmayan 255 olarak saklıyor.
Uyarı
Bölüm 3.1.2.5'e bakınız . ANSI C belgelerinin kopyasındaki türler, char'ın imzalı olup olmadığını sadece uygulamaya bağlı olup olmadığını göreceksiniz. Yani adam muhtemelen kodda gizlenen çok zor bir hata bulduğundan kovulmamalıdır. Derleyiciyi değiştirirken veya farklı mimariye geçerken ortaya çıkabilir. Böylesi bir durumda böcek ortaya çıkarsa kimin kovulacağını merak ediyorum;)
PS. Program, PC Assembly Language'de Paul A. Carter tarafından belirtilen hata etrafında inşa edildi.