Exercise 13-15 - CBD page 467

Solution index                   Textual C program


/* Exercise 13-15, CBD, page 467. Programmed by Kurt Normark, 
   April 2003. */

#include <stdio.h>
#include <string.h>

int getwords(FILE *ifp, int k, char *words){
  char word[100];
  int count = 0;
  while (fscanf(ifp, "%s", word) != EOF && count < k){
    count++;
    strcpy(words,word);
    words += strlen(word); 
    *words++ = '\n'; 
  }
  words--;
  *words = '\0';
  return count;
}
  

int main(void) {
  char buffer[500];
  int no_of_words;

  FILE *input_file = fopen("text-input","r");
  no_of_words = getwords(input_file, 5, buffer);
  printf("%i words read:\n%s\n", no_of_words, buffer);
  fclose(input_file);

  return 0;
}

In this exercise we read k words from a file, and put them into a string with newlines in between them.
 

#include <stdio.h>
#include <string.h>
The file stuff is in the standard IO library, and therefore we include the stdio.h file.
 

int getwords(FILE *ifp, int k, char *words){
  char word[100];
  int count = 0;
  while (fscanf(ifp, "%s", word) != EOF && count < k){
    count++;
    strcpy(words,word);
    words += strlen(word); 
    *words++ = '\n'; 
  }
  words--;
  *words = '\0';
  return count;
}
The function getwords do the main work of our program. It reads from the open file pointed to by ifp (input file pointer). At most k words are read. The words that we read are put into the string words, which is the last parameter of the function. The function is not supposed to be called on an emtpy input file. We return the number of words read. This is useful in case the file contains less than k words. We will now go through the details of the function.
 

int getwords(FILE *ifp, int k, char *words){
  char word[100];
  int count = 0;
After the function head we declare a string of 100 chars, in which we collect single strings. We also declare a count variable, in which we count the number of words that we meet in the input.
 

while (fscanf(ifp, "%s", word) != EOF && count < k){
  count++;
  strcpy(words,word);
  words += strlen(word); 
  *words++ = '\n'; 
}
The while loop is central. In the boolean expression we use fscanf to read the next word from the input file. fscanf is is similar to the well-known scanf, with the only difference that fscanf takes an extra first parameter, namely the input file. The boolean expression states that we continue processing the file as long as fscanf delivers a word (the fscanf result is not EOF) and as long as count is less than k. fscanf may return a non-negative number as well as EOF (usually -1), but we do not expect it return 0 because we ask for words (in contrast to integers, for instance).

In the body of the loop, we increase count. Then we copy word into words using strcpy from string.h. strcpy will add a trailing '\0' character, but this character is disregarded in the way we increase the pointer words by the assignment: words += strlen(word). This is pointer arithmetic. Try instead words += strlen(word) + 1 to see the difference!

On the left-hand side of the assignment *words++ = '\n' the pointer words is first incremented with a postfix increment. (Remember that ++ has higher priority than *). Thus, words is incremented after the original pointer value of words is returned. Then a newline is inserted. In retrospect, it would have been better to write:
  *words = '\n';
  words++;
instead of
  *words++ = '\n'

 

words--;
*words = '\0';
return count;
The loop terminates if we have read k words, or if we encounter the end of the file before that. In any case we decrement the words pointer in order to overwrite the final '\n' character with the '\0' terminator of the string. It is important to end the words string properly. Try without, and see what happens.
 

int main(void) {
  char buffer[500];
  int no_of_words;

  FILE *input_file = fopen("text-input","r");
  no_of_words = getwords(input_file, 5, buffer);
  printf("%i words read:\n%s\n", no_of_words, buffer);
  fclose(input_file);

  return 0;
}
The main function opens a file and associates it with the file text-input. You can create this with your favorite text editor. Next, getwords (which we programmed above) is called, the results are printed, and the file is closed.
 


Generated: Wednesday, March 29, 2006, 12:33:13
This program dissection page is generated from an XML-in-LAML source file