#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);
}
Комментарии:
Ответ №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);