Im new to c++ and I dont know what this error means. It reads from a file and tries to store the values in a char * [].
The file contains:
5,Justin,19,123-45-6789,State Farm,9876,Jessica,Broken Hand,
This is my code.
void Hospital::readRecordsFile(){
std::ifstream fileStream;
fileStream.open(fileName); // Opens the file stream to read fileName
char * temp [8];
int i = 0;
while(!fileStream.eof()){
fileStream.get(temp[i],256,',');
i++;
}
i = 0;
for(char * t:temp){
std::cout << t << std::endl;
}
}
The error is at the line fileStream.get(temp[i],256,',');
You define an array of 8 pointers to char, but forget to allocate memory so that the pointers point to a valid chunk of memory:
char * temp [8]; // need then to allocate memory for the pointers
Because of this, in the line
fileStream.get(temp[i],256,',')
you end up using memory that's not yours.
Solution:
for(int i = 0; i<8; i++)
temp[i] = new char[256]; // we allocate 256 bytes for each pointer
Better though, use a std::vector<std::string> instead.
In the code you have right now it looks like you implicitly assume that the file has no more than 8 lines, which I find hard to believe. If your file has more than 8 lines, then you'll end up accessing the array of 8 pointers out of bounds, so you'll get another undefined behaviour (usually a segfault). That's why is much better to use standard STL containers like std::vector, to avoid all these headaches.
In case you MUST use pointers and want a variable number of lines, then you have to use a pointer to pointer,
char** temp;
then allocate memory for an enough pointers-to-char,
temp = new char* [1000]; // we believe we won't have more than 1000 lines
then, for each pointer-to-char, allocate memory
for(int i = 0; i < 1000; ++i)
temp[i] = new char[256];
At the end of the program, you must then delete[] in reverse order
for(int i = 0; i < 1000; ++i)
delete[] temp[i];
delete[] temp;
As you can see, it's getting messy.
You never allocated memory for each pointer in temp.
You probably want something like:
for (unsigned int i = 0u; i < 8; ++i)
{
temp[i] = new char[256];
}
The says that the temp variable points to 8 dynamically allocated byte buffers of 256 bytes each.
Related
In this code, an array of pointers newData is created in a for loop then it is pushed into a vector testData. The pointers are stored in the vector std::vector<testData*>.
My concern is that I need to make sure that the objects referenced by the pointers remain valid while the vector holds a reference to them. Do I lose this reference by calling the line newData = new unsigned char[frameSize]; in a for loop?
I mainly want to avoid copying the objects with a push_back.
How can I create an array of unsigned char* of random char (here I just use 'a') and then push these arrays to the vector?
int numFrames = 25;
int frameSize = 100;
std::vector<unsigned char*> testData;
unsigned char *newData;
for (int i = 0; i < numFrames; i++) {
newData = new unsigned char[frameSize];
for (int j = 0; j < frameSize; j++) {
newData[j] = 'a'; // fill the frame with random data, 'a' here
}
testData.push_back(newData);
newData = 0; // ??
memset(&newData, 0, frameSize); // ??
}
std::cout << " testData " << testData.size() << "\n";
Do I lose this reference by calling the line newData = new unsigned char[frameSize]; in a for loop?
No, if done correctly it's perfectly feasible.
The are some problems in your code though, in the line memset(&newData, 0, frameSize); // ?? you're setting the memory occupied by a pointer, which is usually no more than 8 bytes (depending on the architecture) with a size of 100 bytes, this invokes undefined behavior. You may wanted:
memset(&newData, 0, sizeof newData); // ??
But this wouldn't do what you need, nullifying the pointer would make you lose access to the data, you don't want that, and you are pushing the same pointer to the vector in each iteration, you'll end up with a vector filled with the same pointer pointing to the same data.
Moving its declaration inside the for loop would solve this. You're not copying any data, instead pushing a new pointer, pointing to a new memory location, into the vector, at each new iteration.
How can I create an array of unsigned char* of random char (here I just use 'a') and then push these arrays to the vector?`
Your code should look something like this:
Live demo
#include <iostream>
#include <vector>
#include <ctime>
int main()
{
srand(time(0)); //seed, not the best randomizer but does the job here
const size_t numFrames = 25; //sizes can/should be constant and unsigned
const size_t frameSize = 100;
std::vector<unsigned char *> testData;
for (size_t i = 0; i < numFrames; i++)
{
//in each iteration a new pointer
unsigned char *newData = new unsigned char[frameSize];
for (size_t j = 0; j < frameSize; j++)
{
newData[j] = 'a' + rand() % 26; //random alphabetic char
}
testData.push_back(newData);
}
std::cout << "testData " << testData.size() << "\n";
for (size_t i = 0; i < numFrames; i++) //test print
{
for (size_t j = 0; j < frameSize; j++)
{
std::cout << testData[i][j];
}
std::cout << "\n";
}
}
Needless to say you should delete the memory you previously allocated when you no longer need it.
If you want a better random engine you can check this post Generate random numbers using C++11 random library.
Some notes:
As you're probably aware the data pointed by newData pointers can't be treated as a string, aka, a null terminated char array because, of course, they're not null terminated.
You'll need to manually manage the memory you allocated, that is to say that the memory reserved manually will also have to be deleted manually, when you're done with it.
The code corrections are for your code as it is, but as WhozCraig correctly points out, you would probably be better off using STL containers all around instead of pointers.
I am trying to create an array, which doubles every time it is completely filled.
#include <iostream>
using namespace std;
int* array_doubler(int* array, int size){
int *new_array = new int[size*2];
for(int i = 0; i < size; i++){
new_array[i] = array[i];
}
delete[] array;
return new_array;
}
int main()
{
int N = 10; // Size of array to be created
int *array = new int[0];
for(int i = 0; i < N; i++)
{
if(array[i] == '\0')
array = array_doubler(array, i);
array[i] = i*2;
}
//Printing array elemensts
for(int i = 0; i < N; i++)
cout << array[i] << '\t';
cout << '\n';
return 0;
}
Problem is when I create dynamic memory with new, all the spots have the null character \0 value in them (not just the last spot). i.e. If i write:
int* p = new int[5];
then all the 5 blocks in memory p[0],p[1],p[2],p[3],p[4],p[5] have \0 in them, not just the p[5]. So the if(array[i] == '\0') in my main() calls array_doubler for every single iteration of for loop. I want it to fill the available spots in the array first and when it reaches the last element, then call array_doubler.
Problem is when I create dynamic memory with new, all the spots have the null character \0 value in them (not just the last spot).
Actually they have undefined values in them. 0 is a valid value for them to have, but tomorrow the compiler might suddenly decide that they should all have 1 instead of 0.
If you want to detect the end of an array, then you have to remember how big the array is. C++ doesn't do it for you. Actually, it does do it for you if you use std::vector, but I suppose that's not the point of this exercise.
I'm not sure why you'd want to do this, as std::vector offer this kind of feature, and are more idiomatic of c++ (see isocpp faq on why C-style array are evil).
One of the issue of C-style array is the fact that they donĀ“t know their own size, and that they don't have default value, thus stay uninitialized.
If for some reason you need to not use std::vector, the next best solution would be to wrap the array with it's size in a structure or a class (which is kinda what std::vector is doing), or to initialize your array using std::memset (which is the C function you would use if you were in C).
Do keep in mind that this is not considered as good practices, and that the STL offer plenty of solution when you need containers.
I have been trying to figure out this assignment for hours and can't grasp it yet. I'm trying to read in names from a txt document, which is working, and I need to store them in an char pointer array. Once the number of names is as big as the array size, I need to use REALLOCATION to make the array bigger (I can't use vector library).
I'm struggling with changing the name array size to make it bigger and deleting the old array from memory (it just crashes when I write delete [] names;).
Here is my currently broken code:
int numNames = 2;
char * names[numNames] = {};
ifstream namesFile("names.txt");
//get names from user, put names in ragged array
int i = 0;
while (i < numNames) {
if (namesFile.good() && !namesFile.eof()) {
//add name to ragged array
names[i] = new char[257];
namesFile >> setw(256) >> names[i];
i++;
if (i == numNames) {
//need a bigger array
numNames *= 2;
char * temp[20] = {};
for (int j = 0; j < numNames / 2; j++) {
temp[j] = names[j];
}
delete [] names;
names = temp;
}
}
else {
//end of file or corrupt file
break;
}
}
namesFile.close();
Any help is appreciated!
The following statement does not do any dynamic allocation. It just declares an array of pointers to char (char*) on a stack of size numNames. So, it is not dynamic by any means:
char * names[numNames] = {};
As such, you cannot change its size.
Instead you need to create a pointer to the array like the following:
char **names = new (char*)[numNames];
Same story for your temp down the road. Now you are free to delete/new and to assign pointers as well: names = temp.
Now, you need to read your char data from a file line by line and put it in the 'names' array. When you read a string, you can allocate space for it in the array member, i.e.
names[i] = new char [strlen(inputString) + 1]; // you need '+1' for termination char
and you can copy data from your string after allocation, i.e.
strcpy(name[i], inputString); // this is a standard 'c' string copy
you can also use std::copy or a for loop do do a copy or whatever. Another method is to use a standard 'c' malloc function to do allocation:
name[i] = (char *)malloc(strlen(inputString) + 1);
The difference is that when you would need to free memory, you would use delete[] name[i] in the first case and free(name[i]) in the second. Though it looks like you do not need to free the memory in your task.
Now you just have to figure out how to read from the file.
I'm new to C++, trying to follow a tutorial series to learn the language, the challenge given for allocating memory is to allocate memory for 26 chars and then fill them with the alphabet, abcde... etc.
I thought I knew the solution but ran into this error:
Invalid address specified to RtlValidateHeap( 00490000, 0049D9EC ) the part that is throwing me off is the program executes fully, a-z but still throws this error
Here is my code:
char c = 'a';
char *pChar = new char[26];
for (int i = 0; i < 26; i++, pChar++, c++) {
*pChar = c;
cout << *pChar << flush;
}
delete[] pChar;
Sorry if the question is worded poorly, I am new to both c++ and stackoverflow.
When you say delete[] pChar; you are in fact attempting to delete what pChar is currently pointing at, which is not the same spot as where it was originally allocated.
In short, when you allocate something with new it puts some data about the allocation (size of the allocation for example so you do not need to say delete[26] pChar; like you had to when C++ was new) usually to the left of the newly allocated memory, and it is probably interpreting things you have written (the alphabet) as that information when trying to use it to free the memory, which is of course not going to work.
You should store a copy of the original pointer to the memory you have allocated instead and use that to delete, or perhaps a better option, use i and subscripts to index via pointer arithmetic instead like:
char c = 'a';
char *pChar = new char[26];
for (int i = 0; i < 26; i++, c++) {
pChar[i] = c;
cout << pChar[i] << flush;
}
delete[] pChar;
The trouble is that when control leaves the loop, pChar points to a location one past the end of the array. You then call delete[] on that pointer, which is like putting a wrecking ball through the wrong house.
As already mentioned in the other answers, you cannot call delete[] on a pointer you have changed since calling new []. It's undefined behavior.
delete [] needs to get passed the exactly same pointer value as you had achieved when calling new[].
And here's the most simple fix, without need to change pChar:
#include <iostream>
int main()
{
char c = 'a';
char *pChar = new char[26];
for (int i = 0; i < 26; ++i) {
pChar[i] = c; // access the character by index ...
std::cout << pChar[i] << std::flush; // access the character by index ...
// ++pChar; DON'T change the original pointer
++c;
}
delete[] pChar;
return 0;
}
Live Demo
in c++ id like to read input into a c-style string one character at a time. how do you do this without first creating a char array with a set size (you don't know how many chars the user will enter). And since you can't resize the array, how is this done? I was thinking something along these lines, but this does not work.
char words[1];
int count = 0;
char c;
while(cin.get(c))
{
words[count] = c;
char temp[count+1];
count++;
words = temp;
delete[] temp;
}
Since you cannot use std::vector, I am assuming you cannot use std::string either. If you can use std::string, you can the solution provide by the answer by #ilia.
Without that, your only option is to:
Use a pointer that points to dynamically allocated memory.
Keep track of the size of the allocated array. If the number of characters to be stored exceeds the current size, increase the array size, allocate new memory, copy the contents from the old memory to new memory, delete old memory, use the new memory.
Delete the allocated memory at the end of the function.
Here's what I suggest:
#include <iostream>
int main()
{
size_t currentSize = 10;
// Always make space for the terminating null character.
char* words = new char[currentSize+1];
size_t count = 0;
char c;
while(std::cin.get(c))
{
if ( count == currentSize )
{
// Allocate memory to hold more data.
size_t newSize = currentSize*2;
char* temp = new char[newSize+1];
// Copy the contents from the old location to the new location.
for ( size_t i = 0; i < currentSize; ++i )
{
temp[i] = words[i];
}
// Delete the old memory.
delete [] words;
// Use the new memory
words = temp;
currentSize = newSize;
}
words[count] = c;
count++;
}
// Terminate the string with a null character.
words[count] = '\0';
std::cout << words << std::endl;
// Deallocate the memory.
delete [] words;
}
You asked for C-style array. Stack or dynamic allocation will not serve you in this case. You need to change the count of the array number in each time you add new element which is not possible automatically. You have to work around and delete and reserve the array each time a new chae is read. So you have to options:
Use std::vector (which was created for this purpose)
Duplicate what is inside std::vector and write it yourself during your code( which seems terrible)
std::vector solution:
std::vector<char> words;
words.reserve(ESTIMATED_COUNT); // if you you do not the estimated count just delete this line
char c;
while(cin.get(c)){
words.push_back(c);
}
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1;
char c;
while (cin.get(c))
{
if (c == '\n')
continue;
s1 += c;
cout << "s1 is: " << s1.c_str() << endl; //s1.c_str() returns c style string
}
}
You have two ways, first is to use an zero size array, after each input you delete the array and allocate a new one that is +1 bigger, then store the input. This uses less memory but inefficient. (In C, you can use realloc to improve efficiency)
Second is to use a buffer, for example you store read input in a fixed size array and when it get full, you append the buffer at the end of main array (by deleting and re-allocating).
By the way, you can use std::vector which grows the size of itself automatically and efficiently.
If you're set on using c-style strings then:
char* words;
int count = 0;
char c;
while(cin.get(c))
{
// Create a new array and store the value at the end.
char* temp = new char[++count];
temp[count - 1] = c;
// Copy over the previous values. Notice the -1.
// You could also replace this FOR loop with a memcpy().
for(int i = 0; i < count - 1; i++)
temp[i] = words[i];
// Delete the data in the old memory location.
delete[] words;
// Point to the newly updated memory location.
words = temp;
}
I would do what Humam Helfawi suggested and use std::vector<char> since you are using C++, it will make your life easier. The implementation above is basically the less elegant version of vector. If you don't know the size before hand then you will have to resize memory.
You need to allocate a string buffer of arbitrary size. Then, if the maximum number of characters is reached upon appending, you need to enlarge the buffer with realloc.
In order to avoid calling realloc at each character, which is not optimal, a growth strategy is recommended, such as doubling the size at each allocation. There are even more fine-tuned growth strategies, which depend on the platform.
Then, at the end, you may use realloc to trim the buffer to the exact number of appended bytes, if necessary.