I am trying to remove a `const char *
int len = str.length();
const char * c = str.c_str();
unsigned short * s = new unsigned short[len];
for (int i = 0; i < len; i++) {
s[i] = c[i] - '0'; // I dislike this cheat
}
delete[] c; // Gives error.
c is also not used after it is deleted.
I am newer to C++ and I am trying to learn the delete operator and it is not going so well :/
I don't support the usage of new and delete in cases like these, but to point out your error, you're deleting memory not allocated via new.
You probably meant to write delete[] s;
(Because s is allocated via new[])
Also, s could easily be a std::vector<unsigned short>:
// Initializes a vector of unsigned shorts with a specified size.
std::vector<unsigned short> s(len);
const char * c = str.c_str();
delete[] c; // Gives error.
c is a pointer to the contents of str that's still owned and managed by the str object itself, may not be dynamically allocated (e.g. it could be a pointer to a Short String Optimisation buffer internal to the str object), let alone by new[], and even if it happens to be the str object will do a delete[] when it goes out of scope or has copied the data to a larger buffer for whatever reason. Summarily, after calling c_str() you can use the pointer until the str object is resized or "destructed", but don't need to do any clean-up yourself.
Looking at the rest of your code...
int len = str.length();
const char * c = str.c_str();
unsigned short * s = new unsigned short[len];
for (int i = 0; i < len; i++) {
s[i] = c[i] - '0'; // I dislike this cheat
}
delete[] c; // Gives error.
...the only error per se is that you delete[] c, but you don't delete[] s and probably should somewhere, some time after it's no longer needed.
That said, you can use std::vector to store the ASCII codes like this (for C++11):
std::vector<unsigned short> s;
for (char c : str)
s.push_back(c - '0');
If you don't have C++11, then:
for (int i = 0; i < str.length(); ++i)
s.push_back(c[i] - '0');
...or if you want to try iterators...
std::vector<unsigned short> s;
for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
s.push_back(*i - '0');
You could also use std::copy with an inserter, more declarative but a bit over-the-top IMHO:
std::copy(str.begin(), str.end(), std::back_inserter(s));
No need to delete c, it's only a a pointer to an array (that contains a null-terminated sequence of characters of "str").
The array is still stored in variable "str".
Related
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
How to set quantity of elements of the char array of a variable?
This is my code:
long int len = strlen(qq);
//char buff[10];
//sprintf(buff, "%d", len);
//MessageBoxA(0,buff,0,0);
char key[len] = "12345678901234567890123456789..";//error
char crypt[len];//error
for (int i = 0; i < len; i++) {
crypt[i] = text[i] ^ key[i];
}
In C++ an array can only be staticly sized using a constant variable that is known at compile time, which your len is not. Note that some compiler extensions DO allow this, as it's allowed in C. But for pure C++ you instead can use dynamic memory allocation (this allocates on the heap instead of the stack):
char* key = new char[len];
char* crypt = new char[len];
Note that a char* can be used the same as a char[] (you can still use array indexing, the rest of your code remains unchanged).
Because the array is now allocated on the heap, to avoid memory leaks you must manually free the memory when you no longer need it using delete e.g. at the end of the function after you loop:
delete[] key;
delete[] crypt;
Since you specified the winapi tag, it may be that the CString class would be a viable solution.
For your key though, you don't even need to allocate an array dynamically. You could use the modulo operator:
static const char key[] = "1234567890";
const size_t keyLength = strlen(key);
CString crypt(0, len);
for (int i = 0; i < len; i++) {
crypt[i] = text[i] ^ key[i & keyLength];
}
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.
so I'm working on a project that I have to read contents from a file and then analyze them. But I'm having a problem with getting the string out of a pointer that contains the address to what I need.
string lePapel(vector<char> vec){
string *str, s;
int i, j = 0;
vector<char> aux;
aux.resize(6);
for (i = 57; i <= 62; i++){
aux[j] = vec[i];
j++;
}
str = new string[aux.size()];
for (i = 0; i < 6; i++){ str[i] = aux[i]; }
return s;
}
So, the file contains in the array positions from 57 to 62 the word: ABCB4, but when returning the string s my output is A only as expected because of the pointer.
The thing is that I have been trying to find a solution and storing the whole content from vec[57] to vec[64] into the string s and returning it, and the closest that I got to returning anything plausible was using a pointer.
So, now to my question, how can I iterate the *str pointer and copy the whole content to s and return it?
Thanks in advance
I'd suggest you to not use pointers on string in your case. The following code is probably what you want :
#include <iostream>
#include <string>
#include <vector>
using namespace std;
string lePapel(vector<char> vec){
int j = 0;
vector<char> aux;
aux.resize(6);
for (int i = 57; i <= 62; i++){
aux[j] = vec[j];
j++;
}
string str;
str.reserve(6);
for (int i = 0; i < 6; i++){ str.push_back(aux[i]); }
return str;
}
int main() {
char x[5] = {'A', 'B', 'C', 'B', '4'};
vector<char> vec(x, x + 5);
string s = lePapel(vec);
cout << s;
return 0;
}
Tested here : Tested code
About reserving space to your vector : c++ vector::reserve
Same for strings : reserve for strings
The dynamic array of string objects and the whole aux vector seem completely needless here (unless there's some other purpose for them in your code). Additionally, str is currently causing a memory leak because you never delete it when you're finished.
A much simpler approach is just to append the characters one-at-a-time to the s string object (assuming it's a std::string):
string lePapel(vector<char> vec) {
string s;
for (int i = 57; i <= 62; i++) {
s += vec[i];
}
return s;
}
There are various ways to make the code even shorter (and more efficient) than that though, if you really want to.
EDIT: If you still need/want to iterate your dynamic array and concatenate the contents into s, here's how you could do it:
for (i = 0; i < 6; i++) s += str[i];
delete [] str; //<-- very important!
Short answer, you don't want a string * you want a char *. What you created is a string array. String objects contain a pointer to the char * data you are trying to capture. Also, the sizeof(std::string) (8 bytes in size) is a lot bigger than sizeof(char) (1 byte in size) the second character you store is 8 bytes away from the first character instead of being adjacent.
There are a lot of other C++ style and safety concerns, but I'll stick with the question. ;)
Is this expression correct?
{
char a;
char *temp;
for(int j = 0; j < len; j++)
{
strcpy(&temp[j], (char*)a);
}
}
in this code a gets updated externally by the user input/key stroke. I want to copy all incoming/updated a to the temp as an entire string.
Since 'a' in your example is not null-terminated and you want to assign a single character in string buffer, you can do:
int const buffer_size = 5;
char a = 'c';
char *temp = new char[buffer_size]; // Remember to allocate your string buffer
temp[index] = a;
// .....
delete[] temp; // free buffer.
index is an int which you can use to keep track of next position in buffer.
No for a few reasons:
temp isn't initialised, it's pointing to some random location and doesn't have any memory allocated for it, so you're just going to be writing over a random part of memory (and/or crash).
a is a single char and you're treating it's value as a string (char*) using strcpy (I'm assuming you meant (char*)&a which is still wrong).
strcpy continues copying chars from the source (a) to the destination until it hits a '\0' in the source...which could be anywhere since a is not a NUL terminated string but a char.
If you want to write/append a single char to a string/buffer you just do buffer[position] = character, where buffer is a char[] or a char* pointing to a block of allocated memory, position is the position in the buffer you want to stick the char, and character is obviously that char.
Anyway, I've got no idea what you're trying to do or the logic behind why you're trying to do whatever it is you're trying to do like this.
EDIT: And also you have this tagged as C++, why aren't you using std::string and std::cin if you are in fact using C++?
Your code is wrong in so many ways:
You cannot cast a char to a char*.
You have to do something like this: (char *)&a; and since a is a char, you don't need to cast it at all.
You don't need to strcpy it. You can just do something like:
temp[j] = a;
char *temp has not associated memory assigned to it. So you need to do something like this: char *temp = malloc(sizeof(char) * len);
Complete code here:
{
char a = myFunToGetInput();
char *temp = malloc(sizeof(char) * len));
for(int j = 0; j < len; j++) {
temp[j] = a;
}
}
Or if you have used memset before:
{
char a = myFunToGetInput();
char *temp = malloc(sizeof(char) * len));
memset(temp, (unsigned char)a, len);
}