第一章最后的习题,我上一次做的时候真是无从下手。现在把书全部看了一遍之后回过头再做这些习题有了一些个人体会:
原来,原作者的思维非常清晰,所挑选的习题并不像国内的一些教材,只是一味的练习零散知识点。原作者想用最精炼的文字和习题让我们跟随作者的思路——如何解决程序语言开发中遇到的问题。
就拿本章末尾几道习题来说,如果将它们综合起来,不就是编译过程中会遇到的字符流处理问题吗?如果将后面所学的内存优化融入进来,那么思考的空间又会有所提升。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
typedef struct
{
char *line;
unsigned int len;
}LINE;
int getline(char *temp, int max_len); //获取单行
char *strdup(char *temp); //字符串复制(同时分配内存)
void detab(LINE *line); //将制表符替换为空格
void entab(LINE *line); //将制表符替换为制表符加空格
void break_line(LINE *line); //折行显示
void delete_line(LINE **line, int count); //删除注释
void find_error(LINE **line, int count); //检查括号是否匹配
#define MAX_LINES 1024
#define MAX_LEN 100
unsigned lines_count = 0;
main()
{
LINE *linep[MAX_LINES];
char temp[MAX_LEN];
unsigned len;
int i, n;
while ((len = getline(temp, MAX_LEN)) > 0)
{
if ((linep[lines_count] = (LINE *)malloc(sizeof(LINE))) == NULL\
|| (linep[lines_count]->line = strdup(temp)) == NULL)
{
printf("error: it's enough memory!\n");
exit(1);
}
linep[lines_count]->len = len;
detab(linep[lines_count]);
entab(linep[lines_count]);
// if (linep[lines_count]->len > 20) //使用break_line时,先屏蔽entab,不然会出现计数不准的情况!
// break_line(linep[lines_count]);
lines_count++;
}
delete_line(linep, lines_count);
find_error(linep, lines_count);
for (i = 0; i < lines_count; i++)
{
// printf("NO%d: \n%s (len = %d)\n", i + 1, linep[i]->line, linep[i]->len);
printf("%s",linep[i]->line);
free(linep[i]->line);
linep[i]->line = NULL;
free(linep[i]);
linep[i] = NULL;
}
return 0;
}
int getline(char *temp, int max_len)
{
int c;
char *p = temp;
while ((c = getchar()) != EOF && c != '\n')
{
*p++ = c;
}
if (c == '\n')
*p++ = '\n';
*p = '\0';
return (p - temp);
}
char *strdup(char *temp)
{
char *p;
if ((p = (char *)malloc(strlen(temp) + 1)) == NULL)
return NULL;
strcpy(p, temp);
return p;
}
void detab(LINE *line) //将制表符替换为空格
{
int i, j, k;
char s[MAX_LEN];
char *p = line->line;
int count = 0;
for (i = 0, j = 0; p[i] != '\0'; i++)
{
if (p[i] != '\t')
{
s[j++] = p[i];
count++;
}
else
{
int n = 8-(count % 8);
while (n--)
{
s[j++] = ' ';
count++;
}
}
}
s[j] = '\0';
free(line->line);
line->line = NULL;
free(line);
line = NULL;
if ((line = (LINE *)malloc(sizeof(LINE))) == NULL\
|| (line->line = strdup(s)) == NULL)
{
printf("error: no enough memory!\n");
exit(2);
}
line->len = count;
}
void entab(LINE *line) //将制表符替换为制表符加空格
{
int i, j, step1, step2, nl, nt;
char *p = line->line;
char s[MAX_LEN];
j = 0;
for (i = 0; p[i] != '\0';i++)
{
if (p[i] != ' ')
s[j++] = p[i];
else
{
step1 = i;
while (p[++i] == ' ');
step2 = i;
if (step2 - step1 < 8 - (step1 % 8))
{
int n = step2 - step1;
while (n--)
s[j++] = ' ';
}
else
{
int step = step2 - step1;
nt = (step - (8 - step1 % 8)) / 8 + 1;
nl = step - (nt - 1) * 8 - (8 - step1 % 8);
while (nt--)
s[j++] = '\t';
while (nl--)
s[j++] = ' ';
}
i--;
}
}
s[j] = '\0';
free(line->line);
line->line = NULL;
free(line);
line = NULL;
if ((line = (LINE *)malloc(sizeof(LINE))) == NULL\
|| (line->line = strdup(s)) == NULL)
{
printf("it's enough memory!\n");
exit(3);
}
line->len = j;
}
#define NBREAK 20 //折行限制
void break_line(LINE *line)
{
char *p = line->line;
char s[MAX_LEN];
int i, j = 0;
printf("break:\n");
for (i = 0; p[i] != '\0'; i++)
{
if (j < NBREAK - 1)
{
if (j == 0)
{
while (p[i] == ' ')
i++;
}
s[j++] = p[i];
}
else
{
s[j++] = p[i];
s[j] = '\0';
puts(s);
j = 0;
}
}
s[j] = '\0';
puts(s);
}
#define IN 0
#define OUT 1
void delete_line(LINE **line, int count) //删除注释
{
int i, j;
int state = OUT, state1 = OUT, state2 = OUT; //state:整体注释态,state1://注释态,state2:/*注释态
for (i = 0; i < count; i++)
{
for (j = 0; line[i]->line[j] != '\0'; j++)
{
if (line[i]->line[j] == '/')
{
if (line[i]->line[j + 1] == '/')
{
state1 = IN;
}
else if (line[i]->line[j + 1] == '*')
{
state2 = IN;
}
}
if (line[i]->line[j] == '\n')
state1 = OUT;
if(line[i]->line[j] == '*')
{
if (line[i]->line[j + 1] == '/')
{
state2 = OUT;
}
}
if (state1 == IN || state2 == IN)
state = IN;
else
state = OUT;
if (state == IN)
{
if (state1 == IN)
{
line[i]->line[j] = '\0';
continue;
}
if (state2 == IN)
{
line[i]->line[j] = '\0';
continue;
}
}
}
}
}
void find_error(LINE **line, int count) //检查括号是否匹配
{
int state1 = OUT, state2 = OUT; //state1:双引号状态,state2:单引号状态
int i, j, na, nb, rn, sn, fn; //na:双引号计数器,nb:单引号计数,rn园括号,sn方括号,fn花括号
na = nb = rn = sn = fn = 0;
for (i = 0; i < count; i++)
{
for (j = 0; line[i]->line[j] != '\0'; j++)
{
if (line[i]->line[j] == '\"')
na++;
if (line[i]->line[j] == '\'')
nb++;
if (na % 2 != 0)
state1 = IN;
else
state1 = OUT;
if (nb % 2 != 0)
state2 = IN;
else
state2 = OUT;
if (line[i]->line[j] == '(' || line[i]->line[j] == ')')
rn++;
if (line[i]->line[j] == '[' || line[i]->line[j] == ']')
sn++;
if (line[i]->line[j] == '{' || line[i]->line[j] == '}')
fn++;
}
}
if (rn % 2 != 0)
printf("圆括号不匹配!\n");
if (sn % 2 != 0)
printf("方括号不匹配!\n");
if (fn % 2 != 0)
printf("花括号不匹配!\n");
}