【原创】C程序设计语言(2版KR) - C语言基础知识(2) 分类: Linux --- C 2014-11-21 19:21 85人阅读 评论(0) 收藏


【原创】C程序设计语言(2版KR) - C语言基础知识(2)


5. 数组






教材答案:

/*************************************************************************
	> File Name: 1_13.c
	> Author: Geng
	> Mail: genglut@163.com
	> Created Time: Tue 18 Nov 2014 11:17:57 PM CST
 ************************************************************************/

/**************************************************************
直方图定义:
n:某个长度单词出现的次数(长度为4的单词出现了9次,则n = 9)
M:出现最频繁的长度的次数
H:定义的直方图的最大长度(本例中为MAXHIST)
**************************************************************/

#include <stdio.h>

#define	MAXHIST	15		//直方图的最大长度
#define	MAXWORD	11		//单词的最大长度
#define	IN	1		//在单词中
#define	OUT	0		//在单词外

int main()
{

	int c, i, nc, state;	//nc:单词的长度
	int len;		//直方图中每个直方条的长度
	int maxvalue;		//wl数组的最大值
	int ovflow;		//长度大于或等于MAXWORD的单词的数量
	int wl[MAXWORD];	//按单词长度值0~11,统计输入中各长度的单词数,存放在wl数组中

	state = OUT;
	nc = 0;
	ovflow = 0;
	for(i = 0; i < MAXWORD; ++i)
		wl[i] = 0;

	while((c = getchar()) != EOF)
	{
		if(c == ' ' || c == '\n' || c == '\t')
		{
			state = OUT;
			if(nc > 0)
				if(nc < MAXWORD)
					++wl[nc];
				else
					++ovflow;
			nc = 0;
		}
		else if(state == OUT)
		{
			state = IN;
			nc = 1;
		}
		else
			++nc;
	}
	maxvalue = 0;
	for(i = 1; i < MAXWORD; ++i)
		if(wl[i] > maxvalue)
			maxvalue = wl[i];
	for(i = 1; i < MAXWORD; ++i)
	{
		printf("%5d - %5d : ", i, wl[i]);
		if(wl[i] > 0)
		{
			if((len = wl[i] * MAXHIST / maxvalue) <= 0)
				len = 1;
		}
		else
			len = 0;
		while(len > 0)
		{
			putchar('*');
			--len;
		}
		putchar('\n');
	}
	if(ovflow > 0)
		printf("there are %d words >= %d/n", ovflow, MAXWORD);

	return 0;
}


6. 函数

函数的默认返回类型为int型。



int power(int, int);

7. 参数--传值调用



8. 字符数组






9. 外部变量与作用域

extern int max;
extern char longest[];



C语言中注释分为以下几种
1) /* hello world */
2) // hello world
3) #if 0
   hello world
   #endif
表面上看起来很简单,其实实现起来比较复杂,有很多细节需要处理,比如注释和引号互相嵌套的问题,/* "hello */ " world */, "/* hello */"。还有比如删除注释后需要适当调整格式使其整齐美观。
目前C语言中的主流注释方式为第一种,故暂时只实现了第一种,其实原理都是一样的。核心原理即为状态机,读入一个字符,根据当前状态和读入的字符转入下一个状态,每一个状态都有相应的动作处理读入的字符,如忽略或写入输出文件或退出上一个字符等等。
共有以下几个状态
#define STATUS_OUTTE  0 /* 在注释和引号外面       */
#define STATUS_DOTTE  1 /* 在引号内部             */
#define STATUS_STIN1  2 /* 读入 /,等待 *         */
#define STATUS_STIN2  3 /* 读入 /* , 准备进入注释 */
#define STATUS_STINN  4 /* 在注释内部             */
#define STATUS_STOU1  5 /* 读入 * , 等待 /        */
#define STATUS_STOU2  6 /* 读入 */, 准备离开注释  */
#define STATUS_STACT  7 /* 伪状态,表示状态机动作 */
状态机有以下几种动作
#define STFLAG_NOACT  0 /* 没动作,忽略字符   */
#define STFLAG_FPUTC  1 /* 将字符写入输出文件 */
#define STFLAG_UNPUT  2 /* 将上一个字符退出   */
完整实现如下

/*
    comment.h
*/
#ifndef _comment_h
#define _comment_h

void comment(char *inpath, char *outpath);

#endif

