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

时间:2010-10-21 16:37:18

标签: 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. PRINT TOP BORDER
  2.   
  3. 打印类别,打印X每个时间条件都是正确的,打印NEWLINE,   REPEAT。
  4.   
  5. PRINT BOTTOM BORDER
  6.   

但是我想的越多,我就越不认为它是如何工作的(因为getchar()一次经过一个角色,而且它无法重新投入X正确的类别。)或者......

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

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

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

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

18 个答案:

答案 0 :(得分:7)

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

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

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

这个提示可以帮助你入门!如果您需要进一步的帮助,请在下方发表评论。

答案 1 :(得分:3)

我建议您通过针对每行一个单词的情况解决问题来简化问题,因此您可以使用fgets。以下是"eat up" lines that are too long的方法。

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

int freq[11];

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

我希望这不是一个剧透。

答案 2 :(得分:2)

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

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

答案 3 :(得分: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");
    }
}

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

答案 4 :(得分:1)

我将链接以下答案,但由于您要求详细信息,因此关键似乎是

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

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

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

array[w_ctr]++

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

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

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

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

结束


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

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

答案 5 :(得分:1)

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

  • 你如何定义一个单词?
  • 如何衡量单词的长度?您在阅读流时是否可以一次执行一个字符,或者是否应该使用strtok或类似内容缓冲输入?

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

  • 您将如何存储此数据?

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

