K&R不论是说明,还是习题,都非常经典,强烈建议大家看看

第一章最后的习题,我上一次做的时候真是无从下手。现在把书全部看了一遍之后回过头再做这些习题有了一些个人体会:
原来,原作者的思维非常清晰,所挑选的习题并不像国内的一些教材,只是一味的练习零散知识点。原作者想用最精炼的文字和习题让我们跟随作者的思路——如何解决程序语言开发中遇到的问题。
就拿本章末尾几道习题来说,如果将它们综合起来,不就是编译过程中会遇到的字符流处理问题吗?如果将后面所学的内存优化融入进来,那么思考的空间又会有所提升。

#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");

}

发布了4 篇原创文章 · 获赞 1 · 访问量 32

猜你喜欢

转载自blog.csdn.net/weixin_46401424/article/details/104655549