/*
    comment.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "comment.h"

#define STATUS_OUTTE 0
#define STATUS_DOTTE 1
#define STATUS_STIN1 2
#define STATUS_STIN2 3
#define STATUS_STINN 4
#define STATUS_STOU1 5
#define STATUS_STOU2 6
#define STATUS_STACT 7

#define STFLAG_NOACT 0
#define STFLAG_FPUTC 1
#define STFLAG_UNPUT 2

static FILE *fpin, *fpout;
static int status_table[8][128];
static int status = STATUS_OUTTE;

#define st(i, j) status_table[(i)][(j)]
        
static void set_status_table(int i, int j, int s)
{
    if (j != -1) st(i, j) = s;
    else {
        for (j = 0; j < 128; j++)
            status_table[i][j] = s;
    }
}

static void init_status(void)
{
    set_status_table(STATUS_OUTTE, -1 , STATUS_OUTTE);
    set_status_table(STATUS_OUTTE, '/', STATUS_STIN1);
    set_status_table(STATUS_OUTTE, '"', STATUS_DOTTE);

    set_status_table(STATUS_DOTTE, -1 , STATUS_DOTTE);
    set_status_table(STATUS_DOTTE, '"', STATUS_OUTTE);
    
    set_status_table(STATUS_STIN1, -1 , STATUS_OUTTE);
    set_status_table(STATUS_STIN1, '/', STATUS_STIN1);
    set_status_table(STATUS_STIN1, '*', STATUS_STIN2);
    set_status_table(STATUS_STIN1, '"', STATUS_DOTTE);
    
    set_status_table(STATUS_STIN2, -1 , STATUS_STINN);
    set_status_table(STATUS_STIN2, '*', STATUS_STOU1);
    
    set_status_table(STATUS_STINN, -1 , STATUS_STINN);
    set_status_table(STATUS_STINN, '*', STATUS_STOU1);
     
    set_status_table(STATUS_STOU1, -1 , STATUS_STINN);
    set_status_table(STATUS_STOU1, '*', STATUS_STOU1);
    set_status_table(STATUS_STOU1, '/', STATUS_STOU2);
    
    set_status_table(STATUS_STOU2, -1 , STATUS_OUTTE);
    set_status_table(STATUS_STOU2, '"', STATUS_DOTTE);
    set_status_table(STATUS_STOU2, '/', STATUS_STIN1);
    
    set_status_table(STATUS_STACT, STATUS_OUTTE, STFLAG_FPUTC);
    set_status_table(STATUS_STACT, STATUS_DOTTE, STFLAG_FPUTC);
    set_status_table(STATUS_STACT, STATUS_STIN1, STFLAG_FPUTC);
    set_status_table(STATUS_STACT, STATUS_STIN2, STFLAG_UNPUT);
    set_status_table(STATUS_STACT, STATUS_STINN, STFLAG_NOACT);
    set_status_table(STATUS_STACT, STATUS_STOU1, STFLAG_NOACT);
    set_status_table(STATUS_STACT, STATUS_STOU2, STFLAG_NOACT);
}            

#define file_noact ((status_handler_t)0)
typedef void (*status_handler_t)(char);

static void file_putc(char c);
static void file_unputc(char c);

static void status_handler(char c)
{
    const status_handler_t handler_a[] = {
        file_noact, file_putc, file_unputc
    };
    int actidx = st(STATUS_STACT, status);
    status_handler_t handler = handler_a[actidx];
    if (handler != NULL) handler(c);
}

static void show_status(char c);

void comment(char *inpath, char *outpath)
{
    char c;
    init_status();
    fpin = fopen(inpath, "r");
    fpout = fopen(outpath, "w");
    assert(fpin && fpout != NULL);
    while ((c = fgetc(fpin)) != EOF) {
        show_status(c);
        if (c == '\r') continue;
        status = st(status, (int)c);
        status_handler(c);
    }        
}
///////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
static char *c_str(char c, char *buf, int size)
{
    if (c == ' ') return "_";
    else if (c == '\t') return "\\t";
    else if (c == '\n') return "\\n";
    else if (c == '\r') return "\\r";
    else if (c == '\0') return "\\0";
    snprintf(buf, size, "%c", c);
    return buf; 
}

#define RET_STATUS_STRING(s)    \
    if (status == (s)) return #s
    
static char *status_str(void)
{
    RET_STATUS_STRING(STATUS_OUTTE);
    RET_STATUS_STRING(STATUS_DOTTE);
    RET_STATUS_STRING(STATUS_STIN1);
    RET_STATUS_STRING(STATUS_STIN2);
    RET_STATUS_STRING(STATUS_STINN);
    RET_STATUS_STRING(STATUS_STOU1);
    RET_STATUS_STRING(STATUS_STOU2);
    return "invalid status"; 
} 

static void show_status(char c)
{
    char t[4];
    fprintf(stdout, ">>> %s, %s\n", 
        status_str(), c_str(c, t, sizeof t));
}

#define MAXLINE 128
static char linebuf[MAXLINE];
static char *lineptr = linebuf;

static void init_line_buf(void)
{
    memset(linebuf, 0, sizeof linebuf);
    lineptr = linebuf;
}

#define isblank(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')

/* is writable */
static int is_wrt(void)
{
    char c, *ptr = linebuf;
    for ( ; (c = *ptr); ptr++) {
        if (isblank(c) == 0)
            return 1;
    }
    return 0;
}

static void file_puts(void)
{
    static int lines; /* empty lines */

    if (is_wrt()) 
        lines = 0;
    else lines++;
    if (lines > 1) 
        return;

    int len = strlen(linebuf);
    fwrite(linebuf, len, 1, fpout);
}

static void file_putc(char c)
{
    *lineptr++ = c;
    if (c == '\n') {
        file_puts();
        init_line_buf();
    }
}

static void file_unputc(char c)
{
    *--lineptr = 0;
}

/*
    main.c
*/
#include <assert.h>
#include "comment.h"

int main(int argc, char *argv[])
{
    assert(argc == 3);
    comment(argv[1], argv[2]);
    return 0;
}

原文链接:

http://blog.csdn.net/geng823/article/details/41356193


版权声明:本文为博主原创文章,未经博主允许不得转载。

posted @ 2014-11-21 19:21  GengLUT  阅读(293)  评论(0编辑  收藏  举报