2024 ผู้เขียน: Howard Calhoun | [email protected]. แก้ไขล่าสุด: 2024-01-17 19:10
ในบทความนี้ ฟังก์ชัน scanf() ถือว่าอยู่ในรูปแบบทั่วไปโดยไม่มีการอ้างอิงถึงมาตรฐานใดโดยเฉพาะ ดังนั้นข้อมูลจากมาตรฐาน C99, C11, C++11, C++14 จึงรวมอยู่ที่นี่ บางที ในบางมาตรฐาน ฟังก์ชันอาจทำงานได้แตกต่างจากเนื้อหาที่นำเสนอในบทความ
ฟังก์ชั่นสแกน C - คำอธิบาย
scanf() เป็นฟังก์ชันที่อยู่ในไฟล์ส่วนหัว stdio.h(C) และ cstdio(C++) หรือที่เรียกว่าอินพุตโปรแกรมที่จัดรูปแบบ scanf อ่านอักขระจากสตรีมอินพุตมาตรฐาน (stdin) และแปลงตามรูปแบบ จากนั้นเขียนลงในตัวแปรที่ระบุ รูปแบบ - หมายความว่าข้อมูลจะถูกแปลงเป็นรูปแบบบางอย่างเมื่อได้รับ ดังนั้น ฟังก์ชัน scanf C จึงถูกอธิบายไว้:
scanf("%format", &variable1[, &variable2, […]), ที่ตัวแปรจะถูกส่งผ่านเป็นที่อยู่ เหตุผลในการส่งผ่านตัวแปรไปยังฟังก์ชันนี้ชัดเจน เนื่องจากการทำงานจะส่งกลับค่าที่ระบุว่ามีข้อผิดพลาด ดังนั้นวิธีเดียวที่จะเปลี่ยนค่าของตัวแปรคือส่งผ่านที่อยู่ ด้วยวิธีนี้ ฟังก์ชันจึงสามารถประมวลผลข้อมูลได้ทุกประเภท
โปรแกรมเมอร์บางคนอ้างถึงฟังก์ชั่นเช่น scanf() หรือ printf() เป็นขั้นตอนเนื่องจากการเปรียบเทียบกับภาษาอื่น
Scanf อนุญาตให้ป้อนภาษาพื้นฐานทั้งหมด: char, int, float, string ฯลฯ ในกรณีของตัวแปรประเภทสตริงไม่จำเป็นต้องระบุเครื่องหมายที่อยู่ - "&" เนื่องจากตัวแปรประเภทสตริงเป็นอาร์เรย์และชื่อคือที่อยู่ขององค์ประกอบแรกของอาร์เรย์ในหน่วยความจำของคอมพิวเตอร์.
รูปแบบการป้อนข้อมูลหรือสตริงควบคุม
เริ่มด้วยการดูตัวอย่างฟังก์ชัน scanf C จากคำอธิบาย
รวม int main() { int x; ในขณะที่ (scanf("%d", &x)==1) printf("%d\n", x); กลับ 0; //ข้อกำหนดสำหรับระบบ linux }
รูปแบบการป้อนข้อมูลประกอบด้วยสี่พารามิเตอร์ต่อไปนี้: ประเภท %[ความกว้าง][ตัวดัดแปลง] ในกรณีนี้ เครื่องหมาย "%" และประเภทเป็นพารามิเตอร์บังคับ นั่นคือ รูปแบบขั้นต่ำจะมีลักษณะดังนี้: “%s”, “%d” เป็นต้น
โดยทั่วไป อักขระที่ประกอบเป็นสตริงรูปแบบจะแบ่งออกเป็น:
- ตัวระบุรูปแบบ - อะไรก็ได้ที่ขึ้นต้นด้วย %;
- แยกหรือเว้นวรรคอักขระ - คือช่องว่าง, แท็บ(t), ขึ้นบรรทัดใหม่ (n);
- ตัวละครอื่นที่ไม่ใช่ช่องว่าง
ฟังก์ชั่นอาจไม่ปลอดภัย
ใช้ scanf_s() แทน scanf().
(ข้อความจาก Visual Studio)
ประเภทหรือตัวระบุรูปแบบหรืออักขระการแปลงหรืออักขระควบคุม
การประกาศ scanf C ต้องมีตัวระบุรูปแบบเป็นอย่างน้อย ซึ่งระบุไว้ที่ส่วนท้ายของนิพจน์ที่ขึ้นต้นด้วย "%" มันบอกโปรแกรมถึงประเภทของข้อมูลที่คาดหวังเมื่อป้อน โดยปกติแล้วจะมาจากแป้นพิมพ์ รายการตัวระบุรูปแบบทั้งหมดในตารางด้านล่าง
ประเภท | ความหมาย | |
1 | %c | โปรแกรมกำลังรอการป้อนอักขระ ตัวแปรที่จะเขียนต้องเป็นประเภทอักขระ char |
2 | %d | โปรแกรมคาดหวังการป้อนเลขฐานสิบของประเภทจำนวนเต็ม ตัวแปรต้องเป็นชนิด int |
3 | %i | โปรแกรมคาดหวังการป้อนเลขฐานสิบของประเภทจำนวนเต็ม ตัวแปรต้องเป็นชนิด int |
4 | %e, %E | โปรแกรมคาดว่าจะป้อนตัวเลขทศนิยม (จุลภาค) ในรูปแบบเลขชี้กำลัง ตัวแปรต้องเป็นประเภท float |
5 | %f | โปรแกรมคาดหวังเลขทศนิยม (จุลภาค) ตัวแปรต้องเป็นประเภท float |
6 | %g, %G | โปรแกรมคาดหวังเลขทศนิยม (จุลภาค)ตัวแปรต้องเป็นประเภท float |
7 | %a | โปรแกรมคาดหวังเลขทศนิยม (จุลภาค) ตัวแปรต้องเป็นประเภท float |
8 | %o | โปรแกรมคาดหวังเลขฐานแปด ตัวแปรต้องเป็นชนิด int |
9 | %s | โปรแกรมกำลังรอให้ป้อนสตริง สตริงคือชุดของอักขระใดๆ จนถึงอักขระตัวคั่นตัวแรกที่พบ ตัวแปรต้องเป็นประเภทสตริง |
10 | %x, %X | โปรแกรมรอเลขฐานสิบหก ตัวแปรต้องเป็นชนิด int |
11 | %p | ตัวแปรคาดหวังอินพุตตัวชี้ ตัวแปรต้องเป็นประเภทตัวชี้ |
12 | %n | เขียนค่าจำนวนเต็มให้กับตัวแปรเท่ากับจำนวนอักขระที่ฟังก์ชัน scanf อ่านจนถึงตอนนี้ |
13 | %u | โปรแกรมอ่านจำนวนเต็มที่ไม่ได้ลงนาม ประเภทตัวแปรต้องเป็นจำนวนเต็มไม่มีเครื่องหมาย |
14 | %b | โปรแกรมกำลังรอเลขฐานสองอยู่ ตัวแปรต้องเป็นชนิด int |
15 |
% |
สแกนชุดอักขระ โปรแกรมกำลังรอให้ป้อนอักขระจากพูลจำกัดที่ระบุระหว่างวงเล็บเหลี่ยม scanf จะทำงานตราบใดที่มีอักขระจากชุดที่ระบุในอินพุตสตรีม |
16 | %% | ลงชื่อ "%". |
ตัวอักษรในรูปแบบสตริง
สัญลักษณ์ดาว ()
เครื่องหมายดอกจัน () คือแฟล็กที่ระบุว่าการดำเนินการมอบหมายควรถูกระงับ เครื่องหมายดอกจันจะอยู่หลังเครื่องหมาย "%" ทันที ตัวอย่างเช่น
scanf("%d%c%d", &x, &y); //ละเว้นอักขระระหว่างจำนวนเต็มสองจำนวน scanf("%s%d%s", str, str2); //ละเว้นจำนวนเต็มระหว่างสองสตริง
นั่นคือ ถ้าคุณป้อนบรรทัด "45-20" ในคอนโซล โปรแกรมจะทำสิ่งต่อไปนี้:
- ตัวแปร "x" จะถูกกำหนดค่าเป็น 45.
- ตัวแปร "y" จะถูกกำหนดค่า 20.
- และเครื่องหมายลบ (แดช) "-" จะถูกละเว้นด้วย "%c"
ความกว้าง (หรือความกว้างของช่อง)
นี่คือจำนวนเต็มระหว่างเครื่องหมาย "%" และตัวระบุรูปแบบที่ระบุจำนวนอักขระสูงสุดที่จะอ่านในการดำเนินการอ่านปัจจุบัน
scanf("%20s", str); //อ่าน 20 อักขระแรกจากสตรีมอินพุต
สิ่งสำคัญที่ควรทราบคือ
- scanf จะสิ้นสุดลงหากพบอักขระตัวคั่น แม้ว่าจะไม่นับ 20 อักขระก็ตาม
- หากป้อนอักขระมากกว่า 20 ตัว ระบบจะเขียนเฉพาะ 20 อักขระแรกใน str
ตัวดัดแปลงพิมพ์ (หรือความแม่นยำ)
นี่คือแฟล็กพิเศษที่ปรับเปลี่ยนประเภทของข้อมูลที่คาดหวังสำหรับการป้อนข้อมูล แฟล็กถูกระบุทางด้านซ้ายของตัวระบุประเภท:
- L หรือ l (L เล็ก) เมื่อใช้ "l" กับตัวระบุ d, i, o, u, x แฟล็กจะบอกโปรแกรมว่าต้องการอินพุต int แบบยาว เมื่อใช้ "l" กับตัวระบุ e หรือ f แฟล็กจะบอกโปรแกรมว่าควรคาดหวังค่าสองเท่า การใช้ "L" เป็นการบอกโปรแกรมว่าคาดว่าจะมี long double การใช้ "l" กับตัวระบุ "c" และ "s" จะบอกโปรแกรมว่าต้องการอักขระสองไบต์เช่น wchar_t ตัวอย่างเช่น "%lc", "%ls", "%l[asd]".
- h เป็นแฟล็กระบุประเภทย่อ
- hh - ระบุว่าตัวแปรเป็นตัวชี้ไปยังถ่านที่มีลายเซ็นหรือค่าถ่านที่ไม่ได้ลงชื่อ แฟล็กสามารถใช้กับตัวระบุ d, i, o, u, x, n.
- ll (ตัว L ตัวเล็กสองตัว) - ระบุว่าตัวแปรเป็นตัวชี้ไปยังค่าของประเภทที่ลงนาม long long int หรือ unsigned long long int ที่ไม่ได้ลงนาม แฟล็กนี้ใช้กับตัวระบุ: d, i, o, u, x, n.
- j - ระบุว่าตัวแปรเป็นตัวชี้ไปยังประเภท intmax_t หรือ uintmax_t จากไฟล์ส่วนหัว stdint.h ใช้กับตัวระบุ: d, i, o, u, x, n.
- z - ระบุว่าตัวแปรเป็นตัวชี้ไปยังประเภท size_t ซึ่งมีคำจำกัดความอยู่ใน stddef.h ใช้กับตัวระบุ: d, i, o, u, x, n.
- t - ระบุว่าตัวแปรเป็นตัวชี้ไปยังประเภท ptrdiff_t คำนิยามประเภทนี้อยู่ใน stddef.h ใช้กับตัวระบุ: d, i, o, u, x, n.
ชัดเจนยิ่งขึ้น รูปภาพพร้อมตัวปรับแต่งสามารถแสดงเป็นตารางได้ รายละเอียดของ scanf C สำหรับโปรแกรมเมอร์จะชัดเจนขึ้น
ตัวละครอื่นๆ
อักขระใดๆ ที่พบในรูปแบบจะถูกยกเลิก ในเวลาเดียวกัน ควรสังเกตว่าการมีอักขระเว้นวรรคหรือตัวคั่น (ขึ้นบรรทัดใหม่ ช่องว่าง แท็บ) ในสตริงการควบคุมสามารถนำไปสู่ลักษณะการทำงานที่แตกต่างกันของฟังก์ชัน ในเวอร์ชันหนึ่ง scanf() จะอ่านโดยไม่บันทึกจำนวนตัวคั่นใดๆ จนกว่าจะพบอักขระอื่นที่ไม่ใช่ตัวคั่น และในเวอร์ชันอื่น ช่องว่าง (เท่านั้น) ไม่มีบทบาทและนิพจน์ "%d + %d" เทียบเท่ากับ "%d+%d".
ตัวอย่าง
มาดูตัวอย่างกันเพื่อช่วยให้คุณคิดและเข้าใจวิธีการทำงานของฟังก์ชันได้ดีขึ้น
scanf("%3s", str); // หากคุณป้อนสตริง "1d2s3d1;3" ในคอนโซล เฉพาะ "1d2" เท่านั้นที่จะถูกเขียนไปยัง str scanf("%dminus%d", &x, &y); //ลบอักขระระหว่างสองตัวเลข scanf("%5[0-9]", str); // อักขระจะถูกป้อนลงใน str จนกว่าจะมี 5 อักขระ และอักขระเป็นตัวเลขตั้งแต่ 0 ถึง 9 scanf("%lf", &d); //คาดหวังการป้อนข้อมูลสองครั้ง scanf("%hd", &x); //คาดหวังจำนวนประเภท short scanf("%hu", &y); //คาดหวัง scanf แบบสั้นของหมายเลขที่ไม่ได้ลงนาม ("lx", &z); //คาดหวังจำนวนชนิด long int
จากตัวอย่างด้านล่างแสดงให้เห็นว่าตัวเลขที่คาดไว้เปลี่ยนไปอย่างไรโดยใช้สัญลักษณ์ต่างๆ
scanf C - คำอธิบายสำหรับผู้เริ่มต้น
ส่วนนี้จะเป็นประโยชน์สำหรับผู้เริ่มต้น บ่อยครั้งที่คุณไม่จำเป็นต้องมีคำอธิบายที่สมบูรณ์ของ scanf C มากเท่ากับรายละเอียดวิธีการทำงานของฟังก์ชัน
- คุณลักษณะนี้ค่อนข้างล้าสมัย มีการใช้งานที่แตกต่างกันหลายอย่างในไลบรารีของเวอร์ชันต่างๆ ตัวอย่างเช่น ฟังก์ชัน scanf SC ที่ปรับปรุงแล้ว ซึ่งมีคำอธิบายอยู่ในเว็บไซต์ microsoft
- จำนวนตัวระบุในรูปแบบต้องตรงกับจำนวนอาร์กิวเมนต์ที่ส่งไปยังฟังก์ชัน
- องค์ประกอบสตรีมอินพุตต้องคั่นด้วยอักขระตัวแยกเท่านั้น: เว้นวรรค, แท็บ, บรรทัดใหม่ เครื่องหมายจุลภาค อัฒภาค จุด ฯลฯ - อักขระเหล่านี้ไม่ใช่ตัวคั่นสำหรับฟังก์ชัน scanf()
- หาก scanf พบตัวคั่น อินพุตจะหยุด หากมีตัวแปรให้อ่านมากกว่าหนึ่งตัว scanf จะย้ายไปอ่านตัวแปรถัดไป
- รูปแบบข้อมูลที่ป้อนไม่สอดคล้องกันเพียงเล็กน้อยนำไปสู่ผลลัพธ์ที่คาดเดาไม่ได้ของโปรแกรม ถ้าโปรแกรมจบลงด้วยข้อผิดพลาด แต่บ่อยครั้งที่โปรแกรมยังคงทำงานและผิดพลาด
- scanf("%20s …", …); หากสตรีมอินพุตเกิน 20 อักขระ scanf จะอ่าน 20 อักขระแรกและยกเลิกหรือย้ายไปอ่านตัวแปรถัดไป หากมีการระบุไว้ ในกรณีนี้ การเรียก scanf ครั้งถัดไปจะอ่านอินพุตสตรีมต่อจากจุดที่การเรียก scanf ก่อนหน้าหยุดทำงาน ถ้าเมื่ออ่าน 20. แรกอักขระ พบอักขระตัวคั่น scanf จะยกเลิกหรืออ่านตัวแปรถัดไปต่อไป แม้ว่าจะไม่ได้อ่านอักขระ 20 ตัวสำหรับตัวแปรแรกก็ตาม ในกรณีนี้ อักขระที่ยังไม่ได้อ่านทั้งหมดจะถูกแนบไปกับตัวแปรถัดไป
- หากชุดอักขระที่สแกนขึ้นต้นด้วย "^" แล้ว scanf จะอ่านข้อมูลจนกว่าจะพบอักขระตัวคั่นหรืออักขระจากชุด ตัวอย่างเช่น "%[^A-E1-5]" จะอ่านข้อมูลจากสตรีมจนกว่าจะพบอักขระภาษาอังกฤษตัวพิมพ์ใหญ่จาก A ถึง E หรือตัวเลข 1 ถึง 5 ตัวใดตัวหนึ่ง
- ฟังก์ชัน scanf C ตามที่อธิบายไว้ จะคืนค่าจำนวนเท่ากับจำนวนการเขียนตัวแปรที่ประสบความสำเร็จ หาก scanf เขียนตัวแปร 3 ตัว ผลสำเร็จของฟังก์ชันจะส่งกลับตัวเลข 3 หาก scanf ไม่สามารถเขียนตัวแปรใดๆ ได้ ผลลัพธ์จะเป็น 0 และสุดท้าย หาก scanf ไม่สามารถเริ่มต้นได้เลยด้วยเหตุผลบางอย่าง ผลลัพธ์จะเป็น EOF.
- หากฟังก์ชั่น scanf() สิ้นสุดอย่างไม่ถูกต้อง ตัวอย่างเช่น scanf("%d", &x) - ต้องการตัวเลข แต่ได้รับอักขระเป็นอินพุต การเรียก scanf() ครั้งต่อไปจะเริ่มที่จุดในสตรีมอินพุตซึ่งการเรียกใช้ฟังก์ชันก่อนหน้าสิ้นสุดลง เพื่อเอาชนะปัญหานี้ จำเป็นต้องกำจัดอักขระที่มีปัญหา ซึ่งสามารถทำได้ ตัวอย่างเช่น โดยการเรียก scanf("%s") นั่นคือฟังก์ชันจะอ่านสตริงของอักขระและโยนทิ้งไป ด้วยวิธีที่ซับซ้อนนี้ คุณสามารถป้อนข้อมูลที่จำเป็นต่อได้
- ในการใช้งาน scanf() บางอย่าง ไม่อนุญาตให้ใช้ "-" ในชุดอักขระที่สแกน
- ตัวระบุ "%c" จะอ่านอักขระแต่ละตัวจากสตรีม นั่นคือมันยังอ่านอักขระตัวคั่นด้วย หากต้องการข้ามอักขระตัวคั่นและอ่านอักขระที่ต้องการต่อ คุณสามารถใช้ "%1s"
- เมื่อใช้ตัวระบุ "c" อนุญาตให้ใช้ความกว้าง "%10c" ได้ แต่จากนั้นจะต้องส่งอาร์เรย์ขององค์ประกอบประเภท char เป็นตัวแปรไปยังฟังก์ชัน scanf
- “%[a-z]” หมายถึง “ตัวอักษรภาษาอังกฤษตัวเล็กทั้งหมด” และ “%[z-a]” หมายถึงเพียง 3 ตัวอักษร: 'z', 'a', '-' กล่าวอีกนัยหนึ่ง อักขระ "-" หมายถึงช่วงก็ต่อเมื่ออยู่ระหว่างอักขระสองตัวที่อยู่ในลำดับที่ถูกต้องเท่านั้น หาก "-" อยู่ท้ายนิพจน์ ที่จุดเริ่มต้น หรือเรียงลำดับอักขระที่ด้านใดด้านหนึ่งไม่ถูกต้อง แสดงว่าเป็นเพียงเครื่องหมายยัติภังค์ ไม่ใช่ช่วง
สรุป
สรุปคำอธิบายของ scanf C นี่เป็นคุณสมบัติที่มีประโยชน์สำหรับการทำงานในโปรแกรมขนาดเล็กและเมื่อใช้วิธีการเขียนโปรแกรมตามขั้นตอน อย่างไรก็ตาม ข้อเสียเปรียบหลักคือจำนวนข้อผิดพลาดที่คาดเดาไม่ได้ที่อาจเกิดขึ้นเมื่อใช้ scanf ดังนั้นคำอธิบายของ scanf C เมื่อการเขียนโปรแกรมควรอยู่ต่อหน้าต่อตาคุณดีที่สุด ในโครงการระดับมืออาชีพขนาดใหญ่ iostreams ถูกใช้เนื่องจากมีความสามารถระดับสูงกว่า จึงสามารถตรวจจับและจัดการข้อผิดพลาดได้ดีขึ้น และยังทำงานกับข้อมูลจำนวนมากได้อีกด้วย ควรสังเกตด้วยว่าคำอธิบายของ scanf C ในภาษารัสเซียมีอยู่ในแหล่งเครือข่ายหลายแห่งรวมถึงตัวอย่างด้วยการใช้งานเนื่องจากอายุของฟังก์ชัน ดังนั้น หากจำเป็น คุณสามารถหาคำตอบได้ในฟอรัมเฉพาะเรื่อง