Проблемы с возвращением массива char с C ++ через указатели - PullRequest
0 голосов
/ 06 ноября 2019

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

По сути, яМне нужно передать предопределенный массив символов (конкретную фразу) и вернуть его в обратном порядке.

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

Чтобы экспериментировать, я попытался вручную присвоить * ptr_cha в конце тела функции что-то вроде "Hello", но затем я встретился сошибки преобразования типов. Если я вручную назначу temp [0] значение «hello», пропущу цикл для и просто скажу в конце, что * ptr_cha [0] равен temp [0], я все равно получу бред,И если я пытаюсь вывести содержимое clone в начале функции (после того, как оно говорит, что оно равно ptr_cha [0]), оно говорит, что содержимое - это «d», буква, которой даже нет в исходном предложении.

Это весь мой код:

#include <iostream>
#include <wchar.h>
#include <locale.h>
#include <array>

using namespace std;

void invertChar(char *ptr_cha[]);

int main()
{
   setlocale(LC_ALL, "");
   char sentence[] {"Pablito clavó un clavito que clavito clavó Pablito"};
   char *ptr_sentence[] {nullptr};
   *ptr_sentence = sentence;
   invertChar(ptr_sentence);
   cout << ptr_sentence[0];
};

void invertChar(char *ptr_cha[]) {
   char clone[] = {""};
   char temp[] =  {""};
   ptr_cha[0] = clone;
   int length = sizeof(clone)/sizeof(*clone);
   int j = length;
   for(int i = 0; i < length; i++) {
    temp[i] = clone[j];
    j--;
   };
   *ptr_cha[0] = temp[0];
};

Как уже упоминалось, идея состоит в том, чтобы предложение было установлено в его инвертированную форму и отображалось в выходных данных.

В качестве дополнительногоДополнительный вопрос: почему вычисление длины массива char в c ++ настолько сложно / многословно? Для строк есть простой метод, здесь вы должны проделать весь этот «трюк» деления размера массива на размер его ссылки. Я даже не вижу, как размер хранилища массива, деленный на размер хранилища его указателя, мог бы вернуть длину массива ...

1 Ответ

1 голос
/ 06 ноября 2019

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

wchar.h и array здесь не используются, вы можете просто удалить эти строки. Кроме этого, вы не должны передавать символьную строку такой функции. См. this , как это сделать правильно.

#include <iostream>
#include <wchar.h> // Not used.
#include <locale.h>
#include <array> // Not used.

using namespace std;

void invertChar(char *ptr_cha[]);

Здесь вам нужно просто передать sentence в invertChar, ptr_sentence не нужно и странно (char* ptr_sentence будет достаточнопотому что теперь это массив, содержащий указатели на char s, и вы сохраняете адрес sentence в его первом слоте).

int main()
{
   setlocale(LC_ALL, "");
   char sentence[] {"Pablito clavó un clavito que clavito clavó Pablito"};
   char *ptr_sentence[] {nullptr};
   *ptr_sentence = sentence;
   invertChar(ptr_sentence);
   cout << ptr_sentence[0];
};

void invertChar(char *ptr_cha[]) {
   char clone[] = {""};
   char temp[] =  {""};

Вы присваиваете clone ptr_cha[0], теперь ptr_cha[0] ссылается на clone, а не на sentence. На данный момент вы не можете достичь sentence.

   ptr_cha[0] = clone;

Первая строка ниже будет более наглядной, например: int length = sizeof(clone) / sizeof(clone[0]). Это делит размер clone на размер его первого элемента, в основном давая вам количество элементов clone. Важно делить на размер элемента, потому что, если clone использует что-то для хранения символов длиной не более 1 байта, например char. С помощью этого трюка вы можете получить количество элементов любого массива.

   int length = sizeof(clone)/sizeof(*clone);
   int j = length;
   for(int i = 0; i < length; i++) {

Помните, что и temp, и clone - пустые строки, точнее, они имеют 1 элемент, и это символ \0это указывает на конец строки. При первом запуске цикла вы делаете это: temp[0] = clone[1], но clone не имеет второго элемента (индекс 1). В этот момент вы получаете доступ к чему-то вне массива и присваиваете ему temp, где оно интерпретируется как char, что приводит к некоторому «бреду».

    temp[i] = clone[j];
    j--;
   };
   *ptr_cha[0] = temp[0];
};

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


Рабочая реализация C (++):

#include <iostream> // cout
#include <locale.h> // setlocale
#include <string.h> // strlen

void reverse(char* string)
{
    // Check whether our pointer really points to something or not.
    if (string == nullptr) return;

    // 'strlen' returns the size of a '\0' terminated character sequence (including the '\0').
    // We subtract 1 from the length because we don't want to swap the terminating
    // '\0' character with the first one.
    const int length = strlen(string) - 1;
    for (int i = 0, j = length; i < j; ++i, --j) {
        const char temp = string[i];
        string[i] = string[j];
        string[j] = temp;
    }
}

int main()
{
    setlocale(LC_ALL, "");
    char sentence[] = "Pablito clavó un clavito que clavito clavó Pablito";
    reverse(sentence);
    std::cout << sentence << '\n';
    return 0;
}

C ++реализация только для сравнения:

#include <algorithm> // reverse
#include <iostream> // cout
#include <locale> // locale, locale::global
#include <string> // string

void reverse(std::string& string)
{
    std::reverse(string.begin(), string.end());
}

int main()
{
    std::locale::global(std::locale(""));
    std::string sentence = "Pablito clavó un clavito que clavito clavó Pablito";
    reverse(sentence);
    std::cout << sentence << '\n';
    return 0;
}
...