Passing pointer to dynamic array? making function modular...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include<iostream>
using namespace std;

char *Decrypt(const char secret_code[], int a_key);
void Output(char cleartext[]);       

int main()
{
	const char codeA[] = ":mmZ\\dxZmx]Zpgy";
	const char codeB[] = "\\Y``c4kcf`X";
	int key;
	int i;
	char *clear_text_main; //pointer will point to array

	cout << endl << " Decrypting Code A:     " << codeA << endl << endl;
	int array_len = sizeof(codeA)/sizeof(char);   
// needed to establish size for Output function. How to pass clear_text_main into output as an array. This is the goal. That way I will not need to determine the size in main. 
//Otherwise establish size from an argument from main and within Output() iterate through clear_text using pointer arithmetic. This is not how I want to do it.

	for(key = 1; key < 101; key++)            

	{
		clear_text_main = Decrypt(codeA, key);
		Output(clear_text_main);
	}

	

	return 0;

}


//Please note decrypt function is how I want it
char *Decrypt(const char code[], int key)
{
	const int array_length = sizeof(code)/sizeof(char);              //division by sizeof(char) to be explicit division by 1
	char *clear_text;
	clear_text = new char[array_length];

	for(int i = 0; i < array_length; i++)
	{
		if (code[i] + key > 126)
		{																	     
		clear_text[i] = 32 + ((code[i] + key)-127)					
		}																	
		else															
		{
			clear_text[i] = code[i] + key;									
		}																		
																			
	}

	return clear_text;
}


void Output(char clear_text[])
{
	const int array_len = sizeof(clear_text)/sizeof(char);

	for(int i = 0; i < array_len; i++)
	{
		cout << clear_text[i];
	}
	cout << endl;
}




What I want to do is make the Output function modular. I want the output function to identify the length of the array passed to it and output that number of characters. I am having issues because Decrypt() returns my pointer, then I don't know how to send that pointer to the Output() function and have it recognized as an array. The sizeof operator recognizes it as a single variable how can I fix this problem. What do I have to do to make Output modular. I understand I could do the output within main. But I want to make a modular Output function.


I hope someone can help me with this. Or explain an alternative that I would like. Thanks.
You have three solutions.

1) pass the length into Output also;
2) use templates
3) use an STL container such as vector<> instead of arrays.

What's your preference?

EDIT: No, in your case you have only two options. Scratch #2 up there.
Last edited on
Will number 3 work? Because I have no experience in how to return a vector.....So this is not possible in the way I have it set up there is not a way to do this while having Output() get the length and stand by itself? If I were to pass the length into output() am I correct in saying I would iterate through the dynamic array using pointer arithmetic?
SO maybe that last bit didn't make sense. I think I just don't understand pointers well enough at this point to do what I am trying to do...... I scraped the output function and deleted some comments. The new comments I put it explain my issues on a more basic level. At this point I want to make a new Output() function that will be modular and can find the size of the array itself. I need to be able to pass the pointer to the function and have it behave like an array. and I'm not sure the best way to do this. Any help would be great. Thanks


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include<iostream>
using namespace std;

char *Decrypt(const char secret_code[], int a_key);    

int main()
{
	const char codeA[] = ":mmZ\\dxZmx]Zpgy";
	const char codeB[] = "\\Y``c4kcf`X";
	int key;
	char *clear_text_main; //pointer will point to array

	cout << endl << " Decrypting Code A:     " << codeA << endl << endl;
	
	for(key = 1; key < 101; key++)           
	{
		clear_text_main = Decrypt(codeA, key); // Pointer is returned here and set equal to another point correct? SO why doesn't the clear_text_main pointer behave like an array??
	}

	return 0;

}



char *Decrypt(const char code[], int key)
{
	int array_length = sizeof(code)/sizeof(char);              //division by sizeof(char) to be explicit division by 1
	char *clear_text;
	clear_text = new char[array_length];

	for(int i = 0; i < array_length; i++)
	{
		if (code[i] + key > 126)
		{																	     
			clear_text[i] = 32 + ((code[i] + key) - 127);					
		}																	
		else															
		{
			clear_text[i] = code[i] + key;									
		}																		
																			
	}

	return clear_text; // returns pointer to array. Why doesn't this behave like an array after this function?
}



Pointers are not arrays.

 
int array_length = sizeof(code)/sizeof(char);              //division by sizeof(char) to be explicit division by 1 


This doesn't work because 'code' is a pointer (read: not an array). Therefore sizeof(code) is returning sizeof(char*), which is probably 4. It does not return the size of the array.

There is no way to tell the size of the array with just a pointer to it. It is not possible in C++. As jsmith said, you have those 3 options.

Of course since these are strings... you could just save yourself the hassle and use std::string instead of char arrays.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
string Decrypt(string code,int key)
{
    for(int i = 0; i < code.length(); ++i)
    {
        if(code[i] + key > 126)
        {
            code[i] = 32 + ((code[i] + key) - 127);
        }
        else
        {
            code[i] = code[i] + key;
        }
    }
    return code;
}


Much simpler, don't you think?



EDIT:

