2010-10-21 22 views
15

Đây là một K & R tập thể dục (1-13) ...In một Histogram dựa trên độ dài từ (C)

"Viết một chương trình để in một histogram chiều dài của các từ trong nó Thật dễ dàng để vẽ biểu đồ với các thanh ngang ngang; hướng dọc là khó khăn hơn. "

Phần này nói về mảng và thành thật mà nói, tôi không chắc là tôi đã hiểu hết. Tất cả mọi thứ cho đến thời điểm này là khá dễ nắm bắt, điều này là không.

Dù sao, tôi đang cố gắng tạo biểu đồ với thanh ngang trước tiên. Một khi tôi nhận được rằng tôi sẽ cố gắng theo chiều dọc, nhưng ngay bây giờ tôi thậm chí không chắc chắn nơi để bắt đầu với phiên bản dễ dàng. (. Tôi đã ngủ trên đó, tỉnh dậy, và vẫn không thể có được nó)

tôi vẽ một ví dụ về những gì chương trình sẽ ra:

---------------------------------------------------------------- 
001|XX 
002|XXXX 
003|X 
004|XXXXXXXXXX 
005|XXXXXXXXXXXXXXXXXXXXXXXXX 
006|XXXX 
007|X 
008| 
009|XXXXXXXXX 
010|XXX 
>10|XXXX 
---------------------------------------------------------------- 

Và cố gắng để phá vỡ nó (chương trình) xuống trong các phần. Đây là những gì tôi đã đưa ra:

  1. PRINT TOP BIÊN GIỚI
  2. IN LOẠI, IN X mỗi lần điều kiện là đúng, IN NEWLINE, REPEAT.
  3. PRINT BOTTOM BIÊN GIỚI

Nhưng tôi càng nghĩ về nó càng ít Tôi nghĩ rằng đó là cách nó sẽ làm việc (vì getchar() đi qua một ký tự cùng một lúc, và nó sẽ không có khả năng đi sao lưu để đặt X vào đúng danh mục.) Hoặc ...

... Tôi thực sự bối rối về cách giải quyết vấn đề này. Dưới đây là như tôi đã có thể nhận được mã khôn ngoan:

#include <stdio.h> 

#define MAXWORDLENGTH 10 

// print a histogram of the length of words in input. horizontal bar version 

int main(void) 
{ 
    int c; 
    while ((c = getchar()) != EOF) { 

    } 

    return 0; 
} 

Ai đó có thể giúp khai sáng cho tôi? Không nhất thiết với mã, có thể chỉ là mã giả, hoặc với một số từ "từ khôn ngoan" như những gì tôi cần làm, hoặc suy nghĩ, hoặc một cái gì đó. Đây chỉ là một hòn đá thực sự lớn trên đường và tôi muốn vượt qua nó: /.

(Tôi sẽ kiểm tra lại sau 30 phút)

+0

