-1

I am practicing c++ and this code is supposed to copy an array to another array.output types are character and which is passed by pointer through the function 'f'. my output type is pointer which is pointing to a char array.here is my code:

using namespace std;
void f(char*, char*);
int main()
    {
    char *a1;
    char a2[] = "1234";

    f(a1, a2);
    cout << a1<< endl;
    return 0;

    }

void f(char *a, char *b)
    {
    int len;
    len = sizeof(b) / sizeof(b[0]);
    a = new char[len];
    for (; (*a=*b )!= '\0'; a++, b++)
    cout<<*a<<endl;

    for (int i=0;i<4;i++)
    cout<<a[i]<<endl;
    }
  1. in the function each time for loop runs 'a' elements changes to the unreadable value. at first, it shows right value and then it changes. for example, in the first loop inside the function, it prints right value of 'a' but in second loop it changes it for no reason!
  2. this function doesn't return any value. as I expect by calling by pointer it has to change the variable but nothing happens. deep explanation is appreciated. I am completely new in c++ programming.
Hamid Reza
  • 492
  • 1
  • 4
  • 14
  • Inline 9th its cout << a1<< endl; – Hamid Reza Sep 04 '19 at 08:05
  • If you are completely new to C++ and programming in general, it is advisable to use `std::vector` (or rather `std::string` as in this case) rather than raw manually allocated arrays. There is seldom a reason to use manual memory allocation. – walnut Sep 04 '19 at 08:06
  • Possible duplicate of [sizeof char\* array in C/C++](https://stackoverflow.com/questions/12353973/sizeof-char-array-in-c-c) – walnut Sep 04 '19 at 08:08
  • Several mistakes here, all of which could be avoided if you started practicing "real" (aka. modern) C++ instead of C. In short: stop using `char*` for strings and start using `std::string` instead. Copying them is as simple as copying an `int`. – sebrockm Sep 04 '19 at 08:10
  • can you tell me my mistakes here or correct them, please? I am following a tutorial and I change the code a little bit. but now I am confused. u mean that I shouldn't use char*?why? – Hamid Reza Sep 04 '19 at 08:17
  • You can't change the value of `a1` in `main` by passing its value to `f`. Assigning to a (non-reference) parameter has no effect outside the function. There is nothing special about pointers. – molbdnilo Sep 04 '19 at 08:21
  • @HamidReza null-terminated C strings (`char*`) come from the C language, which C++ is based on, but C++ has many facilities that C doesn't and that are safer/cleaner to use, especially if you are new to this. There is rarely a reason to use a null-terminated C string over `std::string` in C++. See [the definitive C++ book guide](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) for recommendations of better learning material. – walnut Sep 04 '19 at 08:23
  • Also, `sizeof(b) / sizeof(b[0])` is the same as `sizeof(char*) / sizeof(char)`, which will be either four or eight. – molbdnilo Sep 04 '19 at 08:24

2 Answers2

1

Without changing the basic style of your code, here is a fixed version, with comments:

#include <iostream>

using namespace std;
void f(char**, char*); // You need to pass a pointer to the pointer!
void f2(char*&, char*); // Alternative passing the pointer by reference
int main()
{
    char* a1;
    char a2[] = "1234";

//  f(&a1, a2);     // Pass the address of the 'a1' pointer
    f2(a1, a2);     // a1 pointer is now passed by reference
    cout << a1 << endl;
    delete a1[]; // Here, we free the memory allocated by the new call!
    return 0;
}

void f(char** a, char* b)
{
    int len;
//  len = sizeof(b) / sizeof(b[0]); // You can't get the array length like this!
    len = strlen(b); // Assuming your string is null-terminate!
    *a = new char[len + 1]; // Make room for the null terminator!
    // Make a copy of the pointer (atemp) - otherwise you are changing the address of the new character
    // array you just created - and this will then fail in the 2nd loop ...
    for (char* atemp = *a; (*atemp = *b) != '\0'; atemp++, b++)
        cout << *atemp << endl;

    for (int i = 0; i < len; i++) // Length won't always be 4!
//  for (int i = 0; i < 4; i++)
        cout << (*a)[i] << endl;
}

void f2(char*& a, char* b)
{
    size_t len = strlen(b); // Assuming your string is null-terminate!
    a = new char[len + 1];
    for (char* atemp = a; (*atemp = *b) != '\0'; atemp++, b++)
        cout << *atemp << endl;

    for (int i = 0; i < len; i++) // Length won't always be 4!
        cout << a[i] << endl;
}

Feel free to ask for more details about why the changes were made!

EDIT: Added alternative using argument as a reference.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • 1
    Incidentally, I agree with many of the comments here about the 'bad style'. However, this is a beginner who is exploring the workings of C/C++, so lets try to be helpful, and point out the errors and why they are errors. It's called learning/teaching. – Adrian Mole Sep 04 '19 at 08:49
  • thx for answer, u passed the varibale with refrence. cant wi pass the varibale with pointer? u used '&' .. my problem is why this code works?main(){char *s1;char *s2="ali";f1(s1,s2);cout< – Hamid Reza Sep 04 '19 at 09:16
  • @HamidReza `&` has multiple meanings in C++, depending on context. Because it is not part of a type name in this case, it means `take the address of the variable`. It has nothing to do with C++ references and works the same in C which doesn't have references. Your tutorial should have covered that before. – walnut Sep 04 '19 at 09:19
  • @Hamid Reza - Yes, you could use a *reference* to the pointer in place of a pointer to it! Just wasn't sure if you had come across reference arguments, yet. In fact, reference makes the code a bit simpler (but it probably compiles down to very similar code). – Adrian Mole Sep 04 '19 at 09:19
  • @klaus may u chek my edited comment? why does that code work? it is my real problem. because I change a bitthis learning code. – Hamid Reza Sep 04 '19 at 09:21
  • 1
    @HamidReza That code doesn't work. There will not be a compilation error (but maybe a warning), but it will cause undefined behavior because you are using the uninitialized (indeterminate) value of `s1` in `f`, even dereferencing it. If it happens to print something, that is pure coincidence. – walnut Sep 04 '19 at 09:22
0

A lot of mistakes in your program:

void f(char *a, char *b)
{
    len = sizeof(b) / sizeof(b[0]);

b is a pointer to char. As this it has the pointer size of the machine type, typically it is 32 or 64 bit. So you never get the size of the array!

If you really want to pass a raw pointer to char to a function and want to handle the data stored at the position where the pointer points to, you have either to pass also the size ( number of elements ) or you have to know an end mark. In case of a c-sytle string you have a '\0' at the end of the string which makes it possible to use it.

So you have first to count the number of elements until '\0' is reached, allocate a new array, copy the elements and than return the pointer.

Next failure: If you allocate memory with new, you have to use delete later in your program.

But: What you did is bad sytle C code! It has really nothing todo with C++ nor with good C. There is no need to write a own string copy function as there is already strcpy and strlen to get the size.

In C++ your code can be something like that:

void f( const std::string& src, std::string& target )
{
    target = src;
}

int main()
{
    std::string a2{"abcd"};
    std::string a1;
    f( a2, a1 );
    std::cout << a1 << std::endl;
}
Klaus
  • 24,205
  • 7
  • 58
  • 113
  • I thought when we define a variable in the function it doesn't need to be deleted. because they are local. so, how can I delete a function variable which I located memory to it? if I delete it in the function it doesn't return any output. – Hamid Reza Sep 04 '19 at 09:07
  • @HamidReza The variable defined in a function is deleted automatically, right! But this is only the pointer and not the manually allocated memory which address is stored iStop via EndlessLoopBreakern that pointer! So you have to delete the memory which you allocated, not the pointer which points to that memory. – Klaus Sep 04 '19 at 09:11