Символы, вырезанные из «пользовательского» оператора toupper в C - PullRequest
1 голос
/ 04 марта 2020

Я впервые пишу на C, и мне нужно написать код, который выполняет верхний уровень строки, фактически не используя верхний. Я сделал это, однако он работает только до 8 символов по какой-то причине .... ----- Вот вход: Привет привет привет привет ----- Вот вывод: Копия: привет привет привет привет ; ▒ Строка с большой буквы - HELLO HEp▒▒▒ Оригинальная строка привет привет привет привет

#include <stdio.h>

int strLength(char* str){
     int count;
     for(count=0;str[count] != '\n';count++){}
     return count;
}

char* copyStr(char* str,char* str2){
     for(int i=0;str[i] != '\n';i++){
          char n = str[i];
          str2[i] = n;
     }
     str2[strLength(str)] = '\n';
     return str2;
}

char* upper(char* str){
     char str2[100];
     for(int i=0;str[i] != '\n';i++){
         int current = str[i];
         if((current >= 97) && (current <= 122)){
              char new = str[i];
              str2[i] = new-32;
          }
          else{
               str2[i] = current;
          }
    }
    char* str3 = str2;
    return str3;
}

int main(int argc, char **argv){
     char input[100];
     char inputcopy[100];

     //get the input string
     printf("Enter string: ");
     fgets(input, 100, stdin);

     copyStr(input,inputcopy);
     printf("Copy: %s\n", inputcopy);
     printf("The capitalized string is %s\n",upper(inputcopy));
     printf("The original string is %s",input);
}

1 Ответ

2 голосов
/ 04 марта 2020

Очевидные проблемы:

  • не NUL, завершение копирования в copyStr
  • возвращение указателя на локальную переменную в upper

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

Итак, чтобы " Чтобы вернуть строку из функции, вы должны фактически вернуть указатель на то, что имеет время жизни, которое продолжается после того, как функция вернулась (что означает, что она не может быть указателем на локальный переменный функции). Как правило, есть три способа устроить это:

  1. передать указатель на то, куда поместить результирующую строку в качестве дополнительного аргумента (это то, что вы делаете с вашей функцией copyStr)
  2. используйте mallo c, чтобы выделить динамическое c пространство для строки и вернуть указатель на нее.
  3. вернуть указатель на строку c (global).

У каждого из них есть свои недостатки:

  1. вызывающий должен знать, какой большой размер строки будет возвращен (чтобы создать объект, на который он передал указатель) перед ним даже делает звонок. Часто это невозможно или требует выделения большой строки в «наихудшем случае», или существует опасность переполнения буфера (вызывающего UB). По крайней мере, вам часто требуется второй дополнительный аргумент для указания размера буфера.
  2. Вызывающая сторона должна «взять на себя ответственность» за возвращенную память и убедиться, что она освобождается должным образом. Это становится частью неявного контракта между вызывающей и вызываемой сторонами, но часто не документируется, поэтому является общим источником утечек памяти
  3. Все вызовы, как правило, совместно используют один и тот же статус c global, поэтому он не является повторно входящим или потоком -безопасно.
...