How to use double pointers in array - c++

I am in a problem in which I have to write a function which will tokenize the array of characters and then return the array.... I cannnot understand how to use double pointers... The whole code is here:
#include<iostream>
using namespace std;
char** StringTokenize(char*);
int main()
{
char *string1=new char[50];
cout<<"Enter: ";
cin.getline(string1,50);
StringTokenize(&string1[0]);
return 0;
}
char** StringTokenize(char *string1)
{
int i = 0, j = 0;
char **tokenArray[50];
**tokenArray[0] = &string1[0];
while (string1[i] != '\0')
{
tokenArray[i] = string1[i];
i++;
if (string1[i] == ' ')
{
tokenArray[i] = '\n';
i++;
}
else
{
continue;
}
}
tokenArray[i] = '\0';
cout << tokenArray << endl;
return tokenArray;
}
Please help me and write this function for me... Remember that prototype of function should not change

and then return the array.
In C++, return type of a function cannot be an array.
char *string1=new char[50];
It's a bad idea to use bare owning pointers to dynamic memory. If the program compiled at all, you would be leaking memory. I recommend using std::string instead.
StringTokenize(&string1[0]);
&string1[0] is redundant. You indirect through a pointer, and then get the address of the result... which is the pointer that you indirected through.
int i = 0, j = 0;
You've declared j, but aren't using it for anything.
char **tokenArray[50];
The pointers to substrings should be pointers to char. It's unclear why your array contains pointers to pointers to char.
Note that these pointers are uninitiallised at the moment.
**tokenArray[0] = &string1[0];
**tokenArray[0] will indirect through the first uninitialised pointer and the behaviour of the program will be undefined. And the right hand side has the aforementioned redundancy.
And the types don't match. The type of left hand operand is char while the type of right hand operand is char*. This is ill-formed and meaningless. Your compiler should be telling you about bugs like this.
tokenArray[i] = string1[i];
tokenArray[i] = '\n';
tokenArray[i] = '\0';
The types don't match. The type of left hand operand is char** while the type of right hand operand is char. These are ill-formed and meaningless. Your compiler should be telling you about bugs like this.
return tokenArray;
This is wrong because
The types don't match. You're supposed to return a char**, but tokenArray is an array of char**.
Returning an automatic array would result in implicit conversion to pointer to first element (which is a char***) and the automatic array would be automatically destroyed after the function returns, so the returned pointer would be invalid.
prototype of function should not change
That's rather unfortunate since it prevents writing a well designed function. You will either have to use static storage for the array, or return an owning bare pointer to (first element of) dynamic array. Neither is a good idea.

Related

C++ Passing Static Array and Dynamic Array By Reference

To fully understand how pointers, values, and references work, I am making a basic C++ program that attempts to tamper with some static and dynamic arrays and understand exactly how they should be passed in.
First I generate a static array of 3 elements. I then pass it into a function that modifies all elements. I then pass it into another function with a slightly different signature, but can also alter the array's values.
Next I generate a dynamically sized array, pass it into a function by reference so that all of the values in this dynamically sized array can be altered.
The code is as follows:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
void changeIndexStaticArrayMethod1(int* stat);
void changeIndexStaticArrayMethod2(int (&stat)[3]);
void changeIndexDynamicArrayMethod1(int* dyn, int size);
int main() {
const int MAX = 3;
int arr[MAX] = { 1,2,3 };
changeIndexStaticArrayMethod1(arr);
cout << arr[0] << endl;
cout << arr[1] << endl;
cout << arr[2] << endl;
cout << endl;
changeIndexStaticArrayMethod2(arr);
cout << arr[0] << endl;
cout << arr[1] << endl;
cout << arr[2] << endl;
int SIZE;
cout << "Please choose a size for the array" << endl;
cin >> SIZE;
int *ne = new int[SIZE];
//Build array
for (int i = 0; i < SIZE; i++) {
ne[i] = i;
}
changeIndexDynamicArrayMethod1(ne, SIZE);
for (int i = 0; i < SIZE; i++) {
cout << "ne[" << i << "] = " << ne[i] << endl;
}
//To hang program
cin >> SIZE;
delete[] arr;
delete[] ne;
return 0;
}
void changeIndexStaticArrayMethod1(int* stat) {
stat[0] = 10;
stat[1] = 20;
stat[2] = 30;
}
void changeIndexStaticArrayMethod2(int (&stat)[3]) {
stat[0] = 40;
stat[1] = 50;
stat[2] = 60;
}
void changeIndexDynamicArrayMethod1(int* dyn, int size) {
for (int i = 0; i < size; i++) {
dyn[i] = i * 10;
}
}
All of the above code works how I want it to, I just have a few questions as to why (some of the methods of passing arrays by reference I have found on other SO questions).
In the changeIndexStaticArrayMethod1() and changeIndexDynamicArrayMethod1() functions, why are we able to use the dereference * operator for our array as reference? My knee jerk reaction is seeing that as practically passing the array in by values since it is the dereference operator. I know that with arrays, it is much different than using variables, but also, why will the following not work for single int variables:
void changeStaticNumber(int* num){
num = 100;
}
Obviously the above will work if we use &num and not int* num, and obviously I don't fully understand the relationship between pointers and arrays, but I cannot figure out why when we pass an array by reference, int* staticArray is ok.
Any explanation for these problems I am having would be much appreciated. Thanks.
why are we able to use the dereference * operator for our array as reference?
The * in C means many things. It can mean the unary indirection ("contents of") operator, it can mean the binary multiplication operator and it can mean a pointer declaration. The int* stat is a pointer declaration.
Since you aren't using the * to dereference the contents of the pointer inside that function, I'm not quite sure what you are asking.
When you take the array name of your array in main(), it "decays" into a pointer to the first element. So what those function do, is to take a pointer by value. If you dereference the pointer by typing *stat = something; you access the actual array in main.
Should you do something weird like changing the pointer itself, for example stat++;, then it will not affect the address used in main. You passed the pointer itself by value, so the pointer is a local copy.
My knee jerk reaction is seeing that as practically passing the array in by values since it is the dereference operator.
You can't really pass arrays by value in C or C++, without resorting to dirty tricks (storing them inside structs or classes). For example, had your function been written as void changeIndexStaticArrayMethod1(int stat[3]) it would still give you a pointer to the first element. It will not pass an array by value, as the syntax might trick you into believing.
why will the following not work for single int variables:
void changeStaticNumber(int* num){ num = 100; }
Because num is the pointer itself, not its contents. In order to write code like that, you could pass the variable by reference int& num. Behind the lines this is really the same thing as passing a pointer, just with simplified syntax.
To understand the relation between pointers and arrays better, start by reading this whole chapter: http://c-faq.com/aryptr/index.html (C and C++ are identical when it comes to pointers).
Let me see if I can take a stab at this.
Pointers are simply address holders. Once you do int * ptr = myarray; --- what you are in tern doing is storing the address of the pointer my array into ptr --- array names are actually pointers to the first memory location in the array. You can use pointer arithmetic to get at everything else for example myarray +1 will point you to the next location or myarray[1].
Passing by value is not very useful when you need to modify your array. Passing in by reference is essentially making a pointer to the array and passing that. Since arrays like vectors are contiguous blocks of memory you can index through them rather easily.
As far as your example goes void changeStaticNumber(int* num){ num = 100; } will not work because what you are attempting to do is store 100 into the pointer's address. If you deference num and make it void changeStaticNumber(int* num){ *num = 100; } it will work because you are actually going one step further and accessing the data that num is pointing to. When you use &num it is essentially the same thing - & just gives you the address of something.
For example if you want to point a pointer to an int what you would do is
int num = 5;
int *ptr = &num;
at this point in time ptr has the same address in num. To print out the data in num or that ptr is pointing to you need to dereference or go one step further as I like to tell myself and dereference to so cout << *ptr;
In both changeIndexStaticArrayMethod1 and changeIndexDynamicArrayMethod1 you are not passing an array there is no pass by reference (which only happens if the parameter type is a reference type -- i.e. with &). The parameter has type int * (pointer to int). You are passing a pointer to int by value. There is no "dereference operator" in either function.
ne is already an int *, so passing it is nothing special. arr is an int [3], an array, not a pointer. In C, when an array-of-T is used in a context that expects a pointer-to-T, it is implicitly converted (without you needing to do anything) to a pointer to its first element. So when you do, changeIndexStaticArrayMethod1(arr), the compiler gets a pointer to the first element of arr, and passes that to the function.
The [] operator works on pointers. a[i] is always guaranteed to be the same as *(a + i). Inside both the changeIndexStaticArrayMethod1 and changeIndexDynamicArrayMethod1 functions, [] is used to access subsequent elements using a pointer to the first element.

Returning two dimensional array of strings

string** flowFile() {
string line;
string word[8];
int i=0;
static string flow[23][2];
ifstream myfile ("test.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
strSplit(line,word);
flow[i][0]=word[1];
flow[i++][1]=word[2];
}
myfile.close();
}
else cout << "Unable to open file";
return flow;
}
int main()
{
string **fl=flowFile();
}
I'm getting this error:
error: cannot convert ‘std::string (*)[2] {aka std::basic_string<char> (*)[2]}’
to ‘std::string** {aka std::basic_string<char>**}’
in return
What is wrong with my code?
string flow[23][2] and string ** are two different incompatible types. One cannot convert to another implicitly. Thats all. The solution is to make them compatible, by making the later string [23][2], return reference and accept reference, but that would still be a bad solution, because you're still working with raw arrays.
A good solution is to use std::vector and std::string. Maybe, you need std::pair also, or std::array.
Here is one possible solution:
#include <vector>
#include <array>
#include <string>
//C++11 style typedef
using flow_data_t = std::vector<std::array<std::string,2>>;
//reimplementation of your function
flow_data_t flowFile()
{
std::string line;
std::string word[8];
int i=0;
flow_data_t flow;
std::ifstream myfile ("test.txt");
if ( !myfile )
cout << "Unable to open file";
while ( std::getline (myfile,line) )
{
strSplit(line,word);
flow.push_back({word[0], word[1]});
}
return flow;
}
int main()
{
flow_data_t data=flowFile();
for(auto const & row : data)
for(auto const & col : row)
//work!
}
Hope that helps.
You cannot return array from a function even though you can return a pointer and let your array decay to a pointer: Array Decay
However 2D array can decay to neither T* nor T** because of the memory layout of the array is different from "2D pointer array" (it is actually more like flattened), and you cannot return array from function. However in C++ you can return array reference Full Code:
//This does not work
//typedef string * string2d[2];
//typedef string *(&string2d)[2];
typedef string (&string2d)[23][2];
string2d flowFile() {
static string flow[23][2];
return flow;
}
Array reference would even preserve the information of how big each row and columns are and no array decaying happen.
Of course, a more suggested "C++ way" to do this is using std::vector (as always).
In C++, arrays have type std::vector. You should use these, not low-level builtin arrays declared with [].
In C++, string [23] is sometimes interchangeable with string*, but string[23][2] is never interchangeable with string**. That's one reason you should not use builtin arrays.
In C++, you cannot return a local builtin array variable. It will compile but then your program will probably crash. This is another reason you should not use builtin arrays. (Returning a static array should be OK though).
There are many more reasons.
There is nothing wrong with returning a pointer to a static variable. It's just that the return type must be declared properly. It kind of makes sense if you try to reproduce what the declarations mean, and what the compiler accordingly tries to do. Consider the declaration static string flow[23][2];. It declares 23 rows of strings, each with 2 elements. It helps if you look at it as a one-dimensional array. It just so happens that the array elements are arrays, but that's not so important right now (but we'll come back to it). From this perspective the array has just 23 elements, and each element has the size of 2 strings. Like with all arrays, the elements (here: arrys of 2 strings) are simply lined up in memory.
Like any array, flow will in most contexts decay to a pointer to its first element. Incrementing that pointer will point to the next element, i.e the second row. Numerically the compiler must add 2*sizeof(string) to the address of flow in order to compute the address of flow's next element, which would be flow[1]. (It comes directly behind flow[0]. No magic here.)
Now if you declare string **flowpp, flowpp is a pointer already, no need to decay. If we think it is pointing to the first element in an array, what type would the elements have? Sure enough: plain pointers. Incrementing flowpp would let it point to the next element. My pointers are 4 bytes large, so that numerically adding just 4 to flowpp would be enough to access flowpp's next element. Compared to what needs to be added to flow (remember, 2*sizeof(string)), that's completely different. The compiler computes the offsets of elements depending of what the pointers point to! Which is very different in the two cases.
So what can your function return? What does flow decay to when you return it? It decays to a pointer to its first element. The elements are arrays of two strings. It must be string xxx[2], with xxx being a pointer: hence string (*p)[2]. If the pointer is actually returned by a function, we have a function call instead of plain p, so it's (*f())[2].
Here is a complete example:
#include<iostream>
using namespace std;
const int numFlowElems = 3, numArrElems = 2;
/** #return a pointer to the first element of a static array
of string[numArrElems]s.
*/
string (*flowFile())[numArrElems]
{ // init so that we see something below.
static string flow[numFlowElems][numArrElems]
= {{"1","2"},
{"3","4"},
{"5","6"}
};
// your function code ...
return flow;
}
int main()
{
// array decays to ptr, like usual. Ptr elems are string[numArrElems].
// ptrToArr is a pointer to arrays of two strings.
string (*ptrToArr)[numArrElems] = flowFile();
for( int flowInd= 0; flowInd<numFlowElems; ++flowInd )
{
for(int strInd = 0; strInd<numArrElems; ++strInd)
{
cout << ptrToArr[flowInd][strInd] << ' ';
}
cout << endl;
}
return 0;
}
How do you parse string (*flowFile())[numArrElems]? I needed two attempts to get the declaration right, if that's any consolation. The key is that in C and C++ (not in C#, mind you!) a declaration has the shape of an expression.
You can do it from the inside to the outside: flowFile() is a function. The result is dereferenced because the function call has higher precedence than the star: *flowFile() is the dereferenced result. Apparently that result is an array of size numArrElems, with elements which are strings.
You can do it outside in: The result of (*flowFile())[numArrElems] is declared as a string. (*flowFile()) is an array of strings with numArrElems elements. Apparently flowFile() must be dereferenced to obtain that array so that flowfile is a function which returns a pointer to an array of numArrElems strings. That's true! It returns the first element of flow, which is exactly an array of strings.
Vectors of vectors might indeed be easier; if you want to retain the semantics you should pass references, as others mentioned: After all, all functions in your original program will operate on the same static array. If you pass vectors by value that will not be the case any longer. But then, that may actually be beneficial.

c++ pointer not declared

I am writing a member function for a class where I would like to print out some dynamically allocated array according to the string name passed to the member function. The following code somehow get a compilation error:
error: 'tmp' was not declared in this scope
How should I do the coding? What is the problem of my code?
void backgrnd::print(const char m[]){
if (m == "interior")
int* tmp = this->interior;
else if (m == "fB")
float* tmp = this->fB;
for (int i=0;i<this->n_vox;++i)
cout << tmp[i] << ' ';
}
There are a few problems with your code.
You're passing a string by pointer (writing const char [] is quite the same as writing const char * – BTW, const is left associative and you could write it as char const * as well).
void backgrnd::print(const char m[]){
Anyway, in the next line you're comparing this pointer m with the pointer refering to the string literal constant "interior"
if (m == "interior")
And this does not what you had most likely in mind. This operation compares the values of the pointers and not the strings! The pointers would only compare as equal, if the pointer you passed to the function was that of the same string literal "interior", which is very unlikely the case. If it was just any other string, even if it also contained the character sequence interior, it would not compare equal. It would also happen if the compiler and/or linker didn't redact redundant string literals into a single pointer constant.
And of course the other pointer - string literal comparisions suffer from the same problem.
Now the next problem is, that you create a scoped pointer variable tmp, which you initialize with some instance class member pointer variable of the same type. But as soon as the scope is left that variable is no longer visible...
int* tmp = this->interior;
else if (m == "fB")
float* tmp = this->fB;
... and this for loop can no longer see it. Now this loop is problematic by itself, because it's unclear what n_vox means.
for (int i=0; i < this->n_vox; ++i)
I guess you wrote the above to save some code duplication below. The problem is: C++ is a statically typed language so the following statement can not "dynamically" type to the type of the tmp variable.
cout << tmp[i] << ' ';
}
Here are a few suggestions:
when using C++ you should use std::string instead of naked char arrays. This also makes the equality operator == do what you naively expected. If you insist on using C-style char arrays, use a string comparision function like strncmp.
Since you need to write statically typed cout<< statements anyway, move that loop into the if clauses. Use curly braces to enclose them!.
Use braces if you are new to programming.. those variables are in local scope.
if (m == "interior")
{
int* tmp = this->interior;
}
....
tmp is out of scope..
tmp variable is only in if/else scope, it's not available in for loop.
However, I suggest a better print function:
void backgrnd::print(const std::string& m)
{
if (m == "interior")
{
std::cout << *interior << std::endl;
}
else if (m == "fB")
{
std::cout <<fB << std::endl;
}
}

Compilation error while passing double pointer in cpp

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
void f(char **x)
{
(*x)++;
**x = 'a';
}
int main()
{
char str[]="hello";
f(&str);
cout << str << endl;
return 0;
}
Please tell me why this program is giving compilation Error.I am using the g++ compiler
Error :temp1.cpp:16:8: error: cannot convert ‘char (*)[6]’ to ‘char**’ for
argument ‘1’ to ‘void f(char**)’
Arrays can be implicitly converted to pointers, but that doesn't mean that the implicit "pointer equivalent" already exists.
You are hoping that f(&str); will implicitly create both a pointer to str and a pointer to that pointer.
This small (working) change illustrates this point:
int main()
{
char str[]="hello";
char *pstr = str; // Now the pointer extists...
f(&pstr); // ...and can have an address
cout << str << endl;
return 0;
}
You are passing pointer of constant char to the function but in function you are taking it as pointer of pointers. That is the problem. I commented out below where the problem lies.
[Off topic but N. B. : Arrays and pointers are different concept.]
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
void f(char **x) //**x is pointer of pointer
{
(*x)++;
**x = 'a';
}
int main()
{
char str[]="hello";
f(&str); //You are passing pointer of constant char.
cout << str << endl;
return 0;
}
You're going to run into a serious problem with your function f since &str and &str[0] both evaluate to the same value ... as other posters have pointed out, these operations point to different types, but the actual pointer r-value will be the same. Thus in f when you attempt to double-dereference the char** pointer x, you're going to get a segfault even if you attempted something like a cast to massage the type differences and allow compilation to happen with errors. This is because you are never getting a pointer-to-pointer ... the fact that &str and &str[0] evaluate to the same pointer value means that a double-dereference acually attempts to use the char value in str[0] as a pointer value, which won't work.
Your problem is that you're treating arrays as pointers, when they're not. Arrays decay into pointers, and in this case, it doesn't. What you're passing in is a char (*)[6] when it expects a char **. Those are obviously not the same.
Change your parameter to char (*x)[6] (or use a template with a size parameter):
template <std::size_t N>
void f(char (*x)[N])
Once inside, you try to increment what x is pointing to. You can't increment an array, so use an actual pointer instead:
char *p = *x;
p++;
*p = 'a';
All put together, (sample)
template <std::size_t N>
void f(char(*x)[N])
{
if (N < 2) //so we don't run out of bounds
return;
char *p = *x;
p++;
*p = 'a';
}

Returning Character Array via Assignment Operator

So this is a homework assignment, there might be come constraints that are ridiculous but please bear with me. This is just a simple function but drawn out. I need to return a character array via assignment operator but it doesn't seem to be working at all. I've tried pointers, but no luck.
#include <iostream>
using namespace std;
char* findMax(char*, char*);
int main()
{
char aArray[50] = "Hello World",
bArray[50] = "dlroW olleH",
maxArray[50];
maxArray[50] = findMax(aArray, bArray);
cout << maxArray << " is the bigger of the 2 strings" << endl;
return 0;
}
char* findMax(char* strA, char* strB){
char* maxStr;
if(strcmp(strA, strB) < 1)
maxStr = strB;
else
maxStr = strA;
return maxStr;
}
if I cout the return value of findMax() it does print out the value of bArray, but geting it into maxArray via assignment operator isn't working at all.
There are two ways to do this. As written, maxArray is an array of characters. Arrays can't be directly assigned to. Instead you need to copy each character one by one. You could do that with a loop, or by calling the strcpy standard library function.
char maxArray[50];
strcpy(findMax(aArray, bArray), maxArray);
The other way is to change the declaration of maxArray to be a char *, a pointer. Pointers can be assigned to directly without having to loop or invoke a function.
char *maxArray;
maxArray = findMax(aArray, bArray);
The difference between this and the first solution is subtle, but important. With char maxArray[50] you are actually allocating a third array of 50 characters, separate from aArray and bArray. This array has its own storage, its own 50 bytes of memory.
In the second you don't create a third array. You merely create a pointer which can point to other arrays already in existence. After the assignment, maxArray becomes an indirect reference to either aArray or bArray. It's not a copy of one of those arrays, it points to one of them.