2013-02-06 44 views
0

這是一個C作業。我沒有要求任何人爲我這樣做,我只是碰壁了。這是明天到期的,我不知道如何繼續。我是一個初學者,我的頭開始受傷C編程assignmnt help:讀入並打印格式化

編寫一個ANSI C程序,它格式化文本,以便它很好地適合於給定數量的列。文本格式化程序必須右對齊輸入文本文件,以便右邊距以直線對齊,但有一個例外。最後一行是不正確的。此外,段落不會合並在一起。輸出線之間的空間應均勻分佈。

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

#define IN 1 
#define OUT 0 

/* 
    This is the start of the main pgoram which originated from the K & R word counter... 
    we comment to understand each part... 
*/ 
int main() 
{ 
    /* 
    * This is the pointer to the file object we will be readin in 
    * from... 
    */ 
    FILE   *ptr_file; 
    char   *outputbuf; 

    /* 
    * This variable will hold the maximum width of the line we are to 
    * output 
    */ 
    int width; 
    char eatspace; 
    char c; /* We read each character invidually */ 

    int state = OUT; 

    int nc = 0; /* This is the total count of all words in the document */ 
    int nl = 0; /* This is the total count of newlines in the document */ 
    int nw = 0; 
    int lw = 0; /* Count the total whitespaces spaces per line */ 
    int buff_offset = 0; /* Keep track of how many letters we are into the current output line */ 

    /* Opens a file stream for the .txt file to be read in */ 
    ptr_file = fopen("hollo_man.txt", "r"); 
    if ((fopen("hollo_man.txt", "r")) != NULL) { 
     /* 
     * This loop reads in one character at a time until the end 
     * of file 
     */ 

     /* Read the first line to get the width of the output */ 
     fscanf (ptr_file, "%i", &width); 
     outputbuf = (char*) malloc(width + 1); 
     //fscanf(ptr_file, "%c", &eatspace); 

     int prev_char_was_space = 0; 

     while ((c = fgetc(ptr_file)) != EOF) 
     { 
      ++nc; 
      if (c == '\n' || strlen(outputbuf) == width) 
      { 
       outputbuf[buff_offset] = '\0';  
       ++nl; 
       //    printf("Saw a newline, newline count is now: %i\n", nl); 
       /* Our buffer needs to be ended since we saw a newline */ 

       for(int i = 0; i < (width - buff_offset); i++) 
       { 
        printf(" "); 

       } 
       printf("%s\n", outputbuf); 

       memset(outputbuf, width, '\0'); 

       buff_offset = 0; 
       prev_char_was_space = 0; 

      } 

      /* This more verbose check is to see if there is other whitespace */ 
      else if (isspace(c)) 
      { 


       /* We only store one space between words in the output, this allows us to easily and evenly pad with white space later */ 
       if (!prev_char_was_space) 
       { 

        outputbuf[buff_offset] = c; 
        outputbuf[buff_offset + 1] = '\0';     
        buff_offset++;     

        lw++; 
        prev_char_was_space = 1; 
       } 
      } 
      else /* This was not a whitespace character so store it in the current line buffer */ 
      { 

       prev_char_was_space = 0; /* Keep track that we didnt have a whitespace for the next iteration */ 
       outputbuf[buff_offset] = c; 
       buff_offset++; 
       ++nw; 


      } 

     } /* End reading each character */ 

     /* This line should indeed print output to console for now */ 
     //fprintf(stderr, "ORIG LINE COUNT: %d\nORIG WORD COUNT: %d\nORIG CHAR COUNT: %d\n", nl, lw, nc); 
     /* Close our file and clean up */ 
     fclose(ptr_file); 
    } 

    return 0; 
} 

它所做的只是打印出一個空行。我想我需要另一個緩衝區,但我真的不知道。我將如何去打印它,然後均勻地分隔填充空格的單詞?我也不確定如何將每行打印到指定的寬度。任何幫助將不勝感激!

回答

2

首先不要撥打fopen("hollo_man.txt", "r")兩次,檢查您的if中的指針。

,那麼你應該通過字讀字的文件:

