2013-02-06 2 views
0

이것은 C 지정입니다. 나는 나를 위해 이것을 할 사람을 요구하지 않고있다, 나는 단지 벽에 부딪쳤다. 내일 끝날 예정이며 진행 방법을 모르겠습니다. 나는 초보자이고 상처를 입기 시작한다.C 프로그래밍 할당 도움말 : 읽기 및 인쇄 형식

주어진 수의 열에 잘 맞도록 텍스트의 서식을 지정하는 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에서 포인터를 확인하십시오. 그 길이 계산

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

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

을 당신이 도달 할 때 필요한 폭을 인쇄 :

당신은 단어에 의해 단어에서 파일을 읽어야합니다

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 :'오류가 발생합니다 : 선언의 끝에서'+ = '이 잘못되었습니다. '='을 의미 했습니까? size_t total_length + = word_length; ' – freitazm

+0

+ =은 값을 변경할 때만 유효합니다. 'total_length = total_length + word_length'를 의미합니다. '+ ='는 초기화 프로그램에서 유효하지 않습니다. –

+0

모든 도움을 주셔서 대단히 감사합니다! – freitazm

2

하나에 삭감해야한다 이중하면 fopen의 사소한 문제있다 : 여기

는 완벽한 솔루션입니다.

파일은 아마 이런 형식 뭔가있다 : 입력 파일 위의 형식은

/* 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 
The quick 
brown 

문제는 논리는 다음과 같은 것이 있다는 것이다을 그 너비에 나타나는 너비는 다음과 같습니다.

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

당신의 character-reading-loop는 줄 바꿈을 첫 문자로 본다. 출력 버퍼에 null을 삽입하고 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