C //练习 6-1 上述getword函数不能正确处理下划线、字符串常量、注释及预处理控制指令。请编写一个更完善的getword函数。

本文主要是介绍C //练习 6-1 上述getword函数不能正确处理下划线、字符串常量、注释及预处理控制指令。请编写一个更完善的getword函数。,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

C程序设计语言 (第二版) 练习 6-1

练习 6-1 上述getword函数不能正确处理下划线、字符串常量、注释及预处理控制指令。请编写一个更完善的getword函数。

注意:代码在win32控制台运行,在不同的IDE环境下,有部分可能需要变更。
IDE工具:Visual Studio 2010

 

代码块:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>#define MAXWORD 100
#define NKEYS (sizeof keytab / sizeof(keytab[0]))
#define MAXOP 100
#define NUMBER '0'
#define MAXVAL 100
#define BUFSIZE 100
#define VAR '1'char buf[BUFSIZE];
int bufp = 0;struct key{char *word;int count;
};int getch(void){return (bufp > 0) ? buf[--bufp] : getchar();
}void ungetch(int c){if(bufp >= BUFSIZE){printf("Ungetch! Too many characters!\n");}else{buf[bufp++] = c;}
}int getword(char *word, int lim) {int c;char *w = word;static int line_beg = 1; /* 1 at beginning of a new line */static int after_slash = 0; /* 1 after '\' */int after_star = 0; /* 1 after '*' */if(isspace(c = getch()))after_slash = 0;while(isspace(c)) {if(c == '\n')line_beg = 1;c = getch();}if(c != EOF)*w++ = c;if(c == '#' && line_beg == 1) { /* Preprocessor directive */while((c = getch()) != '\n' && c != EOF) /* Go to end of line */;return getword(word, lim); /* Start over */}line_beg = 0;if(c == '\\') /* Set after_slash flag */after_slash = after_slash ? 0 : 1; /* Ignore '\\' comment */else if(c == '/' ) {if((c = getch()) == '*' && !after_slash) { /* Begin comment */while((c = getch()) != EOF) {if(c == '/') {if(after_star) /* End comment */return getword(word, lim); /* Start over */}else if(c == '*' && !after_slash)after_star = 1;else if(c == '\\')after_slash = after_slash ? 0 : 1; /* Ignore '\\' comments */else {after_star = 0;after_slash = 0;}}} /* End comment */after_slash = 0; /* Not after slash anymore */if(c != EOF)ungetch(c);}else if(c == '\"') {if(!after_slash) { /* String literal */--w; /* Reset w */while((c = getch()) != EOF) {if(c == '\"' && !after_slash)break;else if(c == '\\')after_slash = after_slash ? 0 : 1; /* Ignore '\\' comments */elseafter_slash = 0;*w++ = c;}*w = '\0';if(c == EOF)return EOF;elsereturn getword(word, lim); /* Start over. */}after_slash = 0; /* Not after a slash anymore. */}if(!isalpha(c) && c != '_') { /* It's a symbol. */*w = '\0';if(c != '\\')after_slash = 0;return c;}/* Reset this flag since a slash would have just returned. */after_slash = 0;for( ; --lim > 0; ++w) /* It's a word or letter. */if(!isalnum(*w = getch()) && *w != '_') {ungetch(*w);break;}*w = '\0';return word[0];}int binsearch(char *word, struct key tab[], int n){int cond;int low, high, mid;low = 0;high = n - 1;while(low <= high){mid = (low + high) / 2;if((cond = strcmp(word, tab[mid].word)) < 0){high = mid - 1;}else if(cond > 0){low = mid + 1;}else{return  mid;}}return -1;
}int main(){struct key keytab[] = {{"auto", 0}, {"break", 0}, {"case", 0}, {"char", 0}, {"const", 0}, {"continue", 0}, {"default", 0},{"do", 0}, {"double", 0}, {"else", 0}, {"enum", 0}, {"extern", 0}, {"float", 0}, {"for", 0}, {"goto", 0}, {"if", 0}, {"int", 0},{"long", 0}, {"register", 0}, {"return", 0}, {"short", 0}, {"signed", 0}, {"sizeof", 0}, {"static", 0}, {"struct", 0}, {"switch", 0},{"typedef", 0}, {"unsigned", 0}, {"union", 0}, {"void", 0}, {"volatile", 0}, {"while", 0}};int n;char word[MAXWORD];while(getword(word, MAXWORD) != EOF){if(isalpha(word[0])){if((n = binsearch(word, keytab, NKEYS)) >= 0){keytab[n].count++;}}}for(n = 0; n < NKEYS; n++){if(keytab[n].count > 0){printf("%4d %s\n", keytab[n].count, keytab[n].word);}}system("pause");return 0;
}

