2013-10-10 4 views
0

Я пишу собственную реализацию ToLower (char * str) в C. Но я получаю ошибку сегментации в функции. Функция, которую я написал, это:Реализация функции ToLower в C

void ToLower(char *str) 
{ 
    while(*str != '\0') 
    { 
     if(*str >=65 && *str<=90) 
     { 
      // It fails in the below assignment 
      *str = *str + 32; 
     } 
     str++; 
    } 

} 
+9

Как вы называете это? Если вызывается с постоянной строкой - 'ToLower (" foo ")' - это должно завершиться неудачно. –

+0

Вы называете его нулевой завершаемой строкой? –

+5

Не ответ на ваш вопрос, но зачем использовать '65' и' 90', когда '' A'' и '' Z'' доступны и смысл понятнее? –

ответ

3

Обычно считается хорошей формой для принятия параметра длины в функциях, работающих на строках. Таким образом, если вы передадите строку, которая не завершена нулем, функция не будет зацикливаться на конце ввода.

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

+1

«Обычно считается хорошей формой, чтобы принять параметр длины в функциях, которые работают с строками» Говорит кто? Это имеет смысл при манипулировании данными из ненадежного источника, но это вызывает программный шаблон и произвольные ограничения во многих случаях, поскольку это полезно. –

+1

Он реализует tolower(), который принимает один аргумент и модифицирует аргумент. –

+1

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

9

Вы почти наверняка неудача, когда вы называете его, как:

int main(void) 
{ 
    ToLower("HelloWorld"); 
    return 0; 
} 

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

Попробуйте вместо этого:

int main(void) 
{ 
    char str[] = "HelloWorld"; 

    // Now str is your own local buffer, that you can modify. 
    // It is initialized with the text, but that text can be changed. 
    ToLower(str); 
    return 0; 
} 
-2

для безопасных переменных вы можете использовать следующий прототип:

void ToLower(const char *str) 
+0

tolower() по определению изменяет данную строку на месте. –

+0

О, у меня нет его тела, да, вы говорите правильно, но это небезопасно, ваша примитивная строка должна быть изменена ... – PersianGulf

+0

@CharlieBurns - 'tolower()' Я знаком с принимает один символ, и возвращает один символ, обычно с чем-то вроде 'int tolower (int chr);' как прототип. – ryyker

0

Хотя название вашей функции ToLower() предлагает вам переписывание версии ANSI C из tolower() , (т. е. изменение одного символа от верхнего к нижнему регистру), ваша реализация предполагает, что вы действительно хотите, чтобы вся строка была изменена. Возможно, имя StrToLower() - это то, что вы действительно намереваетесь? (т. е. изменить всю строку). Если это так, иллюстрируется следующий код. (Если вы действительно хотите, чтобы повторно написать tolower(), это должно быть действительно другой вопрос, с прототипом аналогичной версии C, и меняется только один символ за звонок)

Этот ответ предполагает из тега «с «в вашем вопросе, что вам не нужна версия .NET String.ToLower() (которая преобразует строку). Если это неправильное предположение, пренебрегайте моими тиражами.

Этот метод будет работать с char *str="STRING"; или с постоянной строкой ("STRING") в качестве аргумента.
[расширенный] Включите реализацию ToLower, в случае, если это действительно нужно OP.

#include <stdio.h> 
char * StrToLower(char *str) ; 
int toLower(int chr); 

int main(void) 
{ 
    char lowered[] = "UPPER to Lower"; 

    sprintf(lowered, "%s",StrToLower(lowered)); 
    printf("%s\n", lowered); //works with a variable buffer argument 

    lowered[0]=0;//clear the buffer 

    sprintf(lowered, "%s",StrToLower("UPPER to Lower")); 
    printf("%s\n", lowered); //also works with a literal string argument 

    getchar();//view results 
    return 0; 
} 

char * StrToLower(char *str) 
{ 
    char *pNew1 = str; 
    char *pNew2 = str; 

    if(str != NULL) //NULL ? 
    { 
     if(strlen(str) != 0) //"" ? 
     { 
      while(*pNew1) 
      { 
       *pNew2 = toLower(*pNew1); 
       ++pNew2; 
       ++pNew1; 
      } 
      *pNew2 = '\0'; 
      return str;// return changed string 
     }    // and prevent returning null to caller 
    } 
    return "";//Will never get here for non-null input argurment 
} 

int toLower(int chr)//touches only one character per call 
{ 
    return (chr >='A' && chr<='Z') ? (chr + 32) : (chr);  
} 

Результаты: (ответ на комментарий Роланда)
enter image description here

+0

Ваш код * не * работает при вызове с строковым литералом. Кроме того, что такое ''? И почему вы возвращаете '' ''из StrToLower? А как насчет наборов символов, где между буквами «A» и «Z» нет букв? –

+0

@RolandIllig - *** 1) *** Я просто проверил его _does_ работу при вызове с строковым литералом, точно так же, как это было год назад, до тех пор, пока строковый литерал не перезаписывает размер исходного буфера 'lowered '. *** 2) *** Я возвращаю '' '' в случае, если в функцию передан пустой аргумент. Если нет, поток выполнения никогда не доходит. *** 3) *** anci_c.h - сборщик заголовков ANSI C, который я использовал. Полагаю, если вам действительно нужно было найти вопрос с моим ответом, это было бы так. Вы можете избавиться от использования stdio.h на своем месте с помощью этого конкретного примера. (который я редактировал в примере) – ryyker

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