จะหลีกเลี่ยงการลงชื่อ% (เปอร์เซ็นต์) ใน printf ของ C ได้อย่างไร


คำตอบ:


421

คุณสามารถหนีได้โดยโพสต์ '%' สองเท่าดังนี้ %%

ใช้ตัวอย่างของคุณ:

printf("hello%%");

การหลีกเลี่ยงสัญญาณ '%' ใช้สำหรับ printf เท่านั้น ถ้าคุณทำ:

char a[5];
strcpy(a, "%%");
printf("This is a's value: %s\n", a);

มันจะพิมพ์: This is a's value: %%


8
"printf (" สวัสดี %% ");" ถูกต้อง แต่ฉันไม่คิดว่าจะหลบหนี ใช้ printf ("hello \ 045");
Lai Jiangshan

1
@Pablo Santa Cruz: วิธีการ "หลบหนี" %นี้เฉพาะเจาะจงprintfใช่ไหม?
Lazer

10
นี่เป็นกรณีพิเศษของกฎที่พบบ่อยมากในระบบการหลบหนีที่จะได้รับสัญลักษณ์การหลบหนีแท้จริงคุณใช้ <escape symbol> <escape symbol>
dmckee --- ผู้ดูแลอดีตแมว

12
ลาย Jiangshan สิ่งนี้จะไม่ทำงาน \045เป็นการหลบหนีเวลารวบรวมที่เป็นส่วนหนึ่งของภาษาและจะเปลี่ยนเป็น%เมื่อรวบรวม printfเป็นฟังก์ชั่นเวลาทำงานดังนั้นจึงมีข้อตกลงกับไบต์ของสตริงของคุณไม่ได้อยู่กับรหัสที่มา C และจะมีลำดับของตัวเองหลบหนีที่มีส่วนของฟังก์ชั่น ในระยะสั้นprintfคือ "ภาษาภายในภาษา" และให้ผลเช่นเดียวกับprintf("This is a's value: %s\n", a); printf("This is a's value: \045\0163\012", a);
Triang3l

5
printf("hello%c", '%');นอกจากนี้คุณยังสามารถทำเช่นนี้: อย่างไรก็ตาม%%ดีกว่าเพราะไม่ได้ใช้อาร์กิวเมนต์อื่น
Triang3l

36

ดังที่คนอื่น ๆ พูดกัน %% จะหลบหนี%

อย่างไรก็ตามโปรดทราบว่าคุณไม่ควรทำสิ่งนี้:

char c[100];
char *c2;
...
printf(c); /* OR */
printf(c2);

เมื่อใดก็ตามที่คุณต้องพิมพ์สตริงเสมอทุกครั้งจะพิมพ์โดยใช้เสมอ

printf("%s", c)

เพื่อป้องกัน% ฝังตัวจากการก่อให้เกิดปัญหา [การละเมิดหน่วยความจำ, segfault, ฯลฯ ]


โดยทั่วไปคำเตือนนั้นเหมาะสม แต่อาจมีสถานการณ์ที่คุณต้องการทำสิ่งนี้ "" ตราบใดที่คุณรู้ว่าสตริงที่คุณให้นั้นจะถูกตีความว่าเป็นรูปแบบของสตริง
PP

2
ฉันหาวิธีแก้ปัญหาทางเลือกขึ้นมาหนึ่งครั้ง - คัดลอกบัฟเฟอร์ไปยังบัฟเฟอร์อีกครั้งจากนั้นให้ผ่านเครื่องหมาย% ขึ้นไปสองเท่า ในที่สุดฉันก็ได้พบกับความคิดนี้และแทนที่ฟังก์ชั่น 20-30 บรรทัดด้วยหนึ่งบรรทัด ไม่ต้องกังวลฉันตีหัวตัวเองอย่างรุนแรงในขณะที่ฉันสมควรได้รับ
แกรมเพอร์โรว์

จริง แต่อย่าลืมว่า 99% ของเวลาเมื่อคุณได้รับสตริงรูปแบบคุณจะได้รับอาร์กิวเมนต์เป็น va_list ดังนั้นคุณต้องใช้ vprintf ดังนั้นฉันเทคนิคที่ถูกต้อง;)
Mikeage

2
มันง่ายกว่ามากที่จะทำ (c) ถ้า
วิลเลียมเพอร์เซล

1
ทำให้ผนวกขึ้นบรรทัดใหม่ นั่นเป็นพฤติกรรมที่ไม่ต้องการ
Mikeage

33

หากไม่มีรูปแบบในสตริงคุณสามารถใช้puts(หรือfputs):

puts("hello%");

หากมีรูปแบบในสตริง:

printf("%.2f%%", 53.2);

ดังที่ระบุไว้ในความคิดเห็นต่อputsท้าย\nเอาต์พุตและfputsไม่


4
มีมูลค่าการกล่าวถึง fputs () เช่นกันเนื่องจากเป็นการแลกเปลี่ยนโดยตรงกับ fprintf ()
Tim Post

1
ใส่ยังขึ้นบรรทัดใหม่ต่อท้าย [แม้ว่าคุณจะมีหนึ่ง] ถ้าคุณต้องการที่ดี มิฉะนั้น ...
Mikeage

@Sinan Ünür: putsขอบคุณสำหรับการเตือนฉันเกี่ยวกับ ฉันไม่เคยคิดว่าสำหรับการพิมพ์สตริงและกระโดดตรงไปยังputs printfไม่อีกแล้ว.
Lazer


7

Nitpick:
คุณไม่ได้หลบหนี%ในสตริงที่ระบุรูปแบบสำหรับprintf()(และscanf()) ตระกูลฟังก์ชัน

%ในprintf()(และscanf()ครอบครัว) ฟังก์ชั่นเริ่มต้นข้อกำหนดการแปลง หนึ่งในกฎสำหรับสเปคการแปลงระบุว่า a %ในฐานะที่เป็นตัวระบุการแปลง (ทันที%ที่เริ่มสเปคการแปลง) ทำให้'%'อักขระถูกเขียนโดยไม่มีการแปลงอาร์กิวเมนต์

สตริงมี 2 ตัวอักษรจริง ๆ'%' (ตรงกันข้ามกับการหลีกเลี่ยงอักขระ: "a\bc"เป็นสตริงที่มีอักขระที่ไม่ใช่ null 3 ตัว"a%%b"คือสตริงที่มีอักขระที่ไม่ใช่ null 4 ตัว)


2
ในทางเทคนิคมันยังคง "หนี"; ตัวละครที่ต้องการวิธีพิเศษในการ "หลบหนี" ความหมายพิเศษของพวกเขาและกลับสู่ "ลักษณะตัวละคร" ของพวกเขา
ShinTakezou



3

แบ็กสแลชใน C ใช้เพื่อหนีอักขระในสตริง สตริงจะไม่รู้จัก% เป็นอักขระพิเศษดังนั้นจึงไม่จำเป็นต้องมีการยกเว้น Printf เป็นอีกเรื่อง: ใช้ %% เพื่อพิมพ์หนึ่ง%






1

double '%' ยังทำงานใน ".Format (…) ตัวอย่าง (ด้วย iDrawApertureMask == 87, fCornerRadMask == 0.05): csCurrentLine.Format("\%ADD%2d%C,%6.4f*\%",iDrawApertureMask,fCornerRadMask) ; ให้ค่าที่ต้องการและคาดหวังของ (เนื้อหาสตริงใน) csCurrentLine;"% ADD87C, 0.0500 *% "

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.