actually since these are C strings you can use strlen to get the length of the string.. assuming 'code' is null terminated and doesn't use nulls anywhere else in the string:

1
2
3
4
5
6
7
8
9
10
int array_length = strlen(code);
char* clear_text = new char[ array_length + 1 ];  // +1 for the null terminator

for(...)
{
...
}

clear_text[array_length] = 0;  // don't forget to terminate the string
return clear_text;


But this is bad becase now you have to remember to delete[] the returned value otherwise you'll get a memory leak.

Just use std::string. Much less of a hassle.
Last edited on
code is an array actually. There is no problem with the decrypt function. The decrypt function does everything I need it to in the way I want it to.

As for number one 1) pass the length into Output also; I just didn't want to do that because I am shooting for modularity. I thought to use strings, but I didn't want to make it too easy on myself, and I wanted to incorporate pointers. I also wanted to incorporate dynamic memory to practice new and delete. The issue I am having is sending the returned pointer from Decrypt() into another function which will then calculate the c-string length does your statement "here is no way to tell the size of the array with just a pointer to it." hold true even using strlen?

given that I return the pointer to the array from decrypt() what will C++ allow me to do with this pointer withing main or another function that it may be passed into.


Edit: Also is there a way to return an entire array? If there is it wouldn't be efficient, but it's something I would like to know that could solve my problem.
Last edited on
code is an array actually.


No, code is NOT an array. It is a pointer.

does your statement "here is no way to tell the size of the array with just a pointer to it." hold true even using strlen?


strlen() just checks for a '\0' character and assumes that is the end of the C string, so if you had a C string like this:
'a' 'b' '\0' 'c' 'd' '\0'

Then strlen() would return 2, which is incorrect in this case. That's why you should just use std::string.

Edit: Also is there a way to return an entire array? If there is it wouldn't be efficient, but it's something I would like to know that could solve my problem.


No, you can only return/pass pointers to arrays.
code is an array actually


No, it actually is a pointer.

There is no problem with the decrypt function. The decrypt function does everything I need it to in the way I want it to.


Maybe you just haven't tested enough. sizeof(a_pointer) never gives you the size of the array.

As for number one 1) pass the length into Output also; I just didn't want to do that because I am shooting for modularity.


That is modular. It's a little extra work, yeah, but it's definately modular.

I thought to use strings, but I didn't want to make it too easy on myself


That's a silly reason, but okay.

The issue I am having is sending the returned pointer from Decrypt() into another function which will then calculate the c-string length does your statement "here is no way to tell the size of the array with just a pointer to it." hold true even using strlen?


Well you problem here, then, is that your string isn't null terminated.

strlen just steps through the string looking for the null character. It stops when it finds it.

This is not the same thing as returning the size of the array, since the size of the array may be larger than the actual string length (or shorter, if you screwed up and corrupted memory).

Try this out once:

1
2
3
4
5
6
7
8
9
char foo[100] = "A test, baby";

cout << strlen(foo) << endl;  // outputs 12
cout << sizeof(foo) << endl;  // outputs 100

char* ptr = foo;

cout << strlen(ptr) << endl;  // outputs 12 (length of the string)
cout << sizeof(ptr) << endl;  // outputs 4 or 8 (size of a pointer -- not the size of the array) 


note that strlen works ONLY if the string ends with a null terminator.

Your 'clear_text' array does not necessarily end in a null terminator because you never gave it one. Do this:

1
2
3
4
clear_text[array_length] = 0;  // don't forget to terminate the string

// then you can return clear_text
return clear_text;


But of course then:
1) you have to allocate array_length+1 characters (+1 for the null)
2) you have to fix your array_length problem (use strlen instead of sizeof)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include<iostream>
#include<cstring>
using namespace std;

string Decrypt(const string secret_code[], int a_key);    

int main()
{
	const string codeA = ":mmZ\\dxZmx]Zpgy";
	const string codeB = "\\Y``c4kcf`X";
	int key;
	string clear_temp;
	
	cout << endl << " Decrypting Code A:     " << codeA << endl << endl;
	
	for(key = 1; key < 101; key++)           
	{
		clear_temp = Decrypt(codeA, key);
	}

	return 0;

}


string Decrypt(const string code, int key)
{
	int array_length = sizeof(code);
	string clear_text;

	for(unsigned int i = 0; i < code.length(); i++)
	{
		if (code[i] + key > 126)
		{																	     
			clear_text[i] = 32 + ((code[i] + key) - 127);					
		}																	
		else															
		{
			clear_text[i] = code[i] + key;									
		}																		
																			
	}

	return clear_text; 
}




why do I get:

1
2
(18) : error C2664: 'Decrypt' : cannot convert parameter 1 from 'const std::string' to 'const std::string []'
1>        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
Line 5. Get rid of the brackets.


Also... clear_text starts out as a string with length 0, so you can't use the [] operator on it like that. Instead you can push_back new characters:

1
2
//clear_text[i] = code[i] + key;  // bad
clear_text.push_back( code[i] + key );  // good 


Or you can make code nonconst and modify that directly as I did in my previous post.

Topic archived. No new replies allowed.