Làm cách nào để viết thường một chuỗi trong C?


108

Làm cách nào để chuyển đổi chuỗi chữ hoa thường thành chuỗi chữ thường trong C?


2
Bạn chỉ xử lý ASCII với các chữ cái az thôi?
Mark Byers

1
ascii. làm thế nào tôi sẽ tính đến điều đó? ví dụ dưới đây vẫn hoạt động chứ? điều gì xảy ra nếu char của tôi là '#' và tolower () được gọi trên nó?
Tony Stark

1
Điều đó sẽ hoạt động. Tôi đã suy nghĩ nhiều hơn nếu chuỗi của bạn chứa những thứ như é hoặc Ü.
Mark Byers

1
Tại sao không chỉ sử dụng "strlwr"? strlwr((char*)str);Nó chỉ đi qua chuỗi và tự chuyển đổi nó.
Larry

1
@Larry Nó không chuẩn.
giữa

Câu trả lời:


152

Nó nằm trong thư viện chuẩn và đó là cách dễ hiểu nhất mà tôi có thể thấy để triển khai một chức năng như vậy. Vì vậy, có, chỉ cần lặp qua chuỗi và chuyển đổi từng ký tự thành chữ thường.

Một cái gì đó tầm thường như thế này:

#include <ctype.h>

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

hoặc nếu bạn thích một lớp lót, thì bạn có thể sử dụng lớp lót này của JF Sebastian:

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

35
for ( ; *p; ++p) *p = tolower(*p);có vẻ thành ngữ hơn.
jfs

14
@JF đó bạn. Phụ thuộc vào nếu họ muốn mã nhìn đáng sợ hay đẹp :) (rất có thể đọc được một lót, nhưng nó nhìn đáng sợ)
Earlz

điều này mang lại cho tôi một segfault nếu str là một char *, nhưng không phải nếu str là một mảng char. Có bất kỳ lời giải thích cho điều đó?
Electric Coffee

1
Tôi tin rằng một lớp lót sẽ khiến bạn mất con trỏ đến chuỗi.
Ace.C

2
Tôi tin rằng một lớp lót sẽ có vô số phân nhánh.
NOP da CALL

7

để chuyển đổi thành chữ thường tương đương với bit tăng 0x60 nếu bạn tự giới hạn ASCII:

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

6
Để làm cho nó dễ đọc hơn một chút, bạn có thể làmfor(char *p = pstr;*p;++p) *p=*p>='A'&&*p<='Z'?*p|0x60:*p;
Grant Peters

7
Phiên bản này thực sự chậm hơn glibc's tolower(). 55,2 so với 44,15 trên máy của tôi.
jfs

tôi không thể tưởng tượng rằng: tolower () xử lý các ký tự; chỉ khi nó là macro
Oleg Razgulyaev

1
@oraz: tolower () có int (*)(int)chữ ký. Dưới đây là đoạn mã được sử dụng để đo lường hiệu suất gist.github.com/370497
JFS

@JF: Tôi hiểu rồi, họ đã sử dụng bảng, nhưng tôi có thể tối ưu hóa: for (; * p; ++ p) if (* p> 'Z') {continue;} else if (* p <'A') {tiếp tục;} else {* p = * p | 0x60;}
Oleg Razgulyaev

1

Bạn chỉ xử lý các chuỗi ASCII và không có vấn đề về ngôn ngữ? Sau đó, có, đó sẽ là một cách tốt để làm điều đó.


điều gì sẽ xảy ra nếu tolower () được gọi trên một char không phải ascii az? giống '!' hoặc là '#'. tôi đã thử nghiệm nó trên '#' và nó có vẻ hoạt động tốt. Điều này có đúng với tất cả các ký tự ascii không phải là các chữ cái az không?
Tony Stark

1
@hatorade: tolower()không thay đổi đối số nếu nó không nằm trong phạm vi 'A' .. 'Z'.
jfs

1
! và # đều là ký tự ascii. Đánh dấu đã đề cập đến mã hóa khác như UTF8, nơi bạn không thể giả định rằng có một byte cho mỗi ký tự (như giải pháp này không)
hdgarrood


1

Nếu chúng ta sử dụng cẩu thả tolower(), hãy làm như sau:

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

Nhưng, tốt, nó sẽ phát nổ nếu bạn cho nó ăn một số ký hiệu / chữ số, và nói chung là nó xấu xa. Tuy nhiên, câu hỏi phỏng vấn hay.


6
Vâng, điều này sẽ gấp / trục chính / cắt xén nhiều ký hiệu khác nhau (trong ASCII, bất kỳ ký hiệu, ký tự điều khiển hoặc chữ số nào có bit 5 rõ ràng sẽ trở thành mã ký tự tương tự với bộ bit 5, v.v.) vì vậy thực sự, nghiêm túc, không sử dụng nó.
Ken S

Bài đăng này được thảo luận về meta .
Patrick Hofman

0

Vòng con trỏ để đạt được hiệu suất tốt hơn:

#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;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.