C++ Random String return unexpected results - c++

I am trying to use a function to generate a char[] :
char* randString(){
const int len = 5;
char s[len] = {0};
static const char alphanum[] =
"0123456789"
"!##$%^&*"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
int stringLength = sizeof(alphanum) - 1;
for (int i = 0; i < len; ++i) {
s[i] = alphanum[rand() % stringLength];
}
return s;
}
the result is random and expected at return s
+ s 0x002df990 "XnQWp... char[5]
however, when i look at the value here:
char* rand = randString();
it contains strange values:
+ rand 0x002df990 "XnQWpÌÌÌÌÌÌÌÌÌÌÌ\x5" char *
did I do something wrong in the return?

You're declaring char s[] as a local variable. Local variables are destroyed when the function returns so returning a pointer to that variable returns a pointer pointing to junk data.
Fix this by allocating s dynamically:
char* s = new char[len];
Or you could pass a char* as a parameter and write your character to that array.
Just remember to add the terminating null character before returning.

Related

c (arduino) misc function returning char pointer

i found function in some code. Looks like that function generates some random number with variable length and returns char*
char* result = (char*)malloc(sizeof(char)*length);
randomSeed(analogRead(A0));
for (int i = 0; i < length; ++i)
{
result[i] = 48 + random(9);
}
result[length] = '\0';
When i tested it, i was surprised that this code works
But in theory char* is read only data, so this accessing to the elements should be incorrect.
Could someone explain it to me?
I think it will be better that the creator will use char array and then copy that memory to the char*
(i do not have link to code)
first of all your code does not work. You write outside the array in this line
result[length] = '\0';
the code shuold look like:
for (int i = 0; i < length - 1; ++i)
{
result[i] = 48 + random(9);
}
result[length - 1] = '\0';
char is just an integer type and it can be read or written.
if you want make it not writable (at least from the C++ point of view) you need to declare it as const.
const char a;
const char *ptr1;
char * const ptr2;
const char * const ptr3;
where:
ptr1 is a pointer to const char
ptr2 is a const pointer to char
ptr2 is a const pointer to const char

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.

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

Write access in char array

everyone!
I'm writing a simple char* string reverse. I get an error with writing access in line src[k] = src[n - k]; when I initialize my input array as a pointer : char * input= "string".
And it is fixed, when I put: char input[] = "string";
Why doesn't it work with a pointer? Thanks a lot!
Here is my code:
void reverse(char* src) {
if (src == NULL) {
return;
}
size_t n = strlen(src) - 1;
char swap;
for (int k = 0; k <= n/2; k++) {
swap = src[k];
src[k] = src[n - k];
src[n - k] = swap;
}
src[n + 1] = '\0';
}
It doesn't work with the pointer because the pointer points to the literal "string". String literals are not modifiable. When you use an array, the literal is copied into the array, which is modifiable.

Substring of char[] in c++

I have
char t[200];
cin.get(s, 200);
int i = 5;
int j = 10;
Is there any simple way to get substriing(i,j) from t beside copying every element seperately to the another array? No strings etc. just char t[200].
If you are allowed to modify t, you could set t[j] to 0 and then use t + i to get the substring.
If not, you are going to have to make a copy.
That said, why can't you just use std::string and save yourself the headache?
char* substr(char* arr, int begin, int len)
{
char* res = new char[len + 1];
for (int i = 0; i < len; i++)
res[i] = *(arr + begin + i);
res[len] = 0;
return res;
}
If you need only to read the data then t+i is what you want, alas you'll have to manage the length of your substring...
char *sub = t+i;
int len = j-i;
printf("%.*s\n",len,sub);
If you need to have a distinct copy of the substring, then you must copy.
This should work fine:
#include <string.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int main()
{
char t[200];
cin.get(t, 200);
int i = 5;
int j = 10;
char *to = (char*) malloc(j-i+1);
strncpy(to, t+i, j-i);
to[j-i]='\0';
cout << to;
}
You can use new instead of malloc like this:
char* to = new char[j-i+1];
This does not do any bounds checking to ensure the destination array is large enough
char newt[200];
// copy j-i chars from position t+i to newt array
strncpy(newt, t + i, j-i);
// now null terminate
newt[j-i] = 0;
Use two pointers to denote a range within the string.
char const * beg = t+i;
char const * end = t+j+1;
std::cout.write(beg, end-beg);
Or you can use a class that encapsulates this idea. There is something like that being proposed for the standard library. In the meantime, you can write your own, or you can use one from a library. For example, llvm::StringRef.
llvm::StringRef sref(t+i, j+1-i);
std:cout << sref;