Ошибка C ++ – возврат массива char

Рассмотрим следующий код:

char CeaserCrypt(char str[256],int key) { char encrypted[256],encryptedChar; int currentAsci; encrypted[0] = '\0'; for(int i = 0; i < strlen(str); i++) { currentAsci = (int)str[i]; encryptedChar = (char)(currentAsci+key); encrypted[i] = encryptedChar; } return encrypted; } 

Visual Studio 2010 дает ошибку, потому что функция возвращает массив. Что я должен делать?

Мой друг сказал мне изменить подпись на void CeaserCrypt(char str[256], char encrypted[256], int key) . Но я не думаю, что это правильно. Как я могу избавиться от ошибки компиляции?

Тип возврата должен быть char * но это добавит еще одну проблему.

encrypted «выделено» в стеке CeaserCrypt и может быть недействительным при возврате функции. Так как encrypted будет иметь такую ​​же длину, как и вход, выполните:

 int len = strlen(str); char *encrypted = (char *) malloc(len+1); encrypted[len] = '\0'; for (int i = 0; i < len; i++) { // ... } 

Однако не забудьте освободить буфер позже (с помощью free() ).

EDIT: @Yosy: не чувствуйте себя обязанным просто копировать / вставлять. Используйте это как указатель для улучшения вашей практики кодирования. Кроме того, чтобы удовлетворить критику: передайте уже выделенный указатель на вашу процедуру шифрования, используя приведенный выше пример .

Он хочет, чтобы вы вернули char *, а не char. Независимо от того, вы не должны возвращать ссылку или указатель на то, что вы создали в стеке. Вещи, выделенные в стеке, имеют срок службы, соответствующий их объему . После окончания области действия эти переменные стека могут уходить.

Верните std :: vector вместо массива.

 std::vector CeaserCrypt(char str[256],int key) { std::vector encrypted(256); char encryptedChar; int currentAsci; encrypted[0] = '\0'; for(int i = 0; i < strlen(str); ++i) { currentAsci = (int)str[i]; encryptedChar = (char)(currentAsci+key); encrypted[i] = encryptedChar; } return encrypted; } 

Там есть еще одна тонкая проблема: вы бросаете целое число в значение символа. Максимальный размер int намного больше, чем символ, поэтому ваш бросок может урезать значение.

Поскольку вы используете C ++, вы можете просто использовать std::string . Но в противном случае то, что предложил ваш друг, вероятно, лучше всего.

Здесь есть несколько проблем. Сначала:

 char CeaserCrypt(char str[256],int key) 

Как указывали другие, ваш тип возврата неверен. Вы не можете вернуть в один символ весь массив. Вы можете вернуть char* но это возвращает указатель на массив, который будет размещен локально в стеке, и поэтому будет недействительным после удаления кадра стека (после функции в основном). На английском вы будете получать доступ к этому адресу памяти, но кто знает, что там будет …

Как сказал ваш друг, лучшей подписью будет:

 void CeaserCrypt(char* encrypted, const char str*, const size_t length ,int key) 

Я добавил несколько вещей – длину size_t чтобы вы могли обрабатывать любую длину. Таким образом, размер str может быть определен по мере необходимости. Просто убедитесь, что char* encrypted имеет тот же размер.

Тогда вы можете сделать:

 for(int i = 0; i < length; i++) { // ... 

Для этого вашему абоненту потребуется выделение буферов соответствующего размера той же длины, длина которых должна быть указана в параметре длины. Посмотрите malloc для C. Если C ++, используйте std::string .

Если вам нужна совместимость с C, сделайте зашифрованный аргумент строковой функции. Если нет, используйте C ++ std :: string вместо строки стиля C.

А также в вашем коде зашифрованная строка не заканчивается на ‘\ 0’

Проблема с исходным кодом заключается в том, что вы пытаетесь вернуть указатель char* (к которому ваш локальный массив распадается) от функции, которая прототипирована как возвращающая char . Функция не может возвращать массивы в C, а также в C ++.

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

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

 int func(char array[256]); int func(char* array); 

OTOH, вы должны (если можете!) Выбрать язык, который вы используете. Лучшая версия оригинала (в C ++).

 std::vector CeaserCrypt(const std::string& str, const int key) { std::vector encrypted(str.begin(), str.end()); for (std::vector::iterator iter = vec.begin(); iter != vec.end(); ++iter) { *iter += key; } return vec; } 

Обратите внимание, что переполнение целого числа со знаком приводит к неопределенному поведению .

VS2010 «кричит» на вас, потому что вы пытаетесь вернуть значение, выделенное в стеке, и больше не действует после вызова функции.

У вас есть два варианта: 1) выделить память в куче внутри вашей функции или 2) использовать память, предоставленную вам вызывающим абонентом. Номер 2 – это то, что ваш друг предлагает и очень хороший способ сделать что-то.

Для 1 вам нужно вызвать malloc() или new зависимости от того, работаете ли вы на C или C ++. В C у меня было бы следующее:

 char* encrypted = malloc(256 * sizeof(char)); 

Для C ++, если вы не хотите использовать строку, попробуйте

 char* encrypted = new char[256]; 

Edit : facepalm Извините за шум C, я должен был внимательно рассмотреть вопрос и понял, что вы работаете на C ++.

Вы можете просто сделать свой шифр Ceaser на месте, не нужно передавать массивы туда и обратно.

 char * CeaserCrypt(char str[256], int key) { for(unsigned i = 0; i < strlen(str); i++) { str[i] += key; } return str; } 

В качестве дальнейшего упрощения пропустите возвращаемое значение.

 void CeaserCrypt(char str[256], int key) { for(unsigned i = 0; i < strlen(str); i++) { str[i] += key; } } 

ну, что вы возвращаете, это не символ, а массив символов. Попробуйте изменить тип возврата на char * (char * и массив char, якобы, то же самое для компилятора)

 char* CeaserCrypt(char str[256],int key) 

EDIT: как сказано в других сообщениях, зашифрованный массив, вероятно, не будет действителен после вызова функции. вы всегда можете сделать новое объявление [] для шифрования, не забывая удалить его позже.