[英]How to capitalize first letter of each word except certain words (“and”, “but”, “of”)?
給出的輸入是: the lord of the rings
預期的輸出是: The Lord of the Rings
但是我得到的是: The Lord ofof thethe Rings
碼:
#include <cs50.h>
#include <string.h>
#include <stdio.h>
int main(void)
{
string s = GetString();
//to print an upper case char
printf("%c", toupper(s[0]));
for (int i = 1, n = strlen(s); i <n; i++)
{
//not to capitalize and but of
if (isspace(s[i]))
{
if (s[i + 1] == 't' && s[i + 2] == 'h' && s[i + 3] == 'e') {
printf("%c%c%c%c", s[i], s[i + 1], s[i+2], s[i+3]);
} else if (s[i + 1] == 'a' && s[i + 2] == 'n' && s[i + 3] == 'd') {
printf("%c%c%c%c", s[i], s[i + 1], s[i+2], s[i+3]);
} else if (s[i + 1] == 'b' && s[i + 2] == 'u' && s[i + 3] == 't') {
printf("%c%c%c%c", s[i], s[i + 1], s[i+2], s[i+3]);
} else if (s[i + 1] == 'o' && s[i + 2] == 'f') {
printf("%c%c%c", s[i], s[i + 1], s[i+2]);
} else { //capitalize rest of the code:
printf("%c%c", s[i], toupper(s[i + 1]));
i++;
}
} else {
if( (s[i] == 't' && s[i + 1] == 'h' && s[i + 2] == 'e')
|| (s[i] == 'a' && s[i + 1] == 'n' && s[i + 2] == 'd')
|| (s[i] == 'b' && s[i + 1] == 'u' && s[i + 2] == 't')
|| (s[i] == 'o' && s[i + 1] == 'f' ) )
continue;
else
printf("%c",s[i]);
}
}
}
請幫我解決。
在每個if
子句中,跳過一個停用詞后,您需要根據該詞的長度來調整索引,例如:
if (s[i + 1] == 't' && s[i + 2] == 'h' && s[i + 3] == 'e') {
printf("%c%c%c%c", s[i], s[i + 1], s[i+2], s[i+3]);
i += 3; // Skip the next 3 positions
}
這仍然不能解決不大寫“看起來像”停用詞的較長詞(例如android , butter或offset )的問題。
我會考慮學習strtok()
函數。 您可以使用它來將行分成單個單詞。 然后,如果您有一個包含不應大寫的單詞的數組,則可以使用strcmp()
在此列表中檢查每個單詞,並在適當的情況下將其大寫,然后再將其添加到包含大寫字母的行中。 下面的代碼執行此操作,並且始終將第一個單詞大寫。 請注意, skip_list[]
在最后一個單詞之后包含一個NULL
指針; 用於遍歷列表。 還要注意,用於存儲大寫結果的數組title[]
已分配,因此其長度足以容納input
字符串(包括NUL
終止符)。 此外, title
首先被定義為一個空字符串,以便可以使用strcat()
將第一個word
標記與其安全地連接。
可以通過編寫upcase()
函數(將單詞的第一個字母字符大寫,然后將其余字符downcase()
和downcase()
函數(將單詞中的所有字符downcase()
來改進此方法。 而不是盲目地僅改寫第一個字符,這將可以更好地處理混亂的輸入,例如"tHe lorD oF The rINgs"
。
最后一點:函數strtok()
將通過向其中寫入'\\0'
字符來修改input
。
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdbool.h>
#define MAX_SKIP 100
bool in_list(const char *word, const char **list);
int main(void)
{
const char *skip_words[MAX_SKIP] = { "and", "but", "of", "the", NULL };
char input[] = "the lord of the rings";
size_t title_sz = strlen(input) + 1;
char title[title_sz];
char *word;
title[0] = '\0';
word = strtok(input, " ");
word[0] = toupper(word[0]);
strcat(title, word);
while ((word = strtok(NULL, " "))) {
if (!in_list(word, skip_words)) {
word[0] = toupper(word[0]);
}
strcat(title, " ");
strcat(title, word);
}
puts(title);
return 0;
}
bool in_list(const char *word, const char **list)
{
while (*list != NULL) {
if (strcmp(word, *list) == 0) {
break;
}
++list;
}
return *list != NULL;
}
程序輸出為:
指環王
我基於Apache的WordUtils.capitalize()方法編寫了代碼。 您可以將分隔符設置為正則表達式字符串。 如果要跳過[[and],“ but”,“ of”]之類的詞,只需將其設置為定界符即可。
public static String capitalize(String str, final String delimitersRegex) {
if (str == null || str.length() == 0) {
return "";
}
final Pattern delimPattern;
if (delimitersRegex == null || delimitersRegex.length() == 0){
delimPattern = Pattern.compile("\\W");
}else {
delimPattern = Pattern.compile(delimitersRegex);
}
final Matcher delimMatcher = delimPattern.matcher(str);
boolean delimiterFound = delimMatcher.find();
int delimeterStart = -1;
if (delimiterFound){
delimeterStart = delimMatcher.start();
}
final int strLen = str.length();
final StringBuilder buffer = new StringBuilder(strLen);
boolean capitalizeNext = true;
for (int i = 0; i < strLen; i++) {
if (delimiterFound && i == delimeterStart) {
final int endIndex = delimMatcher.end();
buffer.append( str.substring(i, endIndex) );
i = endIndex;
if( (delimiterFound = delimMatcher.find()) ){
delimeterStart = delimMatcher.start();
}
capitalizeNext = true;
} else {
final char ch = str.charAt(i);
if (capitalizeNext) {
buffer.append(Character.toTitleCase(ch));
capitalizeNext = false;
} else {
buffer.append(ch);
}
}
}
return buffer.toString();
}
希望對您有所幫助:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.