char words[1024]; 
char * next_word = words; 
while(fscanf(ptr_file, "%s", next_word) { 

計算它們的長度

size_t word_length = strlen(next_word); 
next_word += word_length + 1; 

,當你已經達到了必要的寬度打印出來:

total_length += word_length; 
if (total_length > maxColumns) { 
    size_t extra_spaces = total_length - word_length - 2; 

這有幫助嗎?

這裏是一個完整的解決方案:

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

void justify(FILE* in, FILE * out, int columns) { 
    char words[1024]; 
    char * next_word = words; 

    ssize_t total_length = 0; 
    size_t num_words = 0; 

    while (fscanf(in, "%s", next_word) == 1) { 
     size_t word_length = strlen(next_word); 
     next_word += word_length + 1; 
     num_words++; 
     total_length += word_length; 

     if (total_length + num_words > columns) { 

      size_t spaces_needed = columns - (total_length - word_length); 

      int minspoaces = 1; 
      if (num_words > 2) // avoids nasty floating point exception if no two words fit on a line 
       minspoaces = spaces_needed/(num_words - 2); 


      char * word_print = words; 

      size_t chars_printed = fprintf(out, "%s",word_print); 
      word_print += strlen(word_print) + 1; 
      size_t spaces_printed = 0; 
      ssize_t words_to_print = num_words - 2; 

      fflush(out); 

      while (words_to_print > 0) { 
       int spaces_to_print = minspoaces; 
       if (((spaces_needed - spaces_printed) % words_to_print) * 2 >= words_to_print) // spreads spaces out along the line 
        spaces_to_print++; 
       spaces_printed += spaces_to_print; 
       words_to_print--; 
       chars_printed += fprintf(out, "%*c%s", spaces_to_print, ' ', word_print); 
       word_print += strlen(word_print) + 1; 
       fflush(out); 
      } 
      fprintf(out, "\n"); 

      memmove(words, word_print, (total_length = strlen(word_print)) + 1); 
      num_words = 1; 
      next_word = words + total_length + 1; 
     } 

    } 

    char * word_print = words; 
    while (word_print != next_word) { 
     word_print += fprintf(out, "%s ", word_print); 
    } 

    fprintf(out, "\n"); 
} 

int main(int argc, char ** argv) { 

    int columns = atoi(argv[1]); 

    FILE * in = stdin; 

    if (argc >= 3 && argv[2]) { 
     in = fopen(argv[2], "r"); 
     if (!in) { 
      perror("fopen"); 
      return -1; 
     } 
    } 

    justify(in, stdout, columns); 

} 
+0

當我嘗試賦值total_length + = word_length時,在聲明結束處得到以下'error:program1.c:61:23:'error:invalid'+ =';你的意思是'='? size_t total_length + = word_length;' – freitazm

+0

+ =僅在更改值時有效。它意味着'total_length = total_length + word_length'。 '+ ='在初始化程序中無效。 –

+0

非常感謝你的幫助! – freitazm

2

有雙FOPEN的小問題,應減少到一個。

您的文件可能有一個格式是這樣的:

15 
The quick 
brown 

的問題是,你的邏輯是類似以下內容:

/* Opens a file stream for the .txt file to be read in */ 
ptr_file = fopen("hollo_man.txt", "r"); 
if (/*the file was opened correctly */) { 

     Read 'width' from the first word of the file; 
     Create a buffer exactly 'width'+1 in size; 

     while(get_a_character != EOF) { 
      increment_total_character_count; 
      if(character_is_newline) 
       increment_newline_count; 
       insert a '\0' in the output buffer; 
       reset the index we're inserting into the output buffer 
       prevCharacterIsSpace = false; 
      if(character_is_space) 
       if(previous_character_NOT_a_space) 
        put_character_in_output_buffer; 
        increment_word_counter; 
        prevCharacterIsSpace = true; 
      else 
       prevCharacterIsSpace = true; 
       put_character_in_output_buffer; 
       increment_nw (never used) 
     } 


     needed_spaces = (width - nc) % lw; 
     printf(" %s", outputbuf); 

如果輸入文件具有上述格式,寬度出現在它自己的行上,你正在閱讀的字符流是這樣的:

'15' (read as a unit with the %i) 
'\n' 
'T' 
'h' 
... 
'w' 
'n' 
'\n' 

您的字符閱讀循環將換行看作是第一個字符。它在輸出緩衝區中插入一個空值,將prevCharacterIsSpace設置爲false,然後繼續。如果你的文件格式符合我上面的文件格式,那麼你可能想通過閱讀'寬度'後,通過「吃」'\ n'來解決這個問題。

請注意,isspace函數對換行符返回true,所以現在換行符被放入輸出緩衝區的下一個位置,並且字計數器遞增(如果您取消註釋在程序底部的printf,您應該看到那個效果)。該修復可能只是爲了使if (isspace(c))成爲else if (isspace(c))

另一個問題是,您正在將每個單獨的行從文件複製到相同的緩衝區。因此,您無法顯示比輸入的最後一行更多的內容。您可能需要將您的打印代碼放在if (c == '\n') {區塊內。這將允許您在閱讀時打印每一行。代碼

無這裏處理打印右對齊文本,但是對於一個簡單的解決方案將是一個小環:

for (i = 0; i < (width - buff_offset); i++) 
    printf(" "); 

您打印輸出前直接插入。

+0

我隨你的意見去了,並在上面的代碼中加入了我的修改。輸出是正確的,但它不能正確打印。我不太確定如何描述輸出,它幾乎看起來「不完整」。 – freitazm