How to read in the entire word, and not just the first character?

Viewed 113

I am writing a method in C in which I have a list of words from a file that I am redirecting from stdin. However, when I attempt to read in the words into the array, my code will only output the first character. I understand that this is because of a casting issue with char and char *.

While I am challenging myself to not use any of the functions from string.h, I have tried iterating through and am thinking of writing my own strcpy function, but I am confused because my input is coming from a file that I am redirecting from standard input. The variable numwords is inputted by the user in the main method (not shown).

I am trying to debug this issue via dumpwptrs to show me what the output is. I am not sure what in the code is causing me to get the wrong output - whether it is how I read in words to the chunk array, or if I am pointing to it incorrectly with wptrs?

//A huge chunk of memory that stores the null-terminated words contiguously
char chunk[MEMSIZE]; 

//Points to words that reside inside of chunk
char *wptrs[MAX_WORDS]; 

/** Total number of words in the dictionary */
int numwords;
.
.
.
void readwords()
{
  //Read in words and store them in chunk array
  for (int i = 0; i < numwords; i++) {
    //When you use scanf with '%s', it will read until it hits
    //a whitespace
    scanf("%s", &chunk[i]);
    //Each entry in wptrs array should point to the next word 
    //stored in chunk
    wptrs[i] = &chunk[i]; //Assign address of entry
  }
}
2 Answers

Do not re-use char chunk[MEMSIZE]; used for prior words.

Instead use the next unused memory.

char chunk[MEMSIZE]; 
char *pool = chunk; // location of unassigned memory pool

    // scanf("%s", &chunk[i]);
    // wptrs[i] = &chunk[i];
    scanf("%s", pool);
    wptrs[i] = pool;
    pool += strlen(pool) + 1;  // Beginning of next unassigned memory

Robust code would check the return value of scanf() and insure i, chunk do not exceed limits.

I'd go for a fgets() solution as long as words are entered a line at a time.

char chunk[MEMSIZE]; 
char *pool = chunk;

// return word count
int readwords2() {
  int word_count;
  // limit words to MAX_WORDS
  for (word_count = 0; word_count < MAX_WORDS; word_count++) {
    intptr_t remaining = &chunk[MEMSIZE] - pool;
    if (remaining < 2) {
      break; // out of useful pool memory
    }
    if (fgets(pool, remaining, stdin) == NULL) {
      break; // end-of-file/error
    }
    pool[strcspn(pool, "\n")] = '\0'; // lop off potential \n
    wptrs[word_count] = pool;
    pool += strlen(pool) + 1;
  }
  return word_count;
}

While I am challenging myself to not use any of the functions from string.h, ...

The best way to challenge yourself to not use any of the functions from string.h is to write them yourself and then use them.

your program reads the next word in the i-esim position of the buffer chunk, so you are getting the first letters of each word (as long as i doesn't get above the size of chunk) as each time you read, you overwrite the second and rest of the chars of the last word with the ones of the just read one. Then, you are putting all the pointers in wptrs to point to these places, making it impossible to distinguish the end of one string to the next (you overwrote all the null terminators, leaving only the last) so you will get a first string with all the first letters of your words but the last, which is complete. then the second will have the same string, but beginning at the second... then the third.... etc.

Build your own version of strdup(3) and use chunk to store temporarily the string... then make a dynamically allocated copy of the string with your version of strdup(3) and make the pointer to point to it.... etc.

Finally, when you are finished, just free all the allocated strings and voilĂ !!

Also, this is very important: read How to create a Minimal, Complete, and Verifiable example as it is very frequent that your code lacks of some errors that you have eliminated from the posted code (you don't normally know where the error is, or you would have corrected it and no question here, right?)

Related