Search code examples
carraysstringiochar

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


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

Solution

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