Як я можу записувати рядки в C?


108

Як я можу перетворити змішаний рядок у нижній регістр на C?


2
Ви просто маєте справу з ASCII лише буквами az?
Марк Байєрс

1
ascii. як я міг би це врахувати? чи все ще працює приклад нижче? що станеться, якщо мій char - знак "#", і tolower () викликає його?
Тоні Старк

1
Це спрацює. Я більше думав, чи містить ваш рядок такі речі, як é чи Ü.
Марк Байєрс

1
Чому б просто не використовувати "strlwr"? strlwr((char*)str);Він просто проходить через рядок і сам перетворює його.
Ларрі

@Larry Це нестандартно.
середина

Відповіді:


152

Це в стандартній бібліотеці, і це найбільш прямий шлях, який я бачу, щоб реалізувати таку функцію. Так що так, просто переведіть через рядок і перетворіть кожен символ у малі регістри.

Щось тривіальне, як це:

#include <ctype.h>

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

або якщо ви віддаєте перевагу одному вкладишу, тоді ви можете використовувати цей JF Себастьян:

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

35
for ( ; *p; ++p) *p = tolower(*p);здається ідіоматичнішим.
jfs

14
@JF там ви йдете. Залежить від того, чи хочуть вони, щоб код виглядав страшно чи приємно :) (дуже легко читається один вкладиш, але це виглядає страшно)
Earlz

це дає мені segfault, якщо str є a char *, але не, якщо str - це масив char. У вас є якесь пояснення?
Електрична кава

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;
Грант Петерс

7
Ця версія насправді повільніше, ніж версія glibc tolower(). 55,2 проти 44,15 на моїй машині.
jfs

Я не можу собі цього уявити: tolower () має справу з символами; лише якщо це макрос
Олег Разгуляєв

1
@oraz: tolower () має int (*)(int)підпис. Ось код, який використовується для вимірювань продуктивності gist.github.com/370497
jfs

@JF: я бачу, вони використовували таблицю, але я можу оптимізувати: for (; * p; ++ p) if (* p> 'Z') {продовжити;} else if (* p <'A') {продовжити;} інше {* p = * p | 0x60;}
Олег Разгуляєв

1

Ви просто маєте справу з рядками ASCII, і у вас немає проблем з локалью? Тоді так, це був би хороший спосіб зробити це.


що станеться, якщо tolower () викликається на non-ascii az char? подібно до '!' або "#". Я перевірив це на "#", і, здавалося, працює добре. це взагалі вірно для всіх символів ascii, які не букви az?
Тоні Старк

1
@hatorade: tolower()залишає аргумент незмінним, якщо він не знаходиться в діапазоні 'A' .. 'Z'.
jfs

1
! і # обидва символи ascii. Марк мав на увазі інші кодування, такі як 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

Цей пост обговорюється на мета .
Патрік Хофман

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;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.