C
ตัวอักษร "x" หายไปในไฟล์ โปรแกรมถูกเขียนขึ้นเพื่อค้นหา:
#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");
}
}
มันได้รวบรวมและวิ่งไปและในที่สุดก็ตะโกน:
Hurray, letter lost in the file is finally found!
เป็นเวลาหลายปีที่จดหมายได้รับการช่วยเหลือด้วยวิธีนี้จนกระทั่งคนใหม่เข้ามาและปรับรหัสให้เหมาะสม เขาคุ้นเคยกับประเภทข้อมูลและรู้ว่าการใช้ที่ไม่ได้ลงนามดีกว่าการลงชื่อสำหรับค่าที่ไม่เป็นลบนั้นจะดีกว่าเนื่องจากมีช่วงกว้างกว่าและให้การป้องกันโอเวอร์โฟลว์ ดังนั้นเขาจึงเปลี่ยน int เข้า int เขารู้ดีว่า ascii ดีพอที่จะรู้ว่าพวกเขามีค่าที่ไม่เป็นลบเสมอ ดังนั้นเขาก็เปลี่ยนถ่านที่ไม่ได้ลงชื่อเข้าถ่าน เขารวบรวมรหัสและกลับบ้านภูมิใจในงานที่ดีที่เขาทำ โปรแกรมมีลักษณะดังนี้:
#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");
}
}
เขากลับมาหายนะในวันรุ่งขึ้น ตัวอักษร "a" หายไปและถึงแม้ว่ามันควรจะอยู่ใน "desert_file" ที่มี "abc" โปรแกรมกำลังค้นหามันตลอดไปพิมพ์ออกมาเท่านั้น:
Searching file for missing letter a...
พวกเขาไล่คนออกและย้อนกลับไปสู่รุ่นก่อนหน้าโดยระลึกว่าไม่ควรเพิ่มประสิทธิภาพประเภทข้อมูลในรหัสการทำงาน
แต่บทเรียนที่พวกเขาควรเรียนรู้ที่นี่คืออะไร
ก่อนอื่นถ้าคุณดูตาราง ascii คุณจะสังเกตเห็นว่าไม่มี EOF นั่นเป็นเพราะ EOF ไม่ใช่ตัวละคร แต่เป็นค่าพิเศษที่ส่งคืนจาก fgetc () ซึ่งสามารถส่งคืนอักขระที่ขยายเป็น int หรือ -1 หมายถึงจุดสิ้นสุดของไฟล์
ตราบใดที่เราใช้ char ที่ลงชื่อแล้วทุกอย่างทำงานได้ดี - char เท่ากับ 50 จะขยายโดย fgetc () เป็น int เท่ากับ 50 เช่นกัน จากนั้นเราแปลงมันกลับเป็นถ่านและยังมี 50 เหมือนกันเกิดขึ้นกับ -1 หรือผลลัพธ์อื่น ๆ ที่มาจาก fgetc ()
แต่ดูสิ่งที่เกิดขึ้นเมื่อเราใช้ถ่านที่ไม่ได้ลงชื่อ เราเริ่มต้นด้วย char ใน fgetc () ขยายไปยัง int แล้วต้องการถ่านที่ไม่ได้ลงนาม ปัญหาเดียวคือเราไม่สามารถรักษา -1 ในถ่านที่ไม่ได้ลงนาม โปรแกรมจัดเก็บเป็น 255 ซึ่งไม่เท่ากับ EOF
ข้อแม้
หากคุณดูที่หัวข้อ 3.1.2.5 ประเภทในสำเนาของเอกสาร ANSI Cคุณจะพบว่าการลงชื่อเข้าใช้หรือไม่นั้นขึ้นอยู่กับการใช้งานเพียงอย่างเดียว ดังนั้นคนที่แต่งตัวประหลาดอาจไม่ควรถูกไล่ออกเนื่องจากเขาพบข้อผิดพลาดที่ยุ่งยากมากที่ซ่อนอยู่ในรหัส มันอาจออกมาเมื่อเปลี่ยนคอมไพเลอร์หรือย้ายไปที่สถาปัตยกรรมอื่น ฉันสงสัยว่าใครจะถูกไล่ออกหากเกิดข้อผิดพลาดในกรณีเช่นนี้;)
PS โปรแกรมถูกสร้างขึ้นรอบข้อผิดพลาดที่กล่าวถึงใน PC Assembly Language โดย Paul A. Carter