ฉันจะพิมพ์สตริงใน C ได้อย่างไร


108

ฉันจะแปลงสตริงกรณีผสมเป็นสตริงตัวพิมพ์เล็กใน C ได้อย่างไร


2
คุณแค่จัดการกับ ASCII ด้วยตัวอักษร az เท่านั้นหรือไม่?
Mark Byers

1
ascii. ฉันจะคำนึงถึงสิ่งนั้นได้อย่างไร? ตัวอย่างด้านล่างจะยังใช้งานได้หรือไม่ จะเกิดอะไรขึ้นถ้าถ่านของฉันเป็น '#' และ tolower () ถูกเรียกใช้?
Tony Stark

1
ที่จะทำงาน ฉันคิดมากขึ้นถ้าสตริงของคุณมีสิ่งต่างๆเช่นéหรือÜ
Mark Byers

1
ทำไมไม่ใช้แค่ "strlwr" ล่ะ? strlwr((char*)str);มันแค่ผ่านสตริงและแปลงมันเอง
Larry

1
@ แลร์รี่มันไม่ได้มาตรฐาน
กลางเดือน

คำตอบ:


153

มันอยู่ในไลบรารีมาตรฐานและนั่นเป็นวิธีที่ตรงไปตรงมาที่สุดที่ฉันเห็นเพื่อใช้ฟังก์ชันดังกล่าว ใช่เพียงแค่วนสตริงและแปลงอักขระแต่ละตัวเป็นตัวพิมพ์เล็ก

สิ่งเล็กน้อยเช่นนี้:

#include <ctype.h>

for(int i = 0; str[i]; i++){
  str[i] = tolower(str[i]);
}

หรือถ้าคุณชอบหนึ่งสมุทรคุณสามารถใช้อันนี้โดย JF Sebastian:

for ( ; *p; ++p) *p = tolower(*p);

35
for ( ; *p; ++p) *p = tolower(*p);ดูเหมือนสำนวนมากขึ้น
jfs

14
@JF ไปเลย ขึ้นอยู่กับว่าพวกเขาต้องการให้โค้ดดูน่ากลัวหรือดี :) (ซับหนึ่งที่อ่านง่าย แต่มันดูน่ากลัว)
Earlz

สิ่งนี้ทำให้ฉันมีค่า segfault ถ้า str เป็น a char *แต่ไม่ใช่ถ้า str เป็นอาร์เรย์ถ่าน มีคำอธิบายสำหรับสิ่งนั้นหรือไม่?
Electric Coffee

1
ฉันเชื่อว่าซับเส้นเดียวจะทำให้คุณสูญเสียตัวชี้ไปที่สตริง
Ace.C

2
ฉันเชื่อว่าซับหนึ่งเส้นจะมีการแตกแขนงออกไปมากมาย
NOP da CALL

7

การแปลงเป็นตัวพิมพ์เล็กจะเทียบเท่ากับการเพิ่มบิต 0x60 หากคุณ จำกัด ตัวเองเป็น ASCII:

for(char *p = pstr; *p; ++p)
    *p = *p > 0x40 && *p < 0x5b ? *p | 0x60 : *p;

6
เพื่อให้อ่านง่ายขึ้นเล็กน้อยคุณสามารถทำได้for(char *p = pstr;*p;++p) *p=*p>='A'&&*p<='Z'?*p|0x60:*p;
Grant Peters

7
เวอร์ชันนี้ช้ากว่า glibc tolower()จริงๆ 55.2 เทียบกับ 44.15 บนเครื่องของฉัน
jfs

ฉันนึกภาพไม่ออกว่า tolower () เกี่ยวข้องกับตัวอักษร; เฉพาะในกรณีที่เป็นมาโคร
Oleg Razgulyaev

1
@oraz: tolower () มีint (*)(int)ลายเซ็น. นี่คือรหัสที่ใช้สำหรับการวัดประสิทธิภาพgist.github.com/370497
jfs

@JF: ฉันเห็นพวกเขาใช้ตาราง แต่ฉันสามารถปรับให้เหมาะสม: สำหรับ (; * p; ++ p) ถ้า (* p> 'Z') {ดำเนินการต่อ;} else if (* p <'A') {ต่อ;} else {* p = * p | 0x60;}
Oleg Razgulyaev

1

คุณเพิ่งจัดการกับสตริง ASCII และไม่มีปัญหาด้านโลแคลใช่หรือไม่? ใช่ว่าจะเป็นวิธีที่ดี


จะเกิดอะไรขึ้นถ้า tolower () ถูกเรียกบน non-ascii az char? ชอบ '!' หรือ '#'. ฉันทดสอบบน '#' และดูเหมือนว่าจะใช้งานได้ดี โดยทั่วไปแล้วสิ่งนี้เป็นจริงสำหรับอักขระ ascii ทั้งหมดที่ไม่ใช่ตัวอักษร az หรือไม่?
Tony Stark

1
@hatorade: tolower()ไม่เปลี่ยนแปลงอาร์กิวเมนต์หากไม่ได้อยู่ในช่วง 'A' .. 'Z'
jfs

1
! และ # เป็นทั้งตัวอักษร ascii Mark อ้างถึงการเข้ารหัสอื่น ๆ เช่น UTF8 ซึ่งคุณไม่สามารถสันนิษฐานได้ว่ามีหนึ่งไบต์ต่ออักขระ (ตามที่โซลูชันนี้ทำ)
hdgarrood


1

ถ้าเราจะใช้งานเลอะเทอะให้tolower()ทำดังนี้

char blah[] = "blah blah Blah BLAH blAH\0"; int i=0; while(blah[i]|=' ', blah[++i]) {}

แต่มันจะระเบิดได้ถ้าคุณป้อนสัญลักษณ์ / ตัวเลขบางอย่างและโดยทั่วไปแล้วมันก็ชั่วร้าย คำถามสัมภาษณ์ที่ดีแม้ว่า


6
ใช่สิ่งนี้จะพับ / แกนหมุน / ตัดทอนสัญลักษณ์ต่างๆ (ใน ASCII สัญลักษณ์ใด ๆ อักขระควบคุมหรือตัวเลขที่มีบิต 5 ชัดเจนจะกลายเป็นรหัสอักขระเดียวกันกับชุดบิต 5 เป็นต้น) ดังนั้นอย่างจริงจังอย่า ใช้มัน.
Ken S

โพสต์นี้จะกล่าวถึงในเมตา
Patrick Hofman

0

การวนตัวชี้เพื่อให้ได้ประสิทธิภาพที่ดีขึ้น:

#include <ctype.h>

char* toLower(char* s) {
  for(char *p=s; *p; p++) *p=tolower(*p);
  return s;
}
char* toUpper(char* s) {
  for(char *p=s; *p; p++) *p=toupper(*p);
  return s;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.