根据字长打印直方图(C)

这是K&R练习(1-13)……

“编写一个程序来打印输入中单词长度的直方图。可以很容易地绘制水平条形图的直方图;垂直方向更具挑战性。”

该部分是关于数组的,说实话,我不确定我是否完全理解它。 到目前为止,一切都很容易掌握,但事实并非如此。

无论如何我首先尝试用水平条做直方图。 一旦我把它弄下来,我会尝试垂直,但是现在我甚至不确定从哪个版本开始。 (我睡在上面,醒了,仍然无法得到它。)

我画了一个程序输出内容的例子:

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

并尝试将其分解(程序)。 这就是我提出的:

  1. 打印顶部边框
  2. 打印类别,打印X每个时间条件都是正确的,打印NEWLINE,REPEAT。
  3. 打印底部边框

但我想的越多,我认为它的工作方式就越少(因为getchar()一次只能通过一个角色,而且无法重新将X放入正确的类别。)要么…

……我真的很困惑,我将如何解决这个问题。 这是我能够获得代码的明智之处:

 #include  #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; } 

有人可以帮助启发我吗? 不一定是代码,可能只是伪代码,或者是一些“智者的话”,关于我需要做什么,想什么,或者什么。 这只是路上真正的大石头,我想过去:/。

(我会在30分钟后回来查看)

我喜欢伪代码! 在那里有一些好的想法,但你还没有正确地订购你的程序。

正如你自己所说,你无法阅读文本,返回并在特定行中打印X. 如果我们确定无法完成,那么除了事先知道直方图的所有值之外别无选择。

因此,您应该认为您的程序有两个部分(并且您将在几乎所有编写的程序中进行这种划分):首先,将进行计算的部分; 然后是一个以某种格式输出它们的部分(直方图)。

这个提示应该让你开始! 如果您需要进一步的帮助,请在下面评论

我建议你通过解决每行一个单词的情况来简化问题,这样你就可以使用fgets 。 以下是如何“吃掉”过长的线条 。

然后,通常,中央数据结构是解决问题的关键。 您需要的数据结构是用作频率表的数组:

 int freq[11]; 

freq[1] ,存储长度为1的字/行数, freq[2]长度为2的字数等,以及freq[0]长度> 10的字数/行数。 您不需要存储单词,因为程序的其余部分只需要它们的长度。 写出直方图现在应该很容易。

我希望这不是太多的扰流板。

下面的代码仅使用本书提供的基本工具包打印水平直方图:

 #include /* 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'); } } 
 #include #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;i0;--i) { for(count=0;count 

垂直方向:仅使用我们目前在本书中学到的工具。 你可以改变数组大小,wc [50]。 我保持代码有效50个字。 水平方向应该非常简单。 我没试过。

要对字长进行直方图,您需要知道字长。

  • 你怎么定义一个单词?
  • 你怎么测量一个单词的长度? 当你读取流时,你可以一次做一个字符,或者你应该缓冲输入使用strtok或类似的东西?

您需要累积每个长度出现次数的数据。

  • 你将如何存储这些数据?

您需要以令人愉悦的forms输出结果。 这很繁琐,但并不难。

我将链接下面的答案,但既然你要求详细信息,关键似乎就是这个

使用长度的ARRAY,即有一个数组,每个元素初始化为零,假设MAX字长约为30 …

*在单词中有一个标志,并在每次没有遇到空格时递增计数器

*一旦out of the word flag设置为“out”并且数组中相应的字长索引项增加,即如果字长计数器是w_ctr使用

 array[w_ctr]++ 

*使用数组作为循环中每一行的参考表,以打印直方图中的每一行,这样您就可以使用该数组,现在可以确定直方图中要插入的’X’的天气

编辑:对不起,我没有正确阅读问题,但垂直直方图的想法更简单,可以使用相同的东西。

在最后一步之后,只需打印水平直方图,直到计数器超出当前打印的字长

 for(ctr=0;ctr 

结束


原文在这里http://users.powernet.co.uk/eton/kandr2/krx113.html

CLC-wiki也是一个查看评论的地方。

 //This is for horizontal histogram. //It works for any number of lines of words where total words <= MAX #include  #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 

您应该将function中的两个问题分开,例如:

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

然后你的主要容易:

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

垂直直方图可以通过遍历字长数组并在每次迭代时减少字长来一次打印一行。 如果字长仍然高于零,则打印#,当达到0时打印空格。每次迭代后打印换行。

如果length [i]包含单词i的字符数,而wordn是单词的总数,则以下将打印垂直直方图:

 #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'); } 

完整代码如下:

 #include /* 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'); } } 

虽然练习基于Arrays,但我尝试使用基本的while循环和if语句来编写它。 到目前为止我对arrays并不是很好,所以想到尝试这个。 我没有测试它的bug,但它似乎适用于大多数输入。

  #include 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; } 

请注意,这是一个非常基本的代码,可以水平打印,只是为了对结构有基本的了解。

 // Histogram to print the length of words in its input #include  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