Изменить строку на регистр Pascal

#c

#c

Вопрос:

работаю над некоторым кодом. Я новичок в c, поэтому, вероятно, не пойму суперсложный синтаксис. Как указано в вопросе, у меня есть строка, прочитанная пользователем. «cat dog» и программа изменяет его на регистр pascal. Как вы можете видеть, первая буква каждого слова написана заглавными буквами, а пробелы удалены. Вот где у меня возникли проблемы, я не могу понять, как удалить пробелы. Я думал о вводе временного массива, но из-за проблем с областью видимости я не могу вернуть новый массив строк. Заранее спасибо. Также я должен оставаться в пределах функции и не могу создавать новые.

  #include <stdio.>
 #include <stdlib.h>
 #include <string.h>

char toUpperCase(char ch){ //changes char to uppercase
return ch - 'a'  'A';
}

char toLowerCase(char ch){//changes char to lower case
return ch -'A' 'a';
}


void PascalCase(char* word){//"cat dog" "CatDog"
/*Convert to Pascal case
 It is safe to assume that the string is terminated by ''*/
char temp[100];//do not know how to implement
int i;
if (word[0] >= 97 amp;amp; word[0] <= 122) {
    word[0] = toUpperCase(word[0]);
}
    for (i = 1; i < strlen(word);   i) {
        if (word[i] >= 65 amp;amp; word[i] <= 90) {
            word[i] = toLowerCase(word[i]);
        }
        if (word[i] == ' '){
              i;
            if (word[i] >= 97 amp;amp; word[i] <= 122) {
                word[i] = toUpperCase(word[i]);
            }
        }
    }

}



int main(){
 char word[100]; 
 printf("Enter phrase:");
 fgets(word, 100, stdin);

 /*Call PascalCase*/
 PascalCase(word);

 /*Print new word*/
 printf("%sn", word);
 return 0;
}
  

Комментарии:

1. «из-за проблем с областью видимости я не могу вернуть новый массив строк». Вы можете, если используете динамическое выделение памяти. char *temp = malloc(100); . Но убедитесь, что память освобождается, когда она больше не нужна. Другая распространенная идиома заключается в том, что функция принимает указатель буфера, который передает вызывающий объект.

2. не используйте магические числа, такие как 65 или 97. 'a' и 'A' показывает намерение намного яснее и работает в любой кодировке, если от a до z являются непрерывными

Ответ №1:

Вы можете попробовать мой код ниже:

   inline char toUpperCase(char c){
    if('a'<=c amp;amp; c<='z') return c-'a' 'A';
    else return c;
  }
  inline char toLowerCase(char c){
    if('A'<=c amp;amp; c<='Z') return c-'A' 'a';
    else return c;
  }
  void toPascalCase(char *str){
    int i,j=0; bool first=true;
    for(i=0;str[i];i  ){
      if(str[i]==' ') {first=true; continue;}
      if(first) {str[i]=toUpperCase(str[i]); first=false;}
      else str[i]=toLowerCase(str[i]);
      str[j  ]=str[i];
    }
    str[j]='';
  }
  

Поскольку удаление пробела не увеличивает длину строки, операцию можно выполнить на месте. Кроме того, я перенес проверку регистра в toUpperCase функцию, чтобы она стала более удобной в использовании. Если сделать ее встроенной, это позволит ускорить реализацию. Я пробовал разные входные данные, например, «cat dog» или «Cat dog», и код всегда выдает вам «CatDog» (регистр Pascal). Логическая переменная first указывает, является ли текущий символ первым после пробела (начало слова, которое должно быть написано с заглавной буквы).

Комментарии:

1. Я только что добавил toLowerCase функцию, гарантирующую, что символы, которые не являются первыми в слове, преобразуются в нижний регистр. Теперь этот код работает для таких входных данных, как «cAt doG». Но в «cat-dog» буква «d» в «dog» не будет заглавной. Вы получите «Cat-dog». Я не уверен, что это нормально для вас.

Ответ №2:

Вот подход, который использует существующие функции, которые уже доступны. Не уверен, что означает «я должен оставаться в функции и не могу создавать новые», надеюсь, это не делает подход недействительным. Выбранная строка должна быть ироничной.

РЕДАКТИРОВАТЬ: как указано cdlane, strlwr это нестандартная функция, которая может быть недоступна. Я добавил альтернативу.

 #include <stdio.h>
#include <stdlib.h>

void str2lower(char *input)
{
    int i=0;
    while (input[i])
    {
        input[i] = tolower(input[i]);
          i;
    }
}

// returns a new string - caller responsible for freeing the memory
char *pascalCase(char *input)
{
    // create a copy of the string, since strtok modifies its input
    char *tmp = strdup(input);
    // any char in this sring will be used to split the input
    const char *delims = " ";

    // get some memory - same length as original string.
    // **this will be too much** we dont need memory for the sapces
    // that will be removed.
    int len = strlen(input);
    char *result = (char*)calloc(len, 1);

    // return a string that contains chars up to the first
    // char found in the delims string
    char *curWord = strtok(tmp,delims);
    while (curWord != NULL)
    {
        // make the whole word lower-case
        //strlwr(curWord);
        str2lower(curWord);

        // capitalize the first letter
        curWord[0] = toupper(curWord[0]);
        // tack it onto the end of our result
        strcat(result, curWord);
        // get the next word
        curWord = strtok(NULL, delims);
    }
    // dont need this anymore
    free(tmp);
    return resu<
}

int main()
{
    // http://www.ee.ryerson.ca/~elf/hack/realmen.html
    char *result = pascalCase("real programmers don't use pascal");
    printf("%sn", result);
    free(result);
}
  

Комментарии:

1. функция strlwr() — это нестандартная функция, которая может быть недоступна в стандартной библиотеке на C

Ответ №3:

Попытка разобраться со всеми спецификациями и сохранить их простыми:

 #include <string.h>
#include <ctype.h>

/* Convert to Pascal case */
/* It is safe to assume that the string is terminated by '' */

void PascalCase(char *string) { // "cat dog" -> "CatDog"

    char *pointer = string;

    while (*pointer != '') {
        if (pointer == string) { // first character in string
            *pointer = toupper(*pointer);
        } else {
            *pointer = tolower(*pointer); // character not beginning a word
        }

        while (*pointer == ' ') {
            (void) memmove(pointer, pointer   1, strlen(pointer)); // remove space from string
            if ((*pointer = toupper(*pointer)) == '') { // capitalize if a letter replaces space
                return; // not documented if memmove() leaves original '' so CYA
            }
        }

          pointer;
    }
}
  

Тест для первого символа в строке был перемещен внутри цикла, чтобы он также выпадал после '' теста, если функции будет передана пустая строка.

Ответ №4:

Было бы проще использовать второй буфер, но вот другой способ сделать это. Создайте два указателя на буфер, а затем перейдите по строке. isspace является стандартной функцией времени выполнения, чтобы увидеть, является ли символ пробелом или нет.

 char word[] = "dog cat";

char* q = word;  // set pointer to buffer, use this for moving string forward
char* p = word;  // finding the non space characters

while (*p amp;amp; *q)
{
  if (isspace(*p))  // skip any spaces
  {
      p;
  }
  else // find non-space, make first one capital then move it
  { 
    *p = toupper(*p); 
    while (!isspace(*p) amp;amp; *p) *q   = *p  ;
  }
}

*q = '';

puts(word);