• C语言直方图 && EOF释疑


    用C语言统计单词长度出现的频率
    #include <stdio.h>
    
    #define MAX_LEN 10  //单词的最大长度
    #define IN  1
    #define OUT 0
    
    int main(void)
    {
        int len;    //每个单词的长度
        int wc[MAX_LEN+1] = {0};  //每个长度对应的单词数
        int c, i, j;
        int state;
    	int maxnum=0;	//wc[]中的最大数
    
        len = c = i = 0;
    	state = OUT;
        while((c = getchar()) != EOF)  {
    		if(c == ' ' || c == '\t' || c == '\n') {
                if(state == IN)  {	//或者 if(len > 0)
    				if(len >= MAX_LEN) {
    					wc[MAX_LEN]++;
    					len = MAX_LEN;	//单词长度大于MAX_LEN
    				}
    				else {
    					wc[len]++;
    				}
    				if(maxnum < wc[len])
    					maxnum = wc[len];
                    len = 0;
    				state = OUT;
                }
    		}
    		else if(state == OUT) {
    			state = IN;
    			len = 0;	//单词真实的长度为len+1
    		}
    			else
    				len++;
    	}
    
    	putchar('\n');
    
    	for(i = maxnum; i > 0; i--) {
    		printf("%3d|", i);
    		for(j = 0; j <= MAX_LEN; j++) {
    			if(wc[j] >= i)
    				printf(" * ");
    			else
    				printf("   ");
    		}
    		putchar('\n');
    	}
    	printf("   +");
    	for(i = 0; i <= MAX_LEN; i++)
    		printf("___");
    	printf("\n   ");
    	for(i = 0; i < MAX_LEN; i++) {
    		printf("%3d", i+1);
    	}
    	printf(" >10");
    	putchar('\n');
    	return 0;
    }

    效果图


    EOF释疑(转自这里)

    首先要明白一点,EOF并不是标志结尾的特殊字符,而是文字流(stream,标准输入或者文件)达到结尾时返回的一个信号量,在stdio.h中定义为常量,其值常常为-1,只在文本文件中存在,二进制文件中不存在。

    1.如果是从标准输入中读取stream,如下程序

    int c;//定义为int类型,因为返回值EOF(-1)是int类型的
    while((c=getchar()) != EOF)
        putchar(c);
    由于标准输入中无法事先判断长度,无法判断是否是End Of File,所以需要手动输入一个字符表示达到EOF。

    Windows中,在新的一行开头中按下Ctrl+Z,表示达到EOF(因为Windows输入是阻塞式的,所以在敲下换行键之前不会检测Ctrl+Z);

    Linux中,在新的一行开头,按下Ctrl-D,表示达到EOF(或者在一行的中间按两次Ctrl-D,因为在一行的中间按下Ctrl-D,表示输出"标准输入"的缓存区);

    2.如果是从文件中读取stream,一般写成如下形式

    int c;
    while ((c = fgetc(fp)) != EOF){
        c = fgetc(fp);
        do something;
    }

    这样写有一个问题。fgetc()不仅是遇到文件结尾时返回EOF,而且当发生错误时,也会返回EOF。因此,C语言又提供了feof()函数,用来保证确实是到了文件结尾。上面的代码feof()版本的写法就是:
    int c;
    while (!feof(fp)) {
      c = fgetc(fp);
      do something;
    }
    但是,这样写也有问题。fgetc()读取文件的最后一个字符以后,C语言的feof()函数依然返回0,表明没有到达文件结尾;只有当fgetc()向后再读取一个字符(即越过最后一个字符),feof()才会返回一个非零值,表示到达文件结尾。
    所以,按照上面这样写法,如果一个文件含有n个字符,那么while循环的内部操作会运行n+1次。所以,最保险的写法是像下面这样:
    int c = fgetc(fp);
    while (c != EOF) {
      do something;
      c = fgetc(fp);
    }
    if (feof(fp)) {
      printf("\n End of file reached.");
    } else {
      printf("\n Something went wrong.");
    }


    这样在读取stream时,如果c = fgetc(fp) 读到的是二进制的-1,怎么区分读到的c(-1)跟信号值(-1)呢?

    一种解释(不一定对,欢迎讨论):

    在文本文件中,数据以字符的ASCII码值的形式存放。ASCII码值的范围是0~255,不可能出现-1,-1实际上是‘-’ 和‘1’,而fgetc是文本视图处理文件的,因此可以用EOF作为文件结束标志输入的。

    注意:EOF只存在文本视图中,二进制视图是通过比较文件长度来判断是否达到文件结尾。

  • 相关阅读:
    css关于margin计算top/bottom/left/right值,总是不居中的相关说明。
    微信小程序开发工具,设置默认首页的方式。
    html Video标签关于自动播放(autoplay)和支持播放的编码格式相关的文档
    [Vue v3]vueclasscomponent @Component 装饰器和 Vue 基类的更改
    git项目,执行命令this operation must be run in a work tree
    220708Allegro等长操作
    AGC008E Next or Nextnext
    AGC023E Inversions
    AOP之环绕通知 proceedingjoinpoint和前置后置通知 joinpoint区别
    maven中的groupId和artifactId到底指的是什么? groupid公司组织名称 artifactId 项目名称
  • 原文地址:https://www.cnblogs.com/java20130726/p/3218679.html
Copyright © 2020-2023  润新知