0

I am well aware that the instructions for this are highly innefficient/almost obsolete. I actually developed a much simpler solution using strings, but for education purposes, my university has decided to make it a requirement that we solve this issue by the use of pointers and char arrays rather than strings.

Basically, I need to pass a predefined char array (a specific phrase) and have it returned reversed.

So far, my output is absolute gibberish (Some characters which I cannot even type here) so I assume I must be doing something very wrong, but I can't see why.

To experiment, I tried to manually assign the *ptr_cha at the end of the function body to be something like "Hello", but then I'm met with type conversion errors. If I manually assign temp[0] to be "hello", and skip out the for cycle and simply say at the end that *ptr_cha[0] is equal to temp[0], I still get gibberish. And if I try to output the contents of clone at the start of the function (after saying it's equal to ptr_cha[0]), it says the contents are "d", a letter which is not even present in the original sentence.

This is my whole code:

#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];
};

As mentioned, the idea is for sentence to be set to its inverted form and displayed in the output.

As an additional, side question: Why is calculating the length of a char array in c++ so complicated/verbose? For strings there's a simple method, here you have to do this whole "trick" of dividing the sizeof the array by the sizeof its reference. I don't even see how the storage size of the array divided by the storage size of its pointer could return the length of the array...

Dasphillipbrau
  • 524
  • 2
  • 8
  • 17
  • try length/2 ... – Ankur Jyoti Phukan Nov 06 '19 at 06:06
  • 1
    You can get length of a char array using [`strlen`](https://en.cppreference.com/w/cpp/string/byte/strlen) – Rahul Goswami Nov 06 '19 at 06:09
  • Initialize `j` with `length - 1`, because of the 0-indexing – Rahul Goswami Nov 06 '19 at 06:12
  • 2
    The code doesn’t really make sense. The array of pointers is not needed. In the function you overwrite the pointer with another. Then you calculate array sizes which don’t mean anything since the array is constant anyway. Then you use those arrays for access and they don’t contain anything of the original string, and have an out of bounds access. You’ll need to remove all the extra stuff, just have an array, and either do swaps if it’s in-place, or allocate a new array and copy if not. – Sami Kuhmonen Nov 06 '19 at 06:14
  • @SamiKuhmonen Where is the array of pointers? Do you mean the *ptr_cha[] in the function's arguments? If I try to just use *ptr_cha, it doesn't compile. This is the only way in which it compiles. The swapping has to happen inside the function, and it has to happen by pointers, those are the requirements of the project. – Dasphillipbrau Nov 06 '19 at 06:19
  • It doesn’t compile if you have wrong arguments. You make the function take a `char*` and give it a `char*` and it’ll compile just fine. – Sami Kuhmonen Nov 06 '19 at 06:20
  • @SamiKuhmonen The error is "invalid conversion"; not the argument. it says it has to receive a char* and it's receiving ptr_cha which is a *. It's been compiling just fine with the code I provided at first, the errors start happening when I try to do stuff like assign clone to be = to *ptr_cha – Dasphillipbrau Nov 06 '19 at 06:31
  • Also I just realized that, apparently, *ptr_sentence = sentence is actually turning my ptr_sentence into a normal array copy of sentence, rather than a pointer to sentence. if I try to use *ptr_cha = &sentence, I get an error stating again, invalid conversion. – Dasphillipbrau Nov 06 '19 at 06:34
  • Show the exact code you’re trying. You don’t need any extra variables. Give the string to the function. Or if you really need it then `char *whatevs; whatevs = sentence; invertChar(whatevs)` will have no errors. – Sami Kuhmonen Nov 06 '19 at 06:47
  • this code will not work because many things are wrong; first sentence var are const char* so you can't modify its content you must make a duplicate using for example strdup() ; also tmp and clone are points to const char data; – Ahmed Anter Nov 06 '19 at 10:33
  • length var will be zero because sizeof(clone) is zero – Ahmed Anter Nov 06 '19 at 10:34

1 Answers1

1

Let me break down what's happening in each step. If you're using an IDE I highly recommend you to debug your program and see what's happening in each step. (In your code I assumed that you wanted to reverse 'sentence' and not return a copy of its reversed version.)

wchar.h and array are not used here, you can just delete those lines. Other than that, you shouldn't pass a character string to a function like that. See this how to do properly.

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

using namespace std;

void invertChar(char *ptr_cha[]);

Here, you should just pass sentence to invertChar, ptr_sentence is unnecessary and strange (char* ptr_sentence would be enough because now it's an array that contains pointers to chars and you store the address of sentence in its first slot).

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[] =  {""};

You are assigning clone to ptr_cha[0], now ptr_cha[0] is referencing clone and not to sentence. At this point you cannot reach sentence.

   ptr_cha[0] = clone;

The first line below would be more descriptive written like this: int length = sizeof(clone) / sizeof(clone[0]). This divides the size of clone with the size of its first element, basically giving you the number of elements clone has. It's important to divide by the element size because what if clone uses something to store characters that isn't 1 byte long like char. You can get the number of elements of any array with this trick.

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

Remember that both temp and clone are empty strings, more precisely they have 1 element and that's the \0 character that indicates the end of the string. In the first run of the loop you are doing this: temp[0] = clone[1] but clone doesn't have a second element (index 1). At this point you are accessing something that's out of the array and assigning it to temp where it gets interpreted as a char, resulting in some "gibberish".

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

Overall, I would recommend you to look into pointers and how they are working because they can be a little tricky and confusing.


Working C(++) implementation:

#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++ implementation just for comparison:

#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;
}
Doeus
  • 430
  • 1
  • 3
  • 7
  • Thanks a lot for your help mate. I'm currently reading more about pointers and I've been seeing all of my errors, your code really helps! – Dasphillipbrau Nov 07 '19 at 15:34
  • One more thing that I forgot to mention and maybe shed some light ("-->" means "points to"): `sentence` --> `"Pablito..."` `ptr_sentence` --> `sentence` --> `"Pablito..."` You see, what you want to achieve is to have something that points to `"Pablito..."` and not to `sentence` because you want to modify `"Pablito..."` and not the value of `sentence` (that is basically the **memory address** of the first `char` of `"Pablito"`). If you really need a pointer to the string `"Pablito..."` you could do that like this: `char* ptr_sentence = sentence`. – Doeus Nov 07 '19 at 16:07