i got stuck with dynamic arrays. I want to read ints from a text file and store them into the array. I need a push_back and size function but cant use the STL from vector. I tried to do a push_back function but i need to use the size function for this. For the size function i thought of going through the array and increment a counter for each element, but how do i stop the loop, e.g. for (int i = 0; i < d_array.end(); i++), to use .end() I need to include <array> ?
Thanks for hints.
my code so far:
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
int* d_array = 0;
const string filename = "test.txt";
int s = 0;
int counter = 0;
fstream f;
f.open(filename, ios::in);
if (f){
while (f >> s){
counter += 1;
}
}
d_array = new int[counter];
if (f){
while (f >> s){
d_array.push_back(s);
}
f.close();
}
for (int i = 0; i < d_array.size(); i++){
cout << d_array[i] << "\n";
}
void push_back(int value){
int d_size = d_array.size();
int* d2_array = 0;
d2_array = new int[d_size + 1];
d_array = d2_array;
d_array[d_size] = value;
delete[] d2_array;
}
int size() const{
}
}
You're asking the wrong question. You're trying to solve the question
How can I find the length of a dynamically allocated array, given just the pointer to its beginning
which has no solution in general — but the question you actually need to solve is
How do I make a data structure that contains a dynamically allocated array so that I can obtain the size of the array?
which has a really simple solution, once you stop getting hung up on the question you're focusing on....
Related
I'm learning C++ and I'm wondering if anyone can explain some strange behaviour I'm seeing.
I'm currently learning memory management and have been playing around with the following code:
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
// pass back by pointer (old C++)
const int array_size = 1e6; // determines size of the random number array
vector<int> *RandomNumbers1()
{
vector<int> *random_numbers = new vector<int>[array_size]; // allocate memory on the heap...
for (int i = 0; i < array_size; i++)
{
int b = rand();
(*random_numbers).push_back(b); // ...and fill it with random numbers
}
return random_numbers; // return pointer to heap memory
}
int main (){
vector<int> *random_numbers = RandomNumbers1();
for (int i = 0; i < (*random_numbers).size(); i++){
cout << (*random_numbers)[i] + "\n";
}
delete random_numbers;
}
What I'm trying to do is get a pointer to a vector containing random integers by calling the RandomNumbers1() function, and then print each random number on a new line.
However, when I run the above code, instead of printing out a random number, I get all sorts of random information. It seems as though the code is accessing random places in memory and printing out the contents.
Now I know that I'm doing something stupid here - I have an int and I am adding the string "\n" to it. If I change the code in main() to the following, it works fine:
int main (){
vector<int> *random_numbers = RandomNumbers1();
for (int i = 0; i < (*random_numbers).size(); i++){
cout << to_string((*random_numbers)[i]) + "\n";
}
}
However I just can't understand the behaviour I'm getting with the "wrong" code - i.e. how adding the string "\n" to (*random_numbers)[i]
causes the program to access random areas of memory, instead of where my pointer is pointing to. Surely I have de-referenced the pointer and accessed the element at position i before "adding" "\n" to it? So how is the program instead accessing a totally different memory address?
"\n" is a string literal. It is an array and it is converted to a pointer pointing at its first element in your expression.
(*random_numbers)[i] is an integer.
Adding a pointer to an integer means that advance the pointer by the integer.
This will drive the pointer to out-of-range because "\n" has only 2 elements ('\n' and '\0') but the numbers returnd from the rand() function are likely to be larger than 2.
There are several issues with your code.
you are using delete instead of delete[] to free the array allocated with new[].
you are creating an array of 1000000 vectors, but populating only the 1st vector with 1000000 integers. You probably meant to create just 1 vector instead.
you can and should use the -> operator when accessing an object's members via a pointer. Using the * and . operators will also work, but is more verbose and harder to read/code for.
you are trying to print a "\n" after each number, but you are using the + operator when you should be using the << operator instead. You can't append a string literal to an integer (well, you can, but it will invoke pointer arithmetic and thus the result will not be what you want, as you have seen).
With that said, try something more like this:
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
const int array_size = 1e6; // determines size of the random number array
vector<int>* RandomNumbers1()
{
vector<int> *random_numbers = new vector<int>;
random_numbers->reserve(array_size);
for (int i = 0; i < array_size; ++i)
{
int b = rand();
random_numbers->push_back(b);
}
return random_numbers;
}
int main (){
vector<int> *random_numbers = RandomNumbers1();
for (size_t i = 0; i < random_numbers->size(); ++i){
cout << (*random_numbers)[i] << "\n";
}
/* alternatively:
for (int number : *random_numbers){
cout << number << "\n";
}
*/
delete[] random_numbers;
}
However, if you are going to return a pointer to dynamic memory, you really should wrap it inside a smart pointer like std::unique_ptr or std::shared_ptr, and let it deal with the delete for you:
#include <iostream>
#include <vector>
#include <cmath>
#include <memory>
using namespace std;
const int array_size = 1e6; // determines size of the random number array
unique_ptr<vector<int>> RandomNumbers1()
{
auto random_numbers = make_unique<vector<int>>();
// or: unique_ptr<vector<int>> random_numbers(new vector<int>);
random_numbers->reserve(array_size);
for (int i = 0; i < array_size; ++i)
{
int b = rand();
random_numbers->push_back(b);
}
return random_numbers;
}
int main (){
auto random_numbers = RandomNumbers1();
for (size_t i = 0; i < random_numbers->size(); ++i){
cout << (*random_numbers)[i] << "\n";
}
/* alternatively:
for (int number : *random_numbers){
cout << number << "\n";
}
*/
}
Though, in this case, there is really no good reason to create the vector dynamically at all. 99% of the time, it is unnecessary and unwanted to use standard containers like that. Since the vector manages dynamic memory internally, there is no reason for the vector itself to also be created in dynamic memory. Return the vector by value instead, and let the compiler optimize the return for you.
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
const int array_size = 1e6; // determines size of the random number array
vector<int> RandomNumbers1()
{
vector<int> random_numbers;
random_numbers.reserve(array_size);
for (int i = 0; i < array_size; ++i)
{
int b = rand();
random_numbers.push_back(b);
}
return random_numbers;
}
int main (){
vector<int> random_numbers = RandomNumbers1();
for (size_t i = 0; i < random_numbers.size(); ++i){
cout << random_numbers[i] << "\n";
}
/* alternatively:
for (int number : random_numbers){
cout << number << "\n";
}
*/
}
I am trying to understand what I am doing wrong when attempting to dynamically allocate the 2D array "allWordMultiArray" and assign values to it.
I've been reading a lot of articles online (and in Stackoverflow in particular) and tried to implement it in a lot of ways but unsuccessfully. using C++ 14.
So, the following code creates a warning of "Using uninitialized memory '*allWordMultiArray[i]'".
Obviously, when trying to cout the values in the 2D array it prints garbage.
Can someone point to me what the problem is?
Here's a summary of the code:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int letters = 26;
int main() {
....
int numWords, pos;
string input;
int** allWordMultiArray;
cin >> numWords;
allWordMultiArray = new int* [numWords];
for (int i = 0; i < numWords; i++) {
cin >> input;
allWordMultiArray[i] = new int[letters];
for (unsigned long int j = 0; j < input.size(); j++)
{
pos = (input[j] - 'a');
//Here is the problem. Garbage values
allWordMultiArray[i][pos]++;
}
}
return 0;
}
Your help is very much appreciated.
This line:
allWordMultiArray[i] = new int[letters];
does allocate memory for an array, but the values in the array are indeterminate. Reading from these values, like here:
allWordMultiArray[i][pos]++;
will invoke undefined behavior.
Just initialize the array when you allocate it:
allWordMultiArray[i] = new int[letters] {};
// ^^
On the input we get a sentence which we read until EOF. We need to add single words to dynamic array and then write them one on each line.
Input: Hello this, is an example.
Output:
Hello
this,
is
an
example
I have the following code and I can't figure out why it doesn't even add anything to the array.
#include <iostream>
#include <string>
using namespace std;
void addToArray(string newWord, string myArray[], int& arrayLength)
{
string * tempArray = new string[arrayLength + 1];
tempArray[arrayLength] = newWord;
for (int i = 0; i < arrayLength; ++i)
{
myArray[i] = tempArray[i];
}
arrayLength++;
myArray = tempArray;
delete [] tempArray;
}
int main()
{
string * arrayOfWOrds = new string[1000];
int arrayLength = 0;
string temp;
while (getline(cin, temp))
{
cout << temp << endl;
addToArray(temp, arrayOfWOrds, arrayLength);
}
cout << "Array" << endl;
for (int i = 0; i < arrayLength; ++i)
{
cout << arrayOfWOrds[i] << endl;
}
}
It's because you don't return the new array from the addToArray function. The change you make only happens in addToArray, it doesn't happen in main.
You also delete[] the wrong array, you delete the array you've just created.
You also copy the array elements in the wrong direction, i.e. from your new array to your old array.
Try this, I've renamed some of the variables for clarity. There is no temporary array in your function only a new array and an old array. Choosing good variable names is very important for writing working code. Bad variable names just confuse yourself.
string* addToArray(string newWord, string* oldArray, int& arrayLength)
{
string * newArray = new string[arrayLength + 1];
newArray[arrayLength] = newWord;
for (int i = 0; i < arrayLength; ++i)
{
newArray[i] = oldArray[i];
}
arrayLength++;
delete [] oldArray;
return newArray;
}
Then use it like this
arrayOfWOrds = addToArray(temp, arrayOfWOrds, arrayLength);
I see several issues here. To begin with, you set arrayLength = 0, so it's not going to iterate over the whole array if you have stuff already in it. If you don't have anything in it, there's no point in making it start off with 1000 items. Also, while (getline(cin,temp)) is an infinite loop, so it will never end and actually print the array. If you want to print the array after each addition, you need to move it into the while loop. There's no real reason to cout the number the user types either; they can already see the line they just typed.
More importantly, there are real issues with the dynamic allocation. You've created a static array (string * arrayOfWOrds = new string[1000];), then you're giving that to the function which makes a new array one item larger, sets the last item in that array to the new value, then iterates over the entire new array and duplicates the values to the old array. Basically, you're just inserting items into the static array at that point, and what you're inserting is a bunch of nothing (because the new array only has one item in it, and it's at arrayLength+1 which is outside the bounds of the original array).
You need to delete the old array, not the new array, which actually should be thrown on the heap and returned.
Basically, it should look more like this:
#include <iostream>
#include <string>
using namespace std;
string* addToArray(string newWord, string myArray[], int& arrayLength)
{
string * returnArray = new string[arrayLength + 1];
returnArray[arrayLength] = newWord;
for (int i = 0; i < arrayLength; ++i)
{
returnArray[i] = myArray[i];
}
arrayLength++;
delete [] myArray;
return returnArray;
}
int main()
{
const int startSize = 0;
string * arrayOfWords = new string[1];
int arrayLength = startSize;
string temp;
cout << "Input: ";
getline(cin, temp);
string word = "";
for (char c : temp){
if (c == ' '){
arrayOfWords = addToArray(word, arrayOfWords, arrayLength);
word = "";
} else word.push_back(c);
}
arrayOfWords = addToArray(word, arrayOfWords, arrayLength); // Don't forget the last word
for (int i = 0; i < arrayLength; ++i)
{
cout << arrayOfWords[i] << endl;
}
}
The array is unchanged, because you pass the pointer to the addToArray function, but it has no way to pass the new pointer back. You can fix this by changing the signature of the function to
void addToArray(string newWord, string *myArray[], int& arrayLength)
You also need to change the code accordingly, and fix problem with deallocation.
You can save yourself all the trouble and use std::vector in place of manually allocated dynamic array:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<string> arrayOfWOrds;
string temp;
while (getline(cin, temp))
{
cout << temp << endl;
arrayOfWOrds.push_back(temp);
}
cout << "Array" << endl;
for (size_t i = 0; i < arrayOfWOrds.size(); ++i)
{
cout << arrayOfWOrds[i] << endl;
}
}
string in="dasd adas ads adsada adsa asd ads",out;
stringstream ss(in);
vector<string> vr;
while(ss>>out)
{
vr.push_back(out);
//cout<<out<<endl;
}
for(int i=0;i<vr.length();i++)
{
cout<<vr[i]<<endl;
}
try doing this
I'm trying to read an unknown number of elements into the array, when my size reaches the current capacity, I call a function to double the size and copy the contents of the old array into a new array. I got my '&' but it seems it's still passing the array by value.
#include <iostream>
#include <fstream>
using namespace std;
void resize(int*&, int&);
int main() {
ifstream in("numbers.input");
int cap = 10;
double avg;
int total = 0;
int size = 0;
int *arr = new int [cap];
int temp;
for(int i =0; i <cap; i++){
in >> temp;
if(size >= cap) {
resize(arr,cap);
}
arr[i]=temp;
total += arr[i];
size++;
}
avg = (double) total/cap;
cout << cap <<endl;
cout << size <<endl;
cout << total <<endl;
cout << avg;
return 0;
}
void resize(int *&arr,int &cap) {
cap*=2;
int* newArr = new int[cap];
for(int i = 0; i < cap; i++){
newArr[i] = arr[i];
}
delete [] arr;
arr = newArr;
}
Everything you try to implement 'by hand' is already in
the standard library. Use std::vector<> which implements
a doubling/reallocation strategy very similar to what you're
proposing.
#include <fstream>
#include <vector>
int main() {
std::ifstream in("numbers.input");
std::vector<int> arr;
int temp;
while (in >> temp) { arr.push_back(temp); }
// process your data ...
}
See http://www.cplusplus.com/reference/vector/vector/
To answer the question more literally: Arrays are always passed
by reference, typically by passing a pointer to the first element.
Your resize function is taking the pointer by reference and will modify the value of the variable it is called with. However you have a number of bugs:
You copy cap items out of the old array, but you have already doubled cap, leading to an out of bound access and a possible crash.
Your resize function never gets called, due to a bug in your input loop. You should step through in a debugger (or at least add some trace cout calls) to work out what is going on. Try to figure this one out, if you can't let me know.
Your average is using cap as the divisor, that is not correct.
Note: You should add in your question that you can't use vector, because that would be the normal way to do this.
Note 2: In your question, you should also say exactly what is going wrong with your program - "seems to be passing the array by value" is a bit vague - why do you think it isn't passing by value?
im doing simple genetic algorithm uniform crossover operation . for that im using two arrays as parent and mother.i want concatenate the childs for getting the offsprings(childs).
i have problem in adding the arrays .any help plssss.i did it ubuntu
#include<iostream>
#include <fstream>
#include <algorithm>
#include<vector>
using namespace std;
int main()
{
int P[ ]={3,7,6,5,2,4,1,8};
int N[ ]={8,6,7,2,5,3,4,1};
int r= (sizeof(P)/sizeof(*P)) ;
int s= (sizeof(N)/sizeof(*N));
int val=r/2 ;
int t1[val],t2[val],t3[val],t4[val],n=0,p=0;
for(int m=0;m< val;m++)
{
t1[n]=P[m];
t2[n]=N[m];
n++;
}
for(int x=val;x< r;x++)
{
t3[p]=P[x];
t4[p]=N[x];
n++;
}
int* child=new int [val+val];
copy(t1,t1+val,child);
copy(t3,t3+val,child+val);
cout << child;
}
return 0;
}
This part is wrong:
int t1[val], t2[val], t3[val], t4[val]
You can only use constant values to declare the size of arrays.
You can either use a std::vector or dynamically allocate memory for the t-arrays.
std::vector<int> t1(val);
std::vector<int> t2(val);
for(int m = 0; m < val; m++)
{
t1[n] = P[m];
t2[n] = N[m];
n++;
}
There seem to be multiple errors in your code.
Variable length arrays are at present not supported in C++.
int val=r/2 ;
int t1[val]; // Not OK
In the second for loop I guess you meant p++ instead of n++;
Instead of manually doing all the memory allocation - deallocation, you should use std::vectors
cout << child; // This outputs the address of the pointer, not the entire array.