Как сделать первое слово предложения заглавным в Objective-C?

Я уже нашел, как писать с большой буквы все слова предложения, а не только первое слово.

NSString *txt =@"hi my friends!"
[txt capitalizedString];

Я не хочу переходить на нижний регистр и использовать первый символ с заглавной буквы. Я хотел бы использовать только первое слово без изменения остальных.


person wal    schedule 12.03.2010    source источник


Ответы (8)


Вот еще один вариант:

NSString *txt = @"hi my friends!";
txt = [txt stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:[[txt substringToIndex:1] uppercaseString]];

Для языка Swift:

txt.replaceRange(txt.startIndex...txt.startIndex, with: String(txt[txt.startIndex]).capitalizedString)
person Johan Kool    schedule 12.03.2010
comment
Просто убедитесь, что длина строки всегда не менее 1 символа, или что вы готовы обработать исключение, когда это не так. - person Johan Kool; 15.03.2010
comment
Добавьте проверку if([txt length] › 1) перед заменой строки строкой с заглавной буквы. - person looneydoodle; 11.05.2012
comment
@looneydoodle Вы имеете в виду if ([txt length] > 0). Он отлично работает, если длина равна 1. - person Johan Kool; 12.05.2012
comment
Предлагаемое изменение: добавить точку с запятой в качестве последнего символа первой строки. Предотвратит ошибку Xcode при копировании и вставке. - person John Erck; 23.10.2013
comment
Этот ответ неверен. Смотрите мой ответ для правильного подхода. - person Ken Thomases; 12.07.2014
comment
См. мой другой ответ для решения Swift проблемы использования заглавной буквы в строке. Кен Томасс считает, что вам нужно учитывать локализацию, и я рекомендую его ответ: это то, что вам нужно, но во многих случаях этого подхода достаточно. - person Johan Kool; 12.05.2015

Принятый ответ неверен. Во-первых, неправильно рассматривать единицы NSString как «символы» в том смысле, в каком их ожидает пользователь. Есть суррогатные пары. Есть комбинационные последовательности. Их разделение приведет к неправильным результатам. Во-вторых, не обязательно, что заглавная буква первого символа дает тот же результат, что и заглавная буква слова, содержащего этот символ. Языки могут быть контекстно-зависимыми.

Правильный способ сделать это — заставить фреймворки идентифицировать слова (и, возможно, предложения) в соответствии с локалью. А также использовать заглавные буквы в соответствующей локали манере.

[aMutableString enumerateSubstringsInRange:NSMakeRange(0, [aMutableString length])
                                   options:NSStringEnumerationByWords | NSStringEnumerationLocalized
                                usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
    [aMutableString replaceCharactersInRange:substringRange
                                  withString:[substring capitalizedStringWithLocale:[NSLocale currentLocale]]];
    *stop = YES;
}];

Возможно, что первое слово строки не совпадает с первым словом первого предложения строки. Чтобы идентифицировать первое (или каждое) предложение строки, а затем использовать первое слово этого (или тех) с заглавной буквы, затем окружите вышеуказанное внешним вызовом -enumerateSubstringsInRange:options:usingBlock: с помощью NSStringEnumerationBySentences | NSStringEnumerationLocalized. Во внутреннем вызове передайте substringRange, предоставленный внешним вызовом, в качестве аргумента диапазона.

person Ken Thomases    schedule 12.07.2014
comment
Для тех, кто хочет сделать первую букву каждого слова заглавной, просто измените последнюю строку на *stop = enclosingRange.location + enclosingRange.length == self.length;. - person Authman Apatira; 21.03.2015
comment
Если вы хотите писать каждое слово с заглавной буквы, тогда вообще не нужно перечислять по словам. Это поведение -capitalizedStringWithLocale: по умолчанию. Даже если вы хотите перечислить каждое слово, способ сделать это — просто никогда не устанавливать *stop. Перечисление естественно заканчивается в конце строки. (В общем, в методах перечисления с блоком Cocoa вы никогда не должны устанавливать *stop, если вы не устанавливаете его в значение true. Это в основном важно для параллельных перечислений, но это предусмотрено в контракте на проектирование для всех случаев.) - person Ken Thomases; 21.03.2015
comment
Для языков, где каждое существительное пишется с большой буквы, например немецкого, это не сработает. Он будет использовать только первое слово в предложении, а не каждое существительное. - person keithbhunter; 23.11.2016
comment
@keithbhunter, хорошо, но вопрос был не об этом. И я был бы удивлен, если бы существовал какой-либо API, который правильно подходил бы для описанной вами ситуации. - person Ken Thomases; 24.11.2016