答案 6 :(得分: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

答案 7 :(得分:0)

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

<块引用>

横版:

#include<stdio.h>
#define MAX 15

int main()
{
    int c, wordLength, count;
    int arr[MAX] = { 0 };
    
    wordLength = count = 0;
    
    while((c = getchar()) != EOF)
    {
        if(c != ' ' && c != '\t' && c != '\n')
            ++arr[count];
        else
            ++count;
    }
    
    for(int i = 0; i <= count; i++)
    {
        printf("\n%2d |", i+1);
        
        for(int k = arr[i]; k > 0; k--)
            printf("— ");
    }
    
    return 0;
}
<块引用>

输入/输出:

man in black thor jsjsk ksskka
 1 |— — —
 2 |— —
 3 |— — — — —
 4 |— — — —
 5 |— — — — —
<块引用>

垂直版本:

#include<stdio.h>
#define MAX 15

int main()
{
    int c, count, maxLength;
    int arr[MAX] = { 0 };
    
    maxLength = count = 0;
    
    while((c = getchar()) != EOF)
    {
        if(c != ' ' && c != '\t' && c != '\n')
            ++arr[count];
        else
            ++count;
        
        if(arr[count] > maxLength)
            maxLength = arr[count];
    }
    
    for(int i = 1; i <= maxLength + 2; i++)
    {
        printf("\n");
        for(int k = 0; k <= count; k++)
        {
            if(i <= maxLength)
            {
                if(maxLength - i < arr[k])
                    printf("|");
                else
                    printf(" ");
            }
            else
            {
                if(maxLength - i == -1)
                    printf("—");
                else
                    printf("%d", k+1);
            }
            
            printf(" ");
        }
        
    }
    
    return 0;
}
<块引用>

输入/输出:

jsjs sjsj sjsj sjskks sjs sjs
      |
      |
| | | |
| | | | | |
| | | | | |
| | | | | |
— — — — — —
1 2 3 4 5 6

答案 8 :(得分:0)

#include <stdio.h>

int main(void)
{
int i, ii, state, c, largest, highest;
int A[100];
for(i = 0; i < 100; ++i)
    A[i] = 0;
i = ii = state = c = largest = 0;

while((c = getchar()) != EOF)
{
    if(c == ' ' || c == '\b' || c == '\n')
    {
        if(state)
        {
            ++A[i];
            if(largest <= i)
                largest = i;
            i = state = 0;
        }
    }
    else
    {
        if(state)
            ++i;
        else
            state = 1;
    }
}
for(i = 0; i < 100; ++i)
    if(highest <= A[i])
        highest = A[i];

for(i = 0; i <= highest; ++i)
{
    for(ii = 0; ii < 100; ++ii)
        if(A[ii])
        {
            if(A[ii] > (highest - i))
                printf("*\t");
            else
                printf(" \t");
        }
    putchar('\n');
}
for(ii = 0; ii < 100; ++ii)
    if(A[ii])
        printf("-\t");
putchar('\n');

for(ii = 0; ii < 100; ++ii)
    if(A[ii])
        printf("%d\t", ii + 1);
putchar('\n');
return 0;
}

答案 9 :(得分:0)

我也一直在学习K&R书。一个好的方法是使用int array存储单词频率。 数组索引是单词长度,而数组值是频率。

例如:

int histogram[15]; // declares an int array of size 15

// it is very important to initialize the array
for (int i = 0; i <= 15; ++i) {
    histogram[i] = 0;
}

histogram[4] = 7; // this means that you found 7 words of length 4

鉴于现在您已经有了一个存储字长频率的数据结构,您可以使用本书中找到的“字数统计”示例的相同推理来填充histogram数组。重要的是,您必须找到正确的位置来进行 字长跟踪(并对其进行重置) 直方图更新

您可以创建一个函数display_histogram,以便随后显示直方图。

这是一个代码示例:

#include<stdio.h>

#define MAX_WORD_LENGTH 15
#define IS_WORD_SEPARATOR_CHAR(c) (c == '\n' || c ==  ' ' || c == '\t')

#define IN  1
#define OUT 0

/* WARNING: There is no check for MAX_WORD_LENGTH */

void display_horizontal_histogram(int[]);
void display_vertical_histogram(int[]);
void display_histogram(int[], char);

void display_histogram(int histogram[], char type) {
    if (type == 'h') {
        display_horizontal_histogram(histogram);
    } else if (type = 'v') {
        display_vertical_histogram(histogram);
    }
}

void display_horizontal_histogram(int histogram[]) {
    printf("\n");

    //ignoring 0 length words (i = 1)
    for (int i = 1; i <= MAX_WORD_LENGTH; ++i) {
        printf("%2d: ", i);
        for (int j = 0; j < histogram[i]; ++j) {
            printf("*");
        }
        printf("\n");
    }

    printf("\n\n");
}

void display_vertical_histogram(int histogram[]) {
    int i, j,  max = 0;

    // ignoring 0 length words (i = 1)
    for (i = 1; i <= MAX_WORD_LENGTH; ++i) {
        if (histogram[i] > max) {
            max = histogram[i];
        }
    }


    for (i = 1; i <= max; ++i) {
        for (j = 1; j <= MAX_WORD_LENGTH; ++j) {
            if (histogram[j] >= max - i + 1) {
                printf("  * ");
            } else {
                printf("    ");
            }
        }
        printf("\n");
    }

    for (i = 1; i <= MAX_WORD_LENGTH; ++i) {
        printf(" %2d ", i);
    }

    printf("\n\n");
}

int main()
{
    int c, state, word_length;
    int histogram[MAX_WORD_LENGTH + 1];

    for (int i = 0; i <= MAX_WORD_LENGTH; ++i) {
        histogram[i] = 0;
    }

    word_length = 0;
    state = OUT;
    while ((c = getchar()) != EOF) {
        if (IS_WORD_SEPARATOR_CHAR(c)) {
            state = OUT;
            if (word_length != 0) {
                histogram[0]++;
            }
            histogram[word_length]++;
            word_length = 0;
        } else {
            ++word_length;
            if (state == OUT) {
                state = IN;
            }
        }
    }

    if (word_length > 0) {
        histogram[word_length]++;
    }

    display_histogram(histogram, 'h');
    display_histogram(histogram, 'v');
}

这是一个输入/输出示例:

kaldklasjdksla klsad lask dlsk aklsa lkas  adç  kdlaç kd dklask las kçlasd kas kla sd saçd sak dasças  sad sajçldlsak dklaa slkdals kkçl askd lsak lçsakç lsak lsak laskjl sa jkskjd aslld jslkjsak dalk sdlk jsalk askl jdsj dslk salkoihdioa slk sahoi hdaklshd alsh lcklakldjsalkd salk j  sdklald jskal dsakldaksl daslk

 1: *
 2: ***
 3: ******
 4: ***************
 5: **********
 6: ****
 7: ****
 8: ***
 9: 
10: *
11: **
12: 
13: 
14: **
15: 


              *                                             
              *                                             
              *                                             
              *                                             
              *                                             
              *   *                                         
              *   *                                         
              *   *                                         
              *   *                                         
          *   *   *                                         
          *   *   *                                         
          *   *   *   *   *                                 
      *   *   *   *   *   *   *                             
      *   *   *   *   *   *   *           *           *     
  *   *   *   *   *   *   *   *       *   *           *     
  1   2   3   4   5   6   7   8   9  10  11  12  13  14  15 

答案 10 :(得分:0)

我已尝试实现问题的后半部分(即以垂直方式显示直方图),并设法完成了大部分任务。在下面的代码中,接受的最大单词数为20,最大单词长度为10。此外,很抱歉,没有获得典型直方图的最佳图形表示,但是显示竖线的逻辑是完全准确的! 这是我的代码,

#define MAXWORDS 20
#define MAXLENGTH 10

int c, nlength = 0, i, nword = 0, j;
    int length_words[20]= {0};

    while((c = getchar()) != EOF && nword <= MAXWORDS)
    {
        if(c != ' ' && c != '\t' && c != '\n')
            ++nlength;
        else
        {
            if(nlength != 0){
                length_words[nword] = nlength;
                ++nword;
               /* for(i = 0; i < nlength; i++)
                printf("O");
                printf("\n");*/
                printf("Word number: %d has length: %d\n", nword - 1, nlength);
            }
            nlength = 0;
        }
    }
    // Displaying the Histogram
    for(i = MAXLENGTH; i > 0; i--)
    {
        for(j = 0; j < nword; j++)
        {
            if(i > length_words[j])
                printf("   ");
            else
                printf(" O ");
        }
        printf("\n");
    }

随时运行此命令,如有任何差异或漏洞,请通知我!

答案 11 :(得分:0)

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

int main()
{
    //hold length of string
    unsigned long length;
    // Holds the name input by user upto 50 characters
    char name[50];
    //iterator for generating dash for bar chart
    int i = 0;
    //iterator for generating dash for bar chart
    int j = 0;
    //take user name input
    printf("input your name [without spaces and < 50 characters] : ");
    scanf("%s", &name[0]);
    //find the length of string
    length = strlen(name);
    printf("length of your name is %lu \n", length);
    //generate dashes for bar chart
    while (i < length)
    {
        printf("--");
        ++i;
    }
    printf("| \n");
    // fill the bar chart with []
    while (j < length)
    {
        printf("[]");
        ++j;
    }
    printf("| \n");
    //generate dashes for bar chart
    while (length > 0)
    {
        printf("--");
        --length;
    }
    printf("| \n");
}

输入您的姓名(不包含空格和<50个字符):ThisIsAtestRun

您的名字长度为14

----------------------------|
[][][][][][][][][][][][][][]|
----------------------------|

答案 12 :(得分:0)

这里是简单的垂直直方图的示例

   $('#checkout[FORMID]').submit();

答案 13 :(得分:0)

已经使用数组回答了问题。 下面的代码不使用数组就打印水平直方图。 用一个宽松的定义,一个单词是指 不包含空格,制表符或换行符。

#include<stdio.h>
#define BLANK ' '
#define TAB '\t'
#define NEWLINE '\n'
#define RESET 0

void main()
{
    int c, num_char = 0, num_line = 0;
    while((c = getchar()) != EOF)
    {
        if(c == BLANK || c == TAB || c == NEWLINE)
        {
            printf("%d.: ", num_line);
            for(int i = 0; i < num_char; ++i)
                printf(" *");
            putchar(NEWLINE);
            ++num_line;
            do
            {
                c = getchar();
            }while(c == BLANK || c == TAB || c == NEWLINE);
            num_char = RESET;
        }
        ++num_char;
    }
}

答案 14 :(得分: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");
    }


}

答案 15 :(得分:0)

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

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

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

答案 16 :(得分: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<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');
 }
}

答案 17 :(得分:0)

你应该在功能中分开你的两个问题,例如:

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