1

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.

5
  • I dont get runtime error. As I said, I delete unrelated rows of the code. I have conflict with array of strings only. Commented Oct 26, 2014 at 14:36
  • Can you post the complete code? For instance, f is not declared.. Commented Oct 26, 2014 at 14:42
  • Post the complete code to avoid confusion. Commented Oct 26, 2014 at 14:44
  • You might also like to show us how you print the array. Commented Oct 26, 2014 at 15:26
  • I post the full code now. Thanks for your interests.. Commented Oct 26, 2014 at 15:34

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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

1 Comment

Thanks for your answer. Then, how can I fix this?
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.