Использовать

- (NSArray *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator

и используйте первый объект в массиве, а затем используйте

- (NSString *)componentsJoinedByString:(NSString *)separator

присоединиться к ним обратно

person Tuomas Pelkonen    schedule 12.03.2010
comment
Я довольно чужд Objective-c, но вам нужно так много сделать, чтобы просто написать это слово с большой буквы ?? - person Teja Kantamneni; 12.03.2010
comment
Да, только первое слово с заглавной буквы. К сожалению, Objective-C не похож на Python, где каждую операцию можно выполнить в одной строке. - person Tuomas Pelkonen; 12.03.2010
comment
@Teja: NSString изначально не поддерживает выполнение каких-либо действий только с одним словом в строке, и в любом случае это довольно многословный язык, так что да. - person Chuck; 12.03.2010

вы можете использовать регулярное выражение, которое я сделал, это работает для меня просто, вы можете вставить ниже код + (NSString *) CaptializeFirstCharacterOfSentence: (NSString *) предложение {

NSMutableString *firstCharacter = [sentence mutableCopy];
NSString *pattern = @"(^|\\.|\\?|\\!)\\s*(\\p{Letter})";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:NULL];
[regex enumerateMatchesInString:sentence options:0 range:NSMakeRange(0, [sentence length]) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
    //NSLog(@"%@", result);
    NSRange r = [result rangeAtIndex:2];
    [firstCharacter replaceCharactersInRange:r withString:[[sentence substringWithRange:r] uppercaseString]];
}];
NSLog(@"%@", firstCharacter);
return firstCharacter;

} //Вызываем этот метод NsString *resultSentence = [UserClass CaptializeFirstCharacterOfSentence:yourTexthere];

person Ashok Kumar    schedule 26.02.2015

Альтернативное решение в Swift:

var str = "hello"

if count(str) > 0 {
    str.splice(String(str.removeAtIndex(str.startIndex)).uppercaseString, atIndex: str.startIndex)
}
person Johan Kool    schedule 12.05.2015
comment
Что такое сплайсинг? - person Arpit B Parekh; 24.04.2020
comment
@ArpitBParekh Этот код устарел. Он работал в Swift в то время, когда я его опубликовал, но с тех пор splice был заменен. - person Johan Kool; 24.04.2020
comment
Спасибо за ответ @Johan Kool - person Arpit B Parekh; 25.04.2020

Чтобы иметь варианты, я бы предложил:

NSString *myString = [NSString stringWithFormat:@"this is a string..."];

char *tmpStr = calloc([myString length] + 1,sizeof(char));

[myString getCString:tmpStr maxLength:[myString length] + 1 encoding:NSUTF8StringEncoding];

int sIndex = 0;

/* skip non-alpha characters at beginning of string */
while (!isalpha(tmpStr[sIndex])) {
    sIndex++;
}

toupper(tmpStr[sIndex]);

myString = [NSString stringWithCString:tmpStr encoding:NSUTF8StringEncoding];

Я на работе, и у меня нет своего Mac, чтобы проверить это, но, если я правильно помню, вы не можете использовать [myString cStringUsingEncoding:NSUTF8StringEncoding], потому что он возвращает const char *.

person alesplin    schedule 12.03.2010

В Swift вы можете сделать это следующим образом, используя это расширение:

extension String {
    func ucfirst() -> String {
        return (self as NSString).stringByReplacingCharactersInRange(NSMakeRange(0, 1), withString: (self as NSString).substringToIndex(1).uppercaseString)
    }    
}

вызов вашей строки следующим образом:

var ucfirstString:String = "test".ucfirst()
person Antoine    schedule 17.12.2014

Я знаю, что вопрос задает конкретно ответ цели C, однако вот решение для Swift 2.0:

let txt = "hi my friends!"
var sentencecaseString = ""

for (index, character) in txt.characters.enumerate() {
    if 0 == index {
        sentencecaseString += String(character).uppercaseString
    } else {
        sentencecaseString.append(character)
    }
}

Или как расширение:

func sentencecaseString() -> String {
    var sentencecaseString = ""
    for (index, character) in self.characters.enumerate() {
        if 0 == index {
            sentencecaseString += String(character).uppercaseString
        } else {
            sentencecaseString.append(character)
        }
    }
    return sentencecaseString
}
person pheedsta    schedule 11.08.2015