Không hẳn là một bản sao, nhưng bạn có thể tìm thấy sự giúp đỡ trong [làm thế nào để vẽ một biểu đồ trong c] (http://stackoverflow.com/questions/3836987/) và [Tần số Histogram trong C] (http://stackoverflow.com/questions/1413644/). – dmckee

+0

Tôi thích cách bạn nghĩ! Bạn đang thiếu một cái gì đó, tuy nhiên. Xem câu trả lời của tôi dưới đây. – slezica

+3

Loại vấn đề này khiến tôi phát điên khi lần đầu tiên tôi học chương trình (mà tôi đã làm trong C). Bài học, mà Kernighan thường lặp lại trong các cuốn sách khác của ông, là: suy nghĩ về dữ liệu, chứ không phải mã. –

Trả lời

7

Tôi yêu mã giả! Một số suy nghĩ tốt ở đó, nhưng bạn vẫn không đặt hàng đúng chương trình của bạn.

Như bạn đã nói, bạn không thể đọc được văn bản, quay lại và in X trong một hàng cụ thể. Nếu chúng ta thiết lập rằng nó không thể được thực hiện, thì không còn cách nào khác ngoài việc biết tất cả các giá trị của biểu đồ trước đó.

Vì vậy, bạn nên nghĩ rằng chương trình của bạn có hai phần (và bạn sẽ thực hiện loại phân chia này trong thực tế mọi chương trình bạn viết): đầu tiên, một phần sẽ tính toán; và sau đó một phần sẽ xuất chúng theo một định dạng nhất định (biểu đồ).

Mẹo này sẽ giúp bạn bắt đầu! Nếu bạn cần trợ giúp thêm, hãy bình luận bên dưới.

+0

+1 Đây là nơi tốt nhất để bắt đầu.Phân chia nhiệm vụ thành các phần logic của nó và giải quyết chúng một lần. – bta

+0

Tôi đồng ý với bta. Tôi phải thừa nhận tôi đã không mong đợi rất nhiều thông tin từ tất cả mọi người (cảm ơn bạn!), Nhưng đó là một chút áp đảo vì vậy tôi sẽ gắn bó với điều này bây giờ (tôi sẽ đọc tất cả mọi người cuối cùng mặc dù :-)) @Santiago Lezica - Bây giờ tôi đã bán xong mã với lời khuyên của bạn, nó trông như thế nào? http://fpaste.org/7ELL/ - Tôi có đi đúng hướng không? – Matt2012

+0

Vâng, bạn đang có! Điều đó có vẻ tốt, cấu trúc tốt. Hai điều: đầu tiên, suy nghĩ về những gì bạn phải làm khi STATE == IN, và những gì bạn có khi trạng thái thay đổi từ IN sang OUT. Thứ hai, hãy xem xét rằng văn bản của bạn có thể không kết thúc bằng dấu trống (dấu cách, tab, dòng mới) và bạn cũng phải xem xét từ cuối cùng khi tìm thấy EOF. – slezica

1

Để biểu đồ độ dài từ, bạn sẽ cần phải biết độ dài từ.

  • Làm thế nào để bạn xác định một từ?
  • Bạn có thể đo chiều dài của một từ bằng cách nào? Bạn có thể làm điều đó một nhân vật tại một thời điểm khi bạn đọc các dòng, hoặc bạn nên đệm đầu vào sử dụng strtok hoặc một cái gì đó tương tự?

Bạn sẽ cần phải tích lũy dữ liệu về số lần xuất hiện của mỗi độ dài xảy ra.

  • Làm cách nào bạn lưu trữ dữ liệu này?

Bạn sẽ cần xuất kết quả dưới dạng dễ chịu. Điều này là khó sử dụng nhưng không khó.

3

Tôi khuyên bạn nên đơn giản hóa vấn đề bằng cách giải quyết vấn đề cho trường hợp một từ trên mỗi dòng, vì vậy bạn có thể sử dụng fgets. Đây là cách để "eat up" lines that are too long.

Sau đó, thông thường, cấu trúc dữ liệu trung tâm là chìa khóa để giải quyết vấn đề. Cấu trúc dữ liệu bạn cần là một mảng sử dụng như bảng tần số:

int freq[11]; 

Trong freq[1], lưu trữ các số từ/dòng có độ dài 1, trong freq[2] những chiều dài 2, vv, và trong freq[0] những chiều dài > 10. Bạn không cần lưu trữ các từ vì phần còn lại của chương trình chỉ cần chiều dài của chúng. Viết ra các biểu đồ nên được dễ dàng ngay bây giờ.

Tôi hy vọng điều này không phải là quá nhiều của một spoiler.

1

tôi sẽ liên kết các câu trả lời dưới đây nhưng kể từ khi bạn hỏi để biết chi tiết phím có vẻ là này

sử dụng một mảng có độ dài tức là có một mảng với mỗi phần tử được khởi tạo bằng không giả MAX wordlength vào khoảng 30 .. .

* có một lá cờ trong khi trong lời nói và tăng số đếm mỗi khi một khoảng trắng là không gặp phải

