Active data copying - c++

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);
}

Related

Generate random char/digit

I`m trying to found fastest way to generate random digit/char array.
char *randomGet(int num) {
srand(time(NULL));
const char ab[37] = { "0123456789ABCDEFGHIGKLMNOPQRSTUVWXYZ" };//Alphabet&Digit
char *targ = new char[num];
for (int i = 0; i < num; i++) {
strcat(targ, ab[rand() % 38]);
}
return targ;
}
So far I've come up with this, but it does not work (argument of type char is incompatible with parameter of type const char *).
Help me find the best solution to my problem. Ty.
strcat() takes a char* as input, but you are giving it a single char instead, thus the compiler error.
Also, the buffer that strcat() writes to must be null terminated, but your targ buffer is not null terminated initially, and you are not allocating enough space for a final null terminator anyway.
You don't need to use strcat() at all. Since you are looping anyway, just use the loop counter as the index where to write in the buffer:
Also, you are using the wrong integer value when modulo the return value of rand(). You are producing a random index that may go out of bounds of your ab[] array.
Try this instead:
char *randomGet(int num)
{
srand(time(NULL));
static const char ab[] = "0123456789ABCDEFGHIGKLMNOPQRSTUVWXYZ"; //Alphabet&Digit
char *targ = new char[num+1];
for (int i = 0; i < num; ++i) {
targ[i] = ab[rand() % 36];
}
targ[num] = '\0';
return targ;
}
I'd make two changes. First, make the internal source array static:
static const char ab[] = "0123456789ABCDEFGHIGKLMNOPQRSTUVWXYZ";
Note that this version does not specify the array size; the compiler will figure it out from the initializer.
Second, pass in a pointer to the target array:
void randomGet(char* targ, int num) {
static const char ab[] = "0123456789ABCDEFGHIGKLMNOPQRSTUVWXYZ";
for (int i = 0; i < num - 1; ++i)
targ[i] = ab[rand() % (sizeof ab - 1)];
targ[num - 1] = '\0';
}
This way, the caller decides how to allocate memory for the string.

C++ Dynamic Ragged Array

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.

How to set quantity of elements of the char array of a variable

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];
}

C++ Delete[] giving error in VS 2013

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".

Transfer an array of char via pointer to another temp array pointer

I'm learning to use pointer to copy char array.
I have the following code in C++. What I'm trying to do is to transfer and array (set1) using pointer to another pointer array (temp).
But when I try to print out (temp), it is not the same as (set1).
Transfer an array via pointer to another temp array pointer.
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
char set1[] = "ABC";
char* p = &set1[0];
int tempSize = 0;
char* temp = new char[256];
for (int i = 0; i < 3; i++)
{
*temp = *p;
cout << *temp; // ABC
++temp;
++tempSize;
++p;
}
cout << "\n";
for (int i = 0; i < tempSize; i++)
{
cout << temp[i]; // Why ABC is not printed?
}
delete [] temp;
return 0;
}
// Why ABC is not printed?
Because your pointer is travelling in undefined behavior region:
char* temp = new char[256];
...
++temp; // gone !!
On top of that,
you are not terminating the string with \0 in the end (may not be needed in your code)
delete[]ing this corrupt pointer in the end.
Since you are writing for learning purpose, I would suggest simple fix to your code:
char* const temp = new char[256];
^^^^^ ensures `temp` is not modifiable
Now use temp[i] for traversing purpose.
It's because in the loop copying the array, you change temp. After the loop, it points to one beyond the copied data.
Also, you forget to terminate the new allocated array. You should add the character '\0' at the end.
The problem is this line:
++temp;
You are incrementing the pointer and then write to it. In the end temp[i]; does not point to the beginning of your string, but to the end.
The easiest way to do this is to remove the first for loop with:
for (int i = 0; i < 3; i++)
{
temp[i] = set1[i];
}
temp[4] = '\0'; // don't forget to close the string
C-style strings have a null terminator - "ABC" contains four characters. Also, I'm not at all sure that the delete call on temp is valid - you have been incrementing it since it was 'newed'.