ฉันรู้สึกทึ่ง ดังนั้นเวลาที่จะเปิดแว่นตาสอบสวนและเนื่องจากฉันไม่สามารถเข้าถึงธงรวบรวมหรือรวบรวมฉันต้องได้รับการประดิษฐ์ นอกจากนี้เนื่องจากไม่มีอะไรเกี่ยวกับรหัสนี้ทำให้รู้สึกว่าไม่ใช่คำถามที่คิดไม่ดีทุกข้อสันนิษฐาน
gets
แรกให้ตรวจสอบชนิดที่แท้จริงของ ฉันมีเล่ห์เหลี่ยมเล็กน้อยสำหรับสิ่งนั้น:
template <class> struct Name;
int main() {
Name<decltype(gets)> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
และดูเหมือน ... ปกติ:
/tmp/613814454/Main.cpp:16:19: warning: 'gets' is deprecated [-Wdeprecated-declarations]
Name<decltype(gets)> n;
^
/usr/include/stdio.h:638:37: note: 'gets' has been explicitly marked deprecated here
extern char *gets (char *__s) __wur __attribute_deprecated__;
^
/usr/include/x86_64-linux-gnu/sys/cdefs.h:254:51: note: expanded from macro '__attribute_deprecated__'
# define __attribute_deprecated__ __attribute__ ((__deprecated__))
^
/tmp/613814454/Main.cpp:16:26: error: implicit instantiation of undefined template 'Name<char *(char *)>'
Name<decltype(gets)> n;
^
/tmp/613814454/Main.cpp:12:25: note: template is declared here
template <class> struct Name;
^
1 warning and 1 error generated.
gets
char *(char *)
ถูกทำเครื่องหมายเป็นที่เลิกใช้และมีลายเซ็น แต่แล้วจะFirstFactorial(gets(stdin));
รวบรวมอย่างไร
ลองทำอย่างอื่น:
int main() {
Name<decltype(gets(stdin))> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
ซึ่งทำให้เรา:
/tmp/286775780/Main.cpp:15:21: error: implicit instantiation of undefined template 'Name<int>'
Name<decltype(8)> n;
^
ในที่สุดเราก็ได้สิ่ง: decltype(8)
. ดังนั้นทั้งหมดgets(stdin)
จึงถูกแทนที่ด้วยข้อความด้วยอินพุต ( 8
)
และสิ่งต่าง ๆ ก็แปลกไป ข้อผิดพลาดของคอมไพเลอร์ยังคง:
/tmp/596773533/Main.cpp:18:26: error: no matching function for call to 'gets'
cout << FirstFactorial(gets(stdin));
^~~~
/usr/include/stdio.h:638:14: note: candidate function not viable: no known conversion from 'struct _IO_FILE *' to 'char *' for 1st argument
extern char *gets (char *__s) __wur __attribute_deprecated__;
ดังนั้นตอนนี้เราได้รับข้อผิดพลาดที่คาดไว้สำหรับ cout << FirstFactorial(gets(stdin));
ฉันตรวจสอบมาโครและ#undef gets
ดูเหมือนว่าจะไม่ทำอะไรเลยดูเหมือนว่าไม่ใช่มาโคร
แต่
std::integral_constant<int, gets(stdin)> n;
มันรวบรวม
แต่
std::integral_constant<int, gets(stdin)> n; // OK
std::integral_constant<int, gets(stdin)> n2; // ERROR wtf??
ไม่ได้มีข้อผิดพลาดที่คาดไว้ในn2
บรรทัด
และอีกครั้งการปรับเปลี่ยนเกือบทั้งหมดเพื่อให้main
เส้นcout << FirstFactorial(gets(stdin));
พ่นควันออกมาจากข้อผิดพลาดที่คาดไว้
ยิ่งไปกว่านั้นstdin
ดูเหมือนว่าจะว่างเปล่า
ดังนั้นฉันสามารถสรุปและคาดเดาได้ว่าพวกเขามีโปรแกรมเล็ก ๆ ที่แยกวิเคราะห์แหล่งที่มาและพยายาม (ไม่ดี) เพื่อแทนที่gets(stdin)
ด้วยค่าอินพุตกรณีทดสอบก่อนที่จะป้อนลงในคอมไพเลอร์ หากใครมีทฤษฎีที่ดีกว่าหรือรู้จริงว่าพวกเขากำลังทำอะไรอยู่โปรดแบ่งปัน!
เห็นได้ชัดว่าเป็นการปฏิบัติที่เลวร้ายมาก ในขณะที่ทำการวิจัยนี้ฉันพบว่ามีคำถามอย่างน้อยที่นี่ ( ตัวอย่าง ) เกี่ยวกับเรื่องนี้และเนื่องจากผู้คนไม่มีความคิดว่ามีเว็บไซต์อยู่ที่นั่นผู้ตอบคำตอบของพวกเขาคือ "อย่าgets
ใช้ ... แทน" ซึ่งแน่นอน คำแนะนำที่ดี แต่สร้างความสับสนให้ OP มากขึ้นเนื่องจากความพยายามในการอ่านที่ถูกต้องจาก stdin จะล้มเหลวในเว็บไซต์นี้
TLDR
gets(stdin)
C ++ ไม่ถูกต้อง เป็นกลไกที่ไซต์นี้ใช้ (เพราะสาเหตุใดที่ฉันไม่สามารถเข้าใจได้) หากคุณต้องการส่งต่อบนเว็บไซต์ (ฉันไม่รับรองหรือไม่รับรอง) คุณต้องใช้โครงสร้างนี้มิฉะนั้นจะไม่สมเหตุสมผล แต่ระวังว่ามันเปราะ เกือบการแก้ไขใด ๆ ที่main
จะพ่นข้อผิดพลาดออกไป นอกไซต์นี้ใช้วิธีการอ่านอินพุตปกติ
stdin
ในห้องสมุดมาตรฐานเป็นFILE*
และตัวชี้ไปยังแปลงชนิดใด ๆ ที่ซึ่งเป็นประเภทของการโต้แย้งของchar*
gets()
อย่างไรก็ตามคุณไม่ควรเขียนโค้ดชนิดนั้นนอกการประกวด C ที่สับสน หากคอมไพเลอร์ของคุณยอมรับได้ให้เพิ่มการตั้งค่าสถานะการเตือนเพิ่มเติมและหากคุณกำลังพยายามแก้ไขรหัสฐานที่มีโครงสร้างนั้นให้เปลี่ยนคำเตือนเป็นข้อผิดพลาด