* một lần ra khỏi lá cờ từ được thiết lập để "out" và chữ tương ứng mục chỉ số chiều dài trong mảng được tăng lên tức là nếu bộ đếm chiều dài từ là w_ctr sử dụng

array[w_ctr]++ 

* sử dụng mảng làm bảng tham chiếu cho mỗi dòng trong một vòng lặp để in mỗi dòng trong biểu đồ để bạn có thể sử dụng mảng và bây giờ có thể xác định thời tiết 'X' trong biểu đồ được chèn vào hay không

EDIT: xin lỗi tôi đã không đọc câu hỏi đúng nhưng ý tưởng đơn giản hơn cho biểu đồ dọc và điều tương tự có thể được sử dụng.

sau khi bước cuối cùng chỉ in các biểu đồ ngang cho đến khi truy cập vượt quá wordlength hiện được in

for(ctr=0;ctr<array[current_wordlength];ctr++) 
    printf('X');  

End


bản gốc là ở đây http://users.powernet.co.uk/eton/kandr2/krx113.html

CLC-wiki cũng là một địa điểm xem nhận xét để biết chi tiết.

+0

Trang web đó đã lỗi thời/không được duy trì, xem cùng một trang trên [CLC-wiki] (http://clc-wiki.net/wiki/K%26R2_solutions:Chapter_1:Exercise_13). – schot

+0

@schot Có nó là như vậy tôi đã thêm liên kết của bạn tôi đã chỉ cho cred cho nguồn từ nơi tôi đã học được điều này một thời gian trước đây :) – Siamore

0

Bạn nên tách 2 vấn đề của mình trong các chức năng, như:

void gethist(char *s, int *hist, int len) 
{ /* words here breaks on spaces (' ') */ 
    char *t; 
    for(t=strtok(s," ");t;t=strtok(0," ")) 
    if(*t) 
     hist[ strlen(t)>len-1?len-1:strlen(t)-1 ]++; 
} 

void outhist(int *hist, int len) 
{ 
    int i; 
    for(i=1; i<=len; ++i) 
    { 
    char *s = calloc(1,5+hist[i-1]); 
    sprintf(s,"%03d|", i); 
    memset(s+4, 'X', hist[i-1]); 
    puts(s); 
    free(s); 
    } 
} 

sau đó dễ dàng của nó trong chính bạn:

int main(void) 
{ 
    int c, hist[11] = {}; 

    char *s = calloc(1,1); 
    while ((c = getchar()) != EOF) { 
    s = realloc(s, 2+strlen(s)); 
    s[ strlen(s)+1 ] = 0; 
    s[ strlen(s) ] = c; 
    } 

    gethist(s,hist,11); free(s); 
    outhist(hist,11); 

    return 0; 
} 
2

Đoạn code dưới đây in một biểu đồ ngang chỉ sử dụng bộ công cụ cơ bản được cung cấp bởi cuốn sách cho đến nay:

#include<stdio.h> 

/* Prints a horizontal histogram of the lengths of words */ 

#define MAX_WORDS 100 
#define IN 1 
#define OUT 0 

main() 
{ 
int c, length, wordn, i, j, state, lengths[MAX_WORDS]; 
wordn = length = 0; 
state = OUT; 
for (i = 0; i < MAX_WORDS; ++i) lengths[i] = 0; 

while ((c = getchar()) != EOF && wordn < MAX_WORDS) 
{ 
    if (c == ' ' || c == '\t' || c == '\n') 
     state = OUT; 

    else if (wordn == 0) 
     { 
     state = IN; 
     ++wordn; 
     ++length; 
     } 

    else if (state == IN) 
     ++length; 

    else if (state == OUT) 
     { 
     lengths[wordn] = length; 
     ++wordn; 
     length = 1; 
     state = IN; 
     } 
}  

lengths[wordn] = length; 

for (i = 1; i <= wordn; ++i) 
    { 
    printf("%3d: ",i); 
    for (j = 0; j < lengths[i]; j++) 
     putchar('-'); 
    putchar('\n'); 
    } 
} 
+0