这篇关于C //练习 6-1 上述getword函数不能正确处理下划线、字符串常量、注释及预处理控制指令。请编写一个更完善的getword函数。的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/619100

相关文章

利用Python编写一个简单的聊天机器人

《利用Python编写一个简单的聊天机器人》这篇文章主要为大家详细介绍了如何利用Python编写一个简单的聊天机器人,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 使用 python 编写一个简单的聊天机器人可以从最基础的逻辑开始,然后逐步加入更复杂的功能。这里我们将先实现一个简单的

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

python修改字符串值的三种方法

《python修改字符串值的三种方法》本文主要介绍了python修改字符串值的三种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录第一种方法:第二种方法:第三种方法:在python中,字符串对象是不可变类型,所以我们没办法直接

使用PyQt5编写一个简单的取色器

《使用PyQt5编写一个简单的取色器》:本文主要介绍PyQt5搭建的一个取色器,一共写了两款应用,一款使用快捷键捕获鼠标附近图像的RGB和16进制颜色编码,一款跟随鼠标刷新图像的RGB和16... 目录取色器1取色器2PyQt5搭建的一个取色器,一共写了两款应用,一款使用快捷键捕获鼠标附近图像的RGB和16

Oracle的to_date()函数详解

《Oracle的to_date()函数详解》Oracle的to_date()函数用于日期格式转换,需要注意Oracle中不区分大小写的MM和mm格式代码,应使用mi代替分钟,此外,Oracle还支持毫... 目录oracle的to_date()函数一.在使用Oracle的to_date函数来做日期转换二.日

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

C#中字符串分割的多种方式

《C#中字符串分割的多种方式》在C#编程语言中,字符串处理是日常开发中不可或缺的一部分,字符串分割是处理文本数据时常用的操作,它允许我们将一个长字符串分解成多个子字符串,本文给大家介绍了C#中字符串分... 目录1. 使用 string.Split2. 使用正则表达式 (Regex.Split)3. 使用

Java中JSON字符串反序列化(动态泛型)

《Java中JSON字符串反序列化(动态泛型)》文章讨论了在定时任务中使用反射调用目标对象时处理动态参数的问题,通过将方法参数存储为JSON字符串并进行反序列化,可以实现动态调用,然而,这种方式容易导... 需求:定时任务扫描,反射调用目标对象,但是,方法的传参不是固定的。方案一:将方法参数存成jsON字

使用Java编写一个文件批量重命名工具

《使用Java编写一个文件批量重命名工具》这篇文章主要为大家详细介绍了如何使用Java编写一个文件批量重命名工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录背景处理1. 文件夹检查与遍历2. 批量重命名3. 输出配置代码片段完整代码背景在开发移动应用时,UI设计通常会提供不

C++11的函数包装器std::function使用示例

《C++11的函数包装器std::function使用示例》C++11引入的std::function是最常用的函数包装器,它可以存储任何可调用对象并提供统一的调用接口,以下是关于函数包装器的详细讲解... 目录一、std::function 的基本用法1. 基本语法二、如何使用 std::function