First element of array (rest are fine) is a non-value half the time after shuffle
Author |
Message |
np_123
|
Posted: Tue May 09, 2017 1:18 am Post subject: First element of array (rest are fine) is a non-value half the time after shuffle |
|
|
The problem I am having is that I'm getting weird output when I try to shuffle an array of 'strings'.
When the array contains {"hi", "hola", "amigo"} half the time I get the same back, the other half this {"8y@", "hola", "amigo"} where @ is a weird character looking like a skinny rectangle.
The method giving problems is the shufflestring method below. I've omitted for clarity two interface methods that don't modify anything:
C: |
char **arr;
shufflestring(arr, sz); /*sz is just length of the array*/
/* Modern Fisher-Yates shuffle */
void shufflestring(char *a[], int n) {
srand((unsigned)time(NULL));
for (int i = n - 1; i > 0; i--) {
int j = rand() % (i + 1);
char *temp;
temp = a[i];
a[i] = &a[j];
a[j] = &temp;
}
}
|
the exact same code works if instead of char** (array of 'strings' is what it's supposed to be) it's double a[] in the shuffle method and double* a being passed to it.
for example these work fine:
C: |
/*Example1*/
char *str[5] = { "help", "hola", "hi", "amigo", "hitme"};
shufflestring(str, 5);
/* Modern Fisher-Yates shuffle */
void shufflestring(char *a[], int n) {
srand((unsigned)time(NULL));
for (int i = n - 1; i > 0; i--) {
int j = rand() % (i + 1);
char *temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
/*Example2*/
double *arr;
shufflereal(arr, sz);
/* Modern Fisher-Yates shuffle */
void shufflereal(double a[], int n) {
srand((unsigned)time(NULL));
for (int i = n - 1; i > 0; i--) {
int j = rand() % (i + 1);
double temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
|
|
|
|
|
|
|
Sponsor Sponsor
|
|
|
Insectoid
|
Posted: Tue May 09, 2017 3:20 pm Post subject: RE:First element of array (rest are fine) is a non-value half the time after shuffle |
|
|
I notice your char** example uses & in the swap, while your char*[] example does not. It's a long time since I've worked with C, but when you get random-looking strings, it's due to a pointer error. a[j] is already a pointer and doesn't need to be dereferenced. The reason your int example works is you are swapping the data directly, whereas your first looks like you're trying to swap pointers.
|
|
|
|
|
|
np_123
|
Posted: Tue May 09, 2017 4:57 pm Post subject: Re: First element of array (rest are fine) is a non-value half the time after shuffle |
|
|
yes, thanks, I've gotten rid of the & now, but the same problem still occurs with one exception: instead of a garbage string the first element ends up empty. And I do agree it's a pointer error of sorts.
I can't figure out how to test the values in an dynamic array (im compiling, debugging using VS) but I'm starting to think that maybe the 'array of strings' that I wish to pass to the method isn't being created/stored properly. Reasoning: when I attempt to DebugOutputString(arr[0]) it crashes, but DebugOutputString(arr) works
The following methods are the relevant top-level method calls that initiate everything
Note: OOTaddr is an alias for char *, OOTint -> long, ADDR_SIZE == 1; (unfortunately the MyExecutorScan isn't code I wrote so while I 'mostly' understand what's happening, I can't really explain it)
C: |
void MIO_sort_sortstring(OOTaddr *sp)
{
char **arr;
OOTint sz;
MyExecutorScan(sp, "AI", &arr, &sz);
MIOSort_sortstring(arr, sz);
}
static void MyExecutorScan (OOTaddr *sp, const char *param, ...)
{
const char *pf = param;
va_list curr_arg;
va_start(curr_arg, param);
while (*pf)
{
switch(*pf)
{
case 'r':
// Skip the function result stack position
sp += ADDR_SIZE;
break;
case 'A':
{
OOTaddr *arg_arrayp = va_arg(curr_arg, OOTaddr *);
*arg_arrayp = (OOTaddr) *sp;
sp += ADDR_SIZE*2;
}
break;
case 'I':
{
OOTint *arg_intp = va_arg(curr_arg, OOTint *);
*arg_intp = *((OOTint *) sp);
sp += INT_SIZE;
}
break;
} // switch
pf++;
} // while
va_end(curr_arg);
} // MyExecutorScan
|
Description: |
includes methods and code enough for a partial trace and comparison between the working int array sorting and broken 'string' array |
|
Download |
Filename: |
int_vs_string_code.c |
Filesize: |
2.26 KB |
Downloaded: |
230 Time(s) |
|
|
|
|
|
|
np_123
|
Posted: Tue May 09, 2017 9:23 pm Post subject: Re: First element of array (rest are fine) is a non-value half the time after shuffle |
|
|
I'm afraid it might have been a wild goose chase. The 'bug' seems to be not in my code, but in the program I'm extending (it's the OpenTuring project source, I doubt anyone's looked at that in years).
So what I gather the program is supposed to do is place/leave arguments on a stack frame which I later grab via pointer to the stack.
However, it appears to leave just the first element of the array on the stack at the and the rest I can't find.
How I came to that conclusion: DebugOutputString(*sp) prints hi ; and *(sp+2) is 3. (given the input i mentioned in the first post) Offsetting the pointer via *(sp + x) with values from -2 to 5 I can't find any other meaningful data
I don't honestly know if there's anything I can do to fix it without going into a bunch of obscure code. Unless there's some pointer offsetting magic I'm missing
|
|
|
|
|
|
np_123
|
Posted: Wed May 10, 2017 12:22 am Post subject: Re: First element of array (rest are fine) is a non-value half the time after shuffle |
|
|
and solved it - each further element of the array had an offset of 256.
as in, if 'hi' is at address x, hola is at x+256... meaning: *(sp) == "hi" and *(sp) + 256 == "hola"
I'm thinking the number 256 should be more than convenience, but doesn't ring any bells at the moment.
If anyone can confirm whether an offset of 256 (maybe it's a default string length/memory allocation?) can be assumed that'd be amazing
|
|
|
|
|
|
|
|