Biểu đồ dọc có thể được in một dòng tại một thời điểm, bằng cách đi qua mảng từ độ dài và giảm độ dài từ tại mỗi lần lặp. A # được in nếu độ dài từ vẫn lớn hơn 0 và không gian được in là nó đã đạt đến 0. Sau mỗi lần chạy, một dòng mới được in. – edrik

0

các biểu đồ dọc có thể được in mỗi lần một dòng tim e, bằng cách đi qua mảng độ dài từ và giảm độ dài từ tại mỗi lần lặp. A # được in nếu độ dài từ vẫn ở trên 0 và khoảng trắng được in khi đạt đến 0. Dòng mới được in sau mỗi lần lặp.

Nếu độ dài [i] nắm giữ số lượng ký tự cho chữ i, và wordn là tổng số từ, sau đó những điều sau đây sẽ in biểu đồ dọc:

#define YES 1 
#define NO 0 


more_lines = YES; 
while (more_lines) 
{ 
    more_lines = NO; 
    for (i = 1; i <= wordn; ++i) 
      { 
     if (lengths[i] > 0) 
       { 
        more_lines = YES; 
        printf("#\t"); 
        --lengths[i]; 
       } 
     else 
       printf(" \t"); 
     } 
    putchar('\n'); 
} 

Các mã hoàn chỉnh là dưới đây:

#include<stdio.h> 
/* Prints a histogram of the lenghts of words */ 

#define MAX_WORDS 100 
#define IN 1 
#define OUT 0 

#define YES 1 
#define NO 0 

main() 
{ 
int c, length, wordn, i, j, state, more_lines, lengths[MAX_WORDS]; 
wordn = length = 0; 
state = OUT; 
for (i = 0; i < MAX_WORDS; ++i) lengths[i] = 0; 

while ((c = getchar()) != EOF && wordn < MAX_WORDS) 
{ 
    if (c == ' ' || c == '\t' || c == '\n') 
     state = OUT; 

    else if (wordn == 0) 
     { 
     state = IN; 
     ++wordn; 
     ++length; 
     } 

    else if (state == IN) 
     ++length; 

    else if (state == OUT) 
     { 
     lengths[wordn] = length; 
     ++wordn; 
     length = 1; 
     state = IN; 
     } 
}  

lengths[wordn] = length; 

/* Print histogram header */ 
    for (i = 1; i <= wordn; ++i)  
printf ("%d\t", i); 
    putchar('\n'); 

more_lines = YES; 
while (more_lines) 
{ 
    more_lines = NO; 
    for (i = 1; i <= wordn; ++i) 
     { 
    if (lengths[i] > 0) 
     { 
      more_lines = YES; 
      printf("#\t"); 
      --lengths[i]; 
     } 
    else 
     printf(" \t"); 
     } 
    putchar('\n'); 
} 
} 
2
#include<stdio.h> 
#define RESET 0 
#define ON 1 

main() 
{ 
    int i,wnum=0,c,wc[50]; 
    int count=0,state; 
    state=RESET; 
    for(i=0;i<50;++i) 
    wc[i]=0; 
    /*Populating the array with character counts of the typed words*/ 
    while((c=getchar())!=EOF) 
    { 
     if(c=='\n'||c=='\t'||c==' '||c=='"') 
    { 
     if(state!=RESET) 
     state=RESET; 
    } 
     else if((c>=65&&c<=90)||(c>=97&&c<=122)) 
    { 
     if(state==RESET) 
     { 
      count=RESET; 
      ++wnum; 
      state=ON; 
     } 
     ++count; 
     wc[wnum-1]=count; 
    } 
    } 
    c=RESET; 

    /*Finding the character count of the longest word*/ 
    for(i=0;i<wnum;++i) 
    { 
     if(c<wc[i]) 
    c=wc[i]; 
    } 

    /*Printing the Histogram Finally*/ 
for(i=c;i>0;--i) 
    { 
     for(count=0;count<wnum;++count) 
    { 
     if(wc[count]-i<0) 
     printf(" "); 
     else printf("x "); 
    } 
     printf("\n"); 
    } 
} 

ĐỨNG ĐỊNH HƯỚNG: chỉ sử dụng các công cụ chúng tôi đã học cho đến nay trong cuốn sách. Và bạn có thể thay đổi kích thước mảng, wc [50]. Tôi giữ mã hợp lệ cho 50 từ. Hướng ngang phải khá đơn giản. Tôi đã không thử nó mặc dù.

0

Mặc dù bài tập dựa trên mảng, tôi đã cố gắng viết nó bằng cách sử dụng vòng lặp cơ bản và câu lệnh if. Tôi không thực sự tốt với mảng như bây giờ, vì vậy nghĩ đến việc cố gắng này ra. Tôi đã không thử nghiệm nó cho các lỗi mặc dù, nhưng nó có vẻ là làm việc tốt cho hầu hết các yếu tố đầu vào.

#include<stdio.h> 
    main() { 
    long int c;   

    while((c=getchar())!=EOF) { 
     if(c!=' '&&c!='\n'&&c!='\t') { 
      putchar("*"); 
     } 

     if(c==' '||c=='\n'||c=='\t') { 
      putchar('\n'); 
     } 

    } 
    return 0; 
    } 

Xin lưu ý rằng đây là đoạn mã cơ bản để in theo chiều ngang, chỉ để hiểu cơ bản về cấu trúc.

0
// Histogram to print the length of words in its input 
#include <stdio.h> 
main() 
{ 
    int wordcount[10],c,token=0; 
    int word=0, count =0; 
    for (int i=0; i<10; i++) 
    { 
     wordcount[i]=0; 
    } 

    while((c=getchar())!=EOF) 
    { 
    if(c== ' ' || c == '\n' || c== '\t') 
    { 
     // add the length of word in the appropriate array number 
     switch(word) 
     { 
      case 1: 
      ++wordcount[0];break; 
      case 2: 
      ++wordcount[1];break; 
      case 3: 
      ++wordcount[2];break; 
      case 4: 
      ++wordcount[3];break; 
      case 5: 
      ++wordcount[4];break; 
      case 6: 
      ++wordcount[5];break; 
      case 7: 
      ++wordcount[6];break; 
      case 8: 
      ++wordcount[7];break; 
      case 9: 
      ++wordcount[8];break; 
      case 10: 
      ++wordcount[9];break; 
     } 
     word =0; 
    } 
    else if (c != ' ' || c != '\n' || c!= '\t') 
    { 
     word++; 
    } 

} 
    for (int j=0; j<10; j++) 
    { 
     if(wordcount[j]==0) 
     { 
      printf("- "); 
     } 
     for (int k=0;k<wordcount[j];k++) 
     printf("X", wordcount[j]); 
     printf("\n"); 
    } 


} 
1
//This is for horizontal histogram. 
//It works for any number of lines of words where total words <= MAX 
#include <stdio.h> 
#define MAX 100 //Change MAX to any value.But dont give words more than MAX. 

void main() 
{ 
    int w, nwords[MAX] = {0}, i = 0; //nwords is an array for storing length of each word.Length of all words initialized to 0. 

    while ((w = getchar()) != EOF) 
    { 
     if (w == ' ' || w == '\t' || w == '\n') 
      ++i;   //if space or tab or newline is encountered, then index of array is advanced indicating new word 
     else 
      ++nwords[i];  //increment the count of number of characters in each word 
    }  //After this step,we will have array with each word length. 

    for (i = 0; i < MAX; i++) //iterating through array 
    { 
     printf("\n"); 
     for (; nwords[i] > 0; nwords[i]--) 
      printf("$");  //if length of word > 0 , print $ and decrement the length.This is in loop. 
     if (nwords[i+1] == 0) //as MAX is 100, to avoid printing blank new lines in histogram,we check the length of next word. 
      break;    //If it is 0, then break the loop 
     printf("\n"); //After each word bar in histogram, new line. 
    } 
    printf("\n"); 
} //main 
Các vấn đề liên quan