Reputation: 45
I tried to store strings in an array. But there is a mistake. My code is here:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <malloc.h>
const long long max_size = 2000; // max length of strings
const long long N = 40; // number of closest words that will be shown
const long long max_w = 50; // max length of vocabulary entries
int main(int argc, char **argv) {
FILE *f;
char st1[max_size];
char kelimeler[max_size];
char *kelimelerim[max_size]; //string array initialization here
char *bestw[N];
char file_name[max_size], st[100][max_size];
float dist, len, bestd[N], vec[max_size];
long long words, size, a, b, c, d, cn, bi[100];
char ch;
float *M;
char *vocab;
strcpy(file_name, argv[1]);
f = fopen(file_name, "rb");
if (f == NULL) {
printf("Input file not found\n");
return -1;
}
fscanf(f, "%lld", &words);
fscanf(f, "%lld", &size);
vocab = (char *)malloc((long long)words * max_w * sizeof(char));
for (a = 0; a < N; a++) bestw[a] = (char *)malloc(max_size * sizeof(char));
M = (float *)malloc((long long)words * (long long)size * sizeof(float));
if (M == NULL) {
printf("Cannot allocate memory");
return -1;
}
for (b = 0; b < words; b++) {
a = 0;
int sayac=0;
while (1) {
sayac++;
vocab[b * max_w + a] = fgetc(f);
if (feof(f) || (vocab[b * max_w + a] == ' ')) {
strcpy(kelimeler,&vocab[b * max_w + a-sayac+2]); //gets the string here
kelimelerim[b] = kelimeler; //and store it into string array here
printf("%s %lld\n",kelimelerim[b],b);
sayac=0;
break;
}
if ((a < max_w) && (vocab[b * max_w + a] != '\n'))
a++;
}
vocab[b * max_w + a] = 0;
for (a = 0; a < size; a++)
fread(&M[a + b * size], sizeof(float), 1, f);
len = 0;
for (a = 0; a < size; a++)
len += M[a + b * size] * M[a + b * size];
len = sqrt(len);
for (a = 0; a < size; a++)
M[a + b * size] /= len;
}
fclose(f);
int index;
for (index = 0; index < words; index ++){
printf("%s %d \n",kelimelerim[index ], index );
}
// here, the loop prints last string stored into array, for all indexes.
I deleted the unimportant rows. When I run the above code and print the kelimelerim array, the last string is printed for all indexes of the array. Where is my mistake? Could you help me, please.
Upvotes: 1
Views: 109
Reputation: 70931
This
kelimelerim[b] = kelimeler;
does not copy any data, but only stores the address of kelimeler
to kelimelerim[b]
. If then looping over kelimelerim[b]
's elements, only references to kelimeler
are found and as kelimeler
gets re-used for each iteration, it contains the string read last, which then in turn is printed for each of element of kelimelerim[b]
.
Update:
To fix this either replace kelimelerim[b]
by an array of "string" not just pointers to strings and do
strcpy(kelimelerim[b], kelimeler);
or dynamically create a real copy of kelimeler
by doing:
kelimelerim[b] = strdup(kelimeler);
Be aware that for this latter case each call to strdup()
allocates memory from the heap, which you shall free if not used anymore, by calling free()
on each elelment of kelimelerim
.
Also strdup()
isn't Standard C but a POSIX extension. You might need to #define
something to have it avaliable. See your implementation's documentaion on strdup()
for details.
If strdup()
is not available you might like to use this:
#include <stdlib.h> /* for malloc() */
#include <string.h> /* for strcpy() */
#include <errno.h> /* for errno */
char * strdup(const char * s)
{
char * p = NULL;
if (NULL == s)
{
errno = EINVAL;
}
else
{
p = malloc(strlen(s) + 1);
if (NULL == p)
{
errno = ENOMEM;
}
else
{
strcpy(p, s);
}
}
return p;
}
Upvotes: 0
Reputation: 29724
You are using char *vocab;
as uninitialized pointer. This results in undefined behavior. You have to initialize this pointer before using it with a valid memory ( e.g. using malloc
).
Upvotes: 0
Reputation: 500357
You never initialize vocab
, so the following has undefined behaviour:
vocab[b * max_w + a] = fgetc(f);
From that point on, all bets are off.
Upvotes: 1