2017-01-15 3 views
-1

ввода приведены в: 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]);   
    } 
    } 
} 

Пожалуйста, помогите мне решить эту проблему.

+1

время использовать отладчик. –

+2

Этот код будет намного лучше с вариантом 'strcmp()' вместо проверки каждого символа отдельно. – chrisaycock

ответ

2

В каждом 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, масло или смещение).

2

Я хотел бы узнать о функции strtok(). Вы можете использовать это, чтобы разбить свою линию на отдельные слова. Затем, если у вас есть массив, содержащий слова, которые не должны быть заглавные, каждое слово может быть проверено в этом списке с использованием strcmp() и при необходимости капитализируется, прежде чем добавлять его в массив, содержащий заглавную строку. Приведенный ниже код делает это и всегда заглаживает первое слово. Обратите внимание, что skip_list[] содержит указатель NULL после последнего слова; это используется для итерации по списку. Также обратите внимание, что массив title[], который используется для хранения капитализированного результата, распределяется так, что он достаточно длинный, чтобы удерживать строку input, включая терминатор NUL. Кроме того, title сначала определяется как пустая строка, так что первый маркер word может быть безопасно соединен с ним с использованием strcat().

Этот подход можно улучшить, написав функцию upcase(), которая обновляет первый буквенный символ слова и уменьшает оставшиеся символы, а также функцию , которая сокращает все символы в слове. Вместо слепого подъема только первого символа это позволило бы лучше обрабатывать беспорядочные входы, например, "tHe lorD oF The rINgs".

Последнее замечание: функция strtok() будет изменять input путем записи в нее '\0' символов.

#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; 
} 

выход Программа:

Властелин колец

0

Я написал код, основанный на методе() WordUtils.capitalize Apache. Вы можете установить разделители как строку регулярных выражений. Если вы хотите, чтобы слова, подобные ["и", "но", "из"], были пропущены, просто установите их как разделитель.

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(); 
} 

Надежда, что помогает :)

Смежные вопросы