Updated: Memory Location being outputted instead of desired string - c++

->Please see my edited question below the horizontal divider:
I was trying to return a string array from a function to another function. The code compiled successfully; however, it failed upon execution. I have included my code below:
string Occupant::LoadDataFunction()
{
string array[5] = {"hello", "you", "are", "a", "human"};
return array[5];
}
void Occupant::LoadData()
{
string loc_array[5];
loc_array[5] = Occupant::LoadDataFunction();
string park_array[5];
park_array[5] = Occupant::LoadDataFunction();
string lease_array[5];
lease_array[5] = Occupant::LoadDataFunction();
}
When I debugged the code, I found out that the problem was in the return statement of the function:
return array[5]
The debugger had the following output:
Signal = SIGSEGV (Segmentation Fault)
this = { Occupant * const | 0x61ff2f} 0x61ff2f
array = {std::_cxx11::basic_string< char, std::char_traits, std::allocator> [5]}
Can someone tell me what is wrong with my return statement, why it is causing a segmentation error? Thanks
** I know there are many other similar questions on the web, but none of them involved a segmentation fault in the return statement Therefore, I would appreciate it if this question is not marked as a duplicate. If you need any more information, just inform me in the comments box. Thanks for your help!
EDIT Thanks everyone, I didn't notice that glitch I just fixed it. I actually wanted to return the entire array, I did it with pointers this time. Here's my code:
string* Occupant::LoadDataFunction()
{
string* array = new string[5];
array[0] = "hello";
array[1] = "hello";
array[2] = "hello";
array[3] = "hello";
array[4] = "hello";
return array;
}
void Occupant::LoadData()
{
string **loc_array = new string*[5];
loc_array[5] = Occupant::LoadDataFunction();
string **park_array = new string*[5];
park_array[5] = Occupant::LoadDataFunction();
string **lease_array = new string*[5];
lease_array[5] = Occupant::LoadDataFunction();
for (int i = 0; i < 5; i++)
{
cout << &loc_array[i] << " : location" << endl;
cout << &park_array[i] << " : parking" << endl;
cout << &lease_array[i] << " : leased" << endl;
}
}
The problem now is that when I run the code, rather than printing hello fifteen times in total, it prints the memory address. Here's what I got:
0xf56d50 : location
0xf56df8 : parking
0xf56ea0 : leased
0xf56d54 : location
0xf56dfc : parking
0xf56ea4 : leased
0xf56d58 : location
0xf56e00 : parking
0xf56ea8 : leased
0xf56d5c : location
0xf56e04 : parking
0xf56eac : leased
0xf56d60 : location
0xf56e08 : parking
0xf56eb0 : leased
I expected a "Hello" word outputted wherever a memory address is outputted. Can anyone explain this now? Thanks for all your answers!

To return an array, use std::array, as a std::array is copyable and assignable, unlike a vanilla array.
#include <array>
#include <algorithm>
typedef std::array<std::string, 5> Array5Strings;
Array5Strings LoadDataFunction()
{
Array5Strings ret;
std::fill(ret.begin(), ret.end(), "hello");
return ret;
}
Also, I used std::fill to quickly set the items to "hello".
Live Example
If for some weird reason you can't use std::array, then the other alternative is to create a struct that contains an array of 5 strings, and return the struct. A struct is copyable, thus can be returned directly from a function.
#include <algorithm>
#include <string>
#include <algorithm>
#include <iostream>
struct Array5Strings
{
std::string sArray[5];
};
Array5Strings LoadDataFunction()
{
Array5Strings ret;
std::fill(std::begin(ret.sArray), std::end(ret.sArray), "hello");
return ret;
}
int main()
{
Array5Strings val = LoadDataFunction();
std::cout << val.sArray[0]; // prints the first value
}
Live Example
Regardless of which you choose, note that there are no pointers involved.

You are accessing the arrays using out of bounds index.
When you have an array declared as:
string loc_array[5];
the valid indices are 0 - 4.
Use of
loc_array[5] = Occupant::LoadDataFunction();
is cause for undefined behavior. I suspect you meant to use:
loc_array[4] = Occupant::LoadDataFunction();
Similarly, you need to use:
park_array[4] = Occupant::LoadDataFunction();
and
lease_array[4] = Occupant::LoadDataFunction();
You also need to change Occupant::LoadDataFunction.
string Occupant::LoadDataFunction()
{
string array[5] = {"hello", "you", "are", "a", "human"};
return array[4];
}
Update
The updated implementation of of Occupant::LoadDataFunction is better but there are still problems.
Each time the function gets called, you are allocating an array of strings. It's not clear whether that's the intention. If that's the intention, then the calling code has to take responsibility for deallocating that memory.
The calling code still suffers from out our bounds memory access. The line
string **loc_array = new string*[5];
allocates memory for 5 string*. The valid indices for loc_array is still 0 - 4. Hence,
loc_array[5] = Occupant::LoadDataFunction();
suffers from out of bounds memory access problem. It's not clear how you wish to use the return value of Occupant::LoadDataFunction. Hence, I am not able to suggest a way to solve the problem.
The lines
park_array[5] = Occupant::LoadDataFunction();
lease_array[5] = Occupant::LoadDataFunction();
suffer from the same problem.

Try returning array[4]. There is no array[5], since arrays start at index 0.

The range of an array of size N is from 0 to N-1. So the 5 is out of the range. And you may want to return an array as a result, but the array is constructed in the function LoadData, after the function is executed, the array is invalid. You may use dynamic allocation for your purpose or use a global variable.
When you use the dynamic allocation array, you can just use string* instead of string**, and you should release the allocated memory.

Related

Logical error. Elements in std::string not replaced properly with for loop

I'm currently doing a programming exercise from a C++ book for beginners. The task reads as follows: "Write a function that reverses the characters in a text string by using two pointers. The only function parameter shall be a pointer to the string."
My issue is that I haven't been able to make the characters swap properly, see the output below. (And I also made the assumption that the function parameter doesn't count, hence why I'm technically using three pointers).
I am almost certain that the problem has to do with the for loop. I wrote this pseudocode:
Assign value of element number i in at_front to the 1st element in transfer_back.
Assign value of element number elem in at_back to element number i in at_front.
Assign value of the 1st element in transfer_back to element number elem in at_back.
Increment i, decrement elem. Repeat loop until !(i < elem)
I wasn't sure whether of not I was supposed to take the null terminator into account. I tried writing (elem - 1) but that messed up with the characters even more so I've currently left it as it is.
#include <iostream>
#include <string>
using namespace std;
void strrev(string *at_front) {
string *transfer_back = at_front, *at_back = transfer_back;
int elem = 0;
while(at_back->operator[](elem) != '\0') {
elem++;
}
for(int i = 0; i < elem; i++) {
transfer_back->operator[](0) = at_front->operator[](i);
at_front->operator[](i) = at_back->operator[](elem);
at_back->operator[](elem) = transfer_back->operator[](0);
elem--;
}
}
int main() {
string str = "ereh txet yna";
string *point_str = &str;
strrev(point_str);
cout << *point_str << endl;
return 0;
}
Expected output: "any text here"
Terminal window: "xany text her"
The fact that the 'x' has been assigned to the first element is something I haven't been able to grasp.
Here is the correct answer
void strrev(string *at_front) {
string *at_back = at_front;
char transfer_back;
int elem = 0;
while(at_back->operator[](elem) != '\0') {
elem++;
}
for(int i = 0; i <elem; i++) {
transfer_back = at_front->operator[](i);
at_front->operator[](i) = at_back->operator[](elem);
at_back->operator[](elem) = transfer_back;
elem--;
}
}
Let me explain why you have that error. string *transfer_back = at_front those two are pointed to the same reference, that is why when you change transfer_back->operator[](0) = at_front->operator[](i);this change will reflect in at_front string as well.
"Write a function that reverses the characters in a text string by using two pointers. The only function parameter shall be a pointer to the string."
This sounds to me like the question addresses C strings but not std::string.
Assuming my feeling is right, this could look like:
#include <iostream>
#include <string>
void strrev(char *at_front) {
char *at_back = at_front;
if (!*at_back) return; // early out in edge case
// move at_back to end (last char before 0-terminator)
while (at_back[1]) ++at_back;
// reverse by swapping contents of front and back
while (at_front < at_back) {
std::swap(*at_front++, *at_back--);
}
}
int main() {
char str[] = "ereh txet yna";
strrev(str);
std::cout << str << '\n';
return 0;
}
Output:
any text here
Live Demo on coliru
Note:
I stored the original string in a char str[].
If I had used char *str = "ereh txet yna"; I had assigned an address of a constant string to str. This feels very wrong as I want to modify the contents of str which must not be done on constants.
strrev():
The at_back[1] reads the next char after address in at_back. For a valid C string, this should be always possible as I excluded the empty string (consisting of 0-terminator only) before.
The swapping loop moves at_front as well as at_back. As the pointer is given as value, this has no "destructive" effect outside of strrev().
Concerning std::swap(*at_front++, *at_back--);:
The swapping combines access to pointer contents with pointer increment/decrement, using postfix-increment/-decrement. IMHO, one of the rare cases where the postfix operators are useful somehow.
Alternatively, I could have written:
std::swap(*at_front, *at_back); ++at_front; --at_back;
Please, note that std::string is a container class. A pointer to the container cannot be used to address its contained raw string directly. For this, std::string provides various access methods like e.g.
std::string::operator[]()
std::string::at()
std::string::data()
etc.

Is it possible to make an array of arrays?

I am writing a program to simulate a cache in c++ and am trying to copy addresses that are given in a file into an array. I am struggling to figure out how to copy an array into another array so that I can have an array of memory address arrays. I have read in the addresses into an array called "address" and I want my simulated cache to be an array called "L1_Cache". h is a counter that I am incrementing after I put an address into the L1_Cache. Also, cache size is going to be how many lines of addresses are available in my L1_Cache array, which will be decided by the user of the program. Below is the snippet where I am trying to put the array into the other array.
if(sizeof(L1_Cache) < cachesize)
strcpy(L1_Cache[][h], address);
they are defined as:
const char* address[10];
char* L1_Cache;
If anyone has any suggestions on how to copy one array into another array to make an array of arrays, let me know. I am not sure if anything I am doing is correct, but I am struggling to figure this out.
I want to compare new addresses that I am given to old addresses that are already in the L1_Cache array.
Yes, it is possible to make an array of arrays.
int a[3][3]; // a is an array of integer arrays
You have
a[0]; // this refers to the first integer array
a[1]; // this refers to the second array
Is the following what you are looking for?
#include <iostream>
#include <cstring>
int main()
{
char p[2][256];
strncpy(p[0], "This is my first address", 256);
strncpy(p[1], "This is my second address", 256);
std::cout << p[0] << std::endl << p[1];
return 0;
}
Yes. They are called multidimensional arrays.
They can have any number of dimensions.
For example:
int foo[3][3]; // initialize the 2 dimensional array of integers
foo[0][0] = 1; // change a value
foo[0][1] = 2; // change a value
foo[0][2] = 3; // change a value
foo[1][0] = 4; // change a value
foo[1][1] = 5; // change a value
foo[1][2] = 6; // change a value
foo[2][0] = 7; // change a value
foo[2][1] = 8; // change a value
foo[2][2] = 9; // change a value
for(int i=0;i<3;++i){ // display the 2d array
for(int j=0;j<3;++j){
cout<<foo[i][j];
}
cout<<endl;
}
What's happening:
Values are being assigned in a chart.
Think of it like writing a value on each point of a piece of paper.

Having trouble creating linked list

I have an array of strings that I'm supposed to create a linked list with. The problem is I can only use arrays. Everything I've looked up says to use struct and nodes, and I'm not sure where to go from here. I know my code isn't right, I have the pointers pointing to one element of the array each, so they aren't really linked. If anyone can point me in the right direction that would be amazing
Here is what I have so far
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string names [4] = {"Dick", "Harry", "Sam", "Tom", " "};
string *nameptr[4];
for(int x = 0; x < 4; x++)
{
nameptr[x] = &names[x];
cout << *nameptr[x] << " is at position " << x << " and points to ";
cout << &nameptr[x] << endl;
}
return 0;
}
Here is a tutorial for linked lists in c++:
http://www.dreamincode.net/forums/topic/31357-c-linked-lists-custom-linked-lists-part-1/
You should search and have a go first in future, then when you ask people here will be able to better help you with your question. In fact read this as well:
http://mattgemmell.com/2008/12/08/what-have-you-tried/
Actually if using arrays, you only need a pointer to the first element, and you can access the rest of the array by pointer arithmetic.
However, if you want a real link list. then you could do something like this:
struct mydata{
std::string data;
struct mydata* next;
}
mydata names[4] = {{"Dick",NULL}, {"Harry",NULL}, {"Sam",NULL}, {"Tom",NULL}, {" ",NULL}};
//here you establish the link
names[0].next = &names[1];
names[1].next = &names[2];
names[2].next = &names[3];
names[3].next = &names[4];
//here is the pointer to the head;
mydata* nameptr = names;
while(nameptr)
{
cout << nameptr->data;
nameptr = nameptr->next;
}
What do you mean by "I can only use arrays"? You only know how to use arrays, or you are limited to only using arrays, or ??
You've looked up some stuff that's told you to use structs - have you tried doing this? It isn't in your code here.
Unrelated to your actual question, but you've declared an array of 4 strings (string names [4]), then you're trying to initialise that array with 5 items.
My advice is similar to what you've seen: use structures, and I'll add that you're going to need to use the heap as well (malloc in c, new in c++). The structure will need a link pointer to the next list element, and somewhere to store the data itself, in this case probably just a char pointer.

2d boolean array initialization in c++

I don't use C that much and I recently got confused about 2d array initialization problem. I need to debug somebody's code and stuck in the following(her original code):
const int location_num = 10000;
bool **location_matrix;
if (node_locations)
{
location_matrix = (bool **)malloc(location_num*sizeof(bool *));
if (!location_matrix)
{
cout<<"error 1 allocating location_matrix" << endl;
exit;
}
for (i=0; i<location_num; i++)
{
location_matrix[i] = (bool *) malloc(location_num*sizeof(bool ));
if (!location_matrix[i])
{
cout<<"error 2 allocating location_matrix" << endl;
exit;
}
for (j=0; j<location_num; j++)
location_matrix[i][j] = false;
}
}
I thought is was redundant, so I changed it to the following:
location_matrix[location_num][location_num] = { {false} };
However, segmentation fault happens at runtime.
My question is: how does the above code fail? If it looks right, what's the difference between dynamically allocation and static allocation? Is it just because the dimension might not be constant, so we need to do it dynamically?
Also, just for curiosity, how do I malloc 2d array that stores pointers? Thanks.
The change would likely require about 100MB (10,000 * 10,000 * 1) on the stack, so the segmentation fault was likely due to a stack overflow.
Edit I originally stated 400MB in the answer, but #Mooing Duck points out bool will likely be 1 byte. I was thinking the Win32 BOOL (for no real reason at all), which is typedefed to an int.
I actually don't see anything wrong with the code.
The following code doesn't work because location_matrix is not allocated:
location_matrix[location_num][location_num] = { {false} };
GCC will allow the following (as an extension):
bool location_matrix[location_num][location_num] = { {false} };
But it will blow your stack because 10000 x 10000 is too large.
Currently, your code uses dynamic allocation. That's the correct way to do it because the matrix is too large to be done as a static array (and may overrun the stack).
As for your last question, "how to make a 2d array that stores pointers": It can be done almost the same way as your current code. Just change bool to int*.
So a 2D array of NULL int pointers will look like this:
int ***location_matrix;
if (node_locations)
{
location_matrix = (int***)malloc(location_num*sizeof(int**));
if (!location_matrix)
{
cout<<"error 1 allocating location_matrix" << endl;
exit;
}
for (i=0; i<location_num; i++)
{
location_matrix[i] = (int**) malloc(location_num*sizeof(int*));
if (!location_matrix[i])
{
cout<<"error 2 allocating location_matrix" << endl;
exit;
}
for (j=0; j<location_num; j++)
location_matrix[i][j] = NULL;
}
}
The standard library is your friend.
#include <vector>
int
main()
{
int location_num = 1000;
std::vector<std::vector<bool> > location_matrix(location_num, std::vector<bool>(location_num, false));
}
Second, the array is likely too large to fit on the stack, so you'd need to dynamically allocate it -- but you can simplify the code as long as the difference between a 2-dimensional array and an array of pointers won't be an issue (as it would be if you needed to pass the array to a function or use pointer arithmetic with it).
You could use something like this:
bool (*location_matrix)[location_num];
location_matrix = (bool (*)[location_num])calloc( location_num,
location_num * sizeof(bool) );
...which allocates space for the whole two-dimensional array and gives a pointer to an array of bool arrays with location_num elements each.

Return string array in C++ function

I am new to C++.
For a school project I need to make a function which will be able to return a string array.
Currently I have this in my header:
Config.h
string[] getVehicles(void);
Config.cpp
string[] Config::getVehicles(){
string test[5];
test[0] = "test0";
test[1] = "test1";
test[2] = "test2";
test[3] = "test3";
test[4] = "test4";
return test;}
Obviously this does not work but that's the idea of what I am trying to do.
In Java this would be the way to do it. I've tried googling my problem but I didn't come across any answers that were clear to be honest.
Maybe it is better to use a vector in this case, but this is not a correct answer for the question. The reason why it doesn't work is that the variable test just exists in the scope of your function.
So you have to manage the memory on your own. Here is an example:
string* getNames() {
string* names = new string[3];
names[0] = "Simon";
names[1] = "Peter";
names[2] = "Dave";
return names;
}
In this case you return a pointer of the position in the heap. All the memory in the heap has to free manually. So it is now your work to delete the memory, if you don't need it anymore:
delete[] names;
In C++ you don't use an array, but a std::vector instance. Arrays in C++ must have a compile-time fixed length while std::vector instances can change their length at runtime.
std::vector<std::string> Config::getVehicles()
{
std::vector<std::string> test(5);
test[0] = "test0";
test[1] = "test1";
test[2] = "test2";
test[3] = "test3";
test[4] = "test4";
return test;
}
std::vector can also grow dynamically, so in a C++ program you will find more often something like
std::vector<std::string> Config::getVehicles()
{
std::vector<std::string> test; // Empty on creation
test.push_back("test0"); // Adds an element
test.push_back("test1");
test.push_back("test2");
test.push_back("test3");
test.push_back("test4");
return test;
}
Allocating dynamically an array of std::string is technically possible but a terrible idea in C++ (for example C++ doesn't provide the garbage collector that Java has).
If you want to program in C++ then grab a good C++ book and read it cover to cover first... writing Java code in C++ is a recipe for a disaster because the languages, despite the superficial braces similarity, are very very different in many fundamental ways.
Try this
#include <iostream>
#include <string>
using namespace std;
string * essai()
{
string * test = new string[6];
test[0] = "test0";
test[1] = "test1";
test[2] = "test2";
test[3] = "test3";
test[4] = "test4";
cout<<"test et *test\t"<<&test<<' '<<*(&test)<<'\n';
return test;
}
main()
{
string * toto;
cout<<"toto et *toto\t"<<&toto<<' '<<*(&toto)<<'\n';
toto = essai();
cout<<"**toto\t"<<*(*(&toto))<<'\n';
cout<<"toto\t"<<&toto<<' '<<*(&toto)<<'\n';
for(int i=0; i<6 ; i++)
{
cout<<toto[i]<<' '<<&toto[i]<<'\n';
}
}
For example, in my computer, the result is
toto et *toto 0x7ffe3a3a31b0 0x55dec837ae20
test et *test 0x7ffe3a3a3178 0x55dec9ddd038
**toto test0
toto 0x7ffe3a3a31b0 0x55dec9ddd038
test0 0x55dec9ddd038
test1 0x55dec9ddd058
test2 0x55dec9ddd078
test3 0x55dec9ddd098
test4 0x55dec9ddd0b8
0x55dec9ddd0d8
Getting addresses and contents of addresses could help you to understand that an array in c++ is really rudimentary : it offers no methods and you could access an index without allocating memory (the value 6 in the loop).
Your first example show a direct allocation of a local array (test), so you can't return it (the local array dies), in this example, the local variable dies also but there is always a variable that access at this part of allocated memory, the function, and then the variable that receive the result of the function, so the variable test is dead after the calling of the function but the memory is still allocated. Regards.