《C程序设计语言》(《The C Programming Language》)第二版第四章练习题

4-1:
编写函数strindex(s, t),它返回字符串t在s中最右边出现的位置。如果s中不包含t,则返回-1

#include <stdio.h>
#include <string.h>

#define MAXSIZE 1000

int getline(char s[], int lim);
int strindex(char s[], char t[]);

int main(void)
{
	char line[MAXSIZE];
    int found;
	char Pattern[MAXSIZE] = "ould";
    
	printf("请输入一条字符串\n");
	while(getline(line, MAXSIZE) > 0)
	{
		if((found = strindex(line, Pattern)) >= 0)
			printf("%s出现在字符串的%d位\n", Pattern, found);
		else
			printf("字符串中不包含%s\n", Pattern);

		printf("请继续输入\n");
	}

	return 0;
}

int getline(char s[], int lim)
{
	int c, i;
	i = 0;

	while(--lim > 0 && (c = getchar()) != EOF && c != '\n')
	{
		s[i++] = c;
	}

	if(c == '\n')
		s[i++] = c;

	s[i] = '\0';
	return i;
}

int strindex(char s[], char t[])
{
	int length_s = strlen(s) - 1;
	int length_t = strlen(t) - 1;
    int k;

	for(int i = length_s; i >= 0; i--)
	{
		for(int j = i, k = length_t; k >= 0 && s[j] == t[k]; j--, k--)
			;
		if(k < 0)
			return (i - length_t + 1);//-length_t返回的是待查找字符串首字符出现的位置,+1表示返回的是实际位置,而不是数组下标
	}
	return -1;
}

4-2:
对atof函数进行扩充,使它可以处理形如123.45e-6的科学表示法,其中,浮点数后面可能会紧跟一个e或E以及一个指数(可能有正负号)

#include <stdio.h>
#include <ctype.h>//包含isspace()库函数和isdigit()库函数,前者判断空格,后者判断数字

#define MAXSIZE 40

int getline(char s[], int lim);
double atof(char s[]);

int main(void)
{
	char line[MAXSIZE];
	double result;

	printf("请输入待转换的字符串\n");

	while(getline(line, MAXSIZE) > 0)
	{
		result = atof(line);
		printf("字符串中的数字为:%lf", result);

		printf("继续输入\n");
	}

	return 0;
}

int getline(char s[], int lim)
{
	int c, i;
	i = 0;

	while(--lim > 0 && (c = getchar()) != EOF && c != '\n')
	{
		s[i++] = c;
	}

	if(c == '\n')
		s[i++] = c;

	s[i] = '\0';
	return i;
}

double atof(char s[])
{
	double val;
	double power = 1.0;
	double sign;
	int mask;      //标记e后面的符号
	int power_e;   //记录指数大小
	double result; //结果值

	for(int i = 0; isspace(s[i]); i++)
		;
	sign = (s[i] == '-')? -1 : 1; 

	if(s[i] == '+' || s[i] == '-')
		i++;
	
	for(val = 0; isdigit(s[i]); i++)
		val = 10.0 * val + (s[i] - '0');
	
	if(s[i] == '.')
	{
		i++;
		for(; isdigit(s[i]); i++)
		{
			val = 10.0 * val + (s[i] - '0');
			power *= 10.0;
		}
	}

	result = sign * val / power;

	if(s[i] == 'e' || s[i] == 'E')
	{
		i++;
		if(s[i] == '-')
			mask = 1;
		else if(s[i] == '+' || isdigit(s[i]))
			mask = 0;
		else
			return result;

		if(s[i] == '-' || s[i] == '+')
			i++;

		for(power_e = 0; isdigit(s[i]); i++)
			power_e = 10 * power_e + (s[i] - '0');

		if(mask)//e后面符号为-时,表示除以power_e个10.0
		{
			while(power_e > 0)
			{
				result /= 10.0;
				power_e--;
			}
			return result;
		}
		else//e后面符号为+或没有符号时,表示乘以power_e个10.0
		{
			while(power_e > 0)
			{
				result *= 10.0;
				power_e--;
			}
			return result;
		}
	}
	else//数字后面没有e或E
		return result;
}

4-3、4-4、4-5、4-6:
请对现在的计算器程序进行扩充:
1.在该程序中加入取模(%)运算符,并注意考虑负数的情况
2.添加以下命令:在不弹出元素的情况下打印栈顶元素,复制栈顶元素,交换栈顶两个元素的值,清空栈
3.增加访问sin、exp与pow库函数的操作,这些库函数包含在<math.h>头文件中
4.增加处理变量的命令(提供26个具有单个英文字母变量名的变量)。增加一个变量存放最近打印的值

/*关于练习4-6,我不太明白变量需要实现什么功能,是像C语言本身的变量一样可以
赋值,可以使用?还是其他?我假定变量的功能和C语言本身的变量类似,例如在输
入行中输入 2 4 + A A A +,2 + 4 的结果赋值给第一个A,赋值结束,变量可以正
常使用,而A A +是表示需要使用变量完成操作,打印结果为A + A的值,即12*/
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#include <stdlib.h>

#define RAD_TO_DEG (180 / (4 * atan(1)))//将弧度转换为角度的公式,即1弧度 = 180 / π 度,其中π = 4 * atan(1)
#define MAXOP 100
#define NUMBER '0'
#define MAXVAL 100
#define BUFSIZE 100
#define MAXVAR 26

int sp = 0;
double val[MAXVAL];
char buf[BUFSIZE];
int bufp = 0;

int getop(char []);
void push(double);
double pop(void);
int getch(void);
void ungetch(int);
void printf_stack_top(void);
void copy_stack_top(void);
void change_stack_top(void);
void empty_stack(void);

int main(void)
{
	int type, i;
	double op2;
	double prev;        //记录最近打印的值
	char s[MAXOP];
	double var[MAXVAR];//包含26个单个英文字母的变量数组
	int print = 0;     //记录最近是否有打印的值
	int mask = 0;      //标记变量是否已赋值

	for(i = 0; i < MAXVAR; i++)//对每个变量的值进行初始化
		var[i] = 0.0;

	while((type = getop(s)) != EOF)
	{
		switch(type)
		{
		case NUMBER:
			push(atof(s));
			break;

		case '+':
			push(pop() + pop());
			break;

		case '*':
			push(pop() * pop());
			break;

		case '-':
			op2 = pop();
			push(pop() - op2);
			break;

		case '/':
			op2 = pop();
			if(op2 != 0.0)
				push(pop() / op2);
			else
				printf("error: zero divisor\n");
			break;

		case '%':
			op2 = pop();
			if(op2 != 0.0)
				push((int)pop() % (int)op2);//由于取模运算符只能执行整型数据之间的取模,因此需要将两个double类型数据强制转换为int类型
			//如果需要处理浮点型数据,可以使用<math.h>头文件中的库函数fmod(),将上面的语句更改为push( fmod(pop(), op2) );
			//如果不想使用库函数,但是需要处理浮点型数据,那么可以先将浮点数乘以n个10转换为整数,取模运算后将结果除以n个10还原,但是很麻烦

			else
				printf("error: zero divisor\n");
			break;

		case 'd'://打印栈顶元素
			printf_stack_top();
			break;

		case 'f'://复制栈顶元素
			copy_stack_top();
			break;

		case 'j'://交换栈顶两个元素的值
			change_stack_top();
			break;

		case 'q'://清空栈
			empty_stack();
			break;

		case 's'://sin函数,注意sin、cos、tan接受的参数为弧度,不是角度
			push( sin( (pop() / RAD_TO_DEG) ) );//将输入的角度转化为弧度
			break;

		case 'c'://cos函数
			push( cos( (pop() / RAD_TO_DEG) ) );
			break;

		case 't'://tan函数
			op2 = pop();
			if(op2  != 90)
				push( tan( (pop() / RAD_TO_DEG) ) );
			else
				printf("tan90 is invalid value\n");
			break;

		case 'e'://exp函数,返回e的指数幂
			push( exp( pop() ) );
			break;

		case 'p'://pow函数,返回参数1的参数2次幂,即假设pow(2, 3),返回2^3的值
			op2 = pop();
			push( pow( pop(), op2 ) );
			break;

		case 'v':
			if(print)
				printf("The most recently printed value is %.8g\n", prev);
			else
				printf("No recently printed values!\n");
			break;

		case '\n':
			prev = pop();
			print = 1;
			printf("\t%.8g\n", prev);
			break;

		default:
			if(type >= 'A' && type <= 'Z')
			{
				if(mask == 0)
				{
					var[type - 'A'] = pop();
					mask = 1;
				}
				else
					push(var[type - 'A']);
			}
			//上面的语句有一个很大的缺陷,mask只能标记有没有为变量赋值,但是无法标记是为哪一个变量赋的值
			//如果需要改进,就要使用结构,但是这还没有开始学,我尽量按照书本上的进度来
			//如果想改进,就创建一个26个元素的结构数组,结构包含一个mask成员和一个value成员
			else
				printf("error: unkown command %s\n", s);
			break;
		}
	}
	return 0;
}

void push(double f)
{
	if(sp < MAXVAL)
		val[sp++] = f;//按照从栈尾到栈顶的顺序依次压入数据
	else
		printf("error: stack full, can't push %g\n", f);
}

double pop(void)
{
	if(sp > 0)
		return val[--sp];//按照栈顶到栈尾的顺序依次取出数据
	else
	{
		printf("error: stack empty\n");
		return 0.0;
	}
}

int getop(char s[])
{
	int i, c;
	while((s[0] = c = getch()) == ' ' || c == '\t')
		;
	s[1] = '\0';
	if(!isdigit(c) && c != '.')
		return c;
	i = 0;
	if(isdigit(c))
		while(isdigit(s[++i] = c = getch()))
			;

	if(c == '.')
		while(isdigit(s[++i] = c = getch()))
			;

	s[i] = '\0';
	if(c != EOF)
		ungetch(c);
	return NUMBER;
}

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;
}

void printf_stack_top(void)
{
	if(sp > 0)
		printf("top of stack: %8g\n", val[sp - 1]);
	else
		printf("stack is empty\n");
}

void copy_stack_top(void)
{
	double temp = pop();//先弹出栈顶元素,将其拷贝给临时变量,将该变量压入两次,完成复制工作

	push(temp);
	push(temp);
	printf("Done!\n");
}

void change_stack_top(void)
{
	double temp1 = pop();//temp1是栈顶第一个元素
	double temp2 = pop();//temp2是栈顶第二个元素

	push(temp1);//temp1先压入,temp2后压入,temp1变成栈顶第二个元素,temp2变成栈顶第一个元素
	push(temp2);
}

void empty_stack(void)
{
	sp = 0;
}

4-7:
编写一个函数ungets(s),将整个字符串s压回到输入中。ungets函数需要使用buf和bufp吗?它能否仅适用ungetch函数?

#include <stdio.h>
#include <string.h>

#define MAXSIZE 100
#define BUFSIZE 100

char buf[BUFSIZE];
int bufp = 0;

void ungets(char s[]);

int getch(void);
void ungetch(int);


int main(void)
{
	char string[MAXSIZE] = "It's a test statement";
	int c;

	ungets(string);
	while((c = getch()) != EOF)
		putchar(c);

	return 0;
}

void ungets(char s[])
{
	int length = strlen(s);
	while(length > 0)
	{
		ungetch(s[--length]);
	}
}


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;
}

4-8:
假定最多只压回一个字符,请相应的修改getch和ungetch这两个函数

#include <stdio.h>

int bufp = EOF;

void ungets(char s[]);

int getch(void);
void ungetch(int);


int main(void)
{
	int c;
	while((c = getch()) != EOF)
	{
		if(c == '\n')
			ungetch('*');
		putchar(c);
	}

	return 0;
}

int getch(void)
{
	int c;
	c = (bufp == EOF) ? getchar() : bufp;
	bufp = EOF;
	return c;
}

void ungetch(int c)
{
	if(bufp != EOF)
		printf("ungetch: too many characters\n");
	else
		bufp = c;
}

4-9:
以上介绍的getch与ungetch函数不能正确的处理压回的EOF。考虑压回EOF时应该如何处理?请实现你的设计方案

将声明中的
char buf[BUFSIZE];
修改为int buf[BUFSIZE];
再将getop函数中的
if(c != EOF)
ungetch©;
去除if条件判断

4-10:
另一种方法是通过getline函数读入整个输入行,这种情况下可以不使用getch与ungetch函数。请运用这一方法修改计算器程序

/*此程序的主要部分不需要改动,仍然保留,主要修改getop函数和main函数,定义
一个外部字符数组,当遇到输入的数字时,将数字以字符形式存储在字符数组中返回
给main函数,交由atof转换为数字,同时我们定义一个int类型外部变量,作为输入
字符串的下标,这样从getop函数返回到main函数再次进入getop函数时,我们仍可以
从上次读取到的地方继续读取*/
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#include <stdlib.h>

#define RAD_TO_DEG (180 / (4 * atan(1)))//将弧度转换为角度的公式,即1弧度 = 180 / π 度,其中π = 4 * atan(1)
#define MAXOP 100
#define NUMBER '0'
#define MAXVAL 100
#define MAXVAR 26
#define NUMBERSIZE 100

int sp = 0;
char number[NUMBERSIZE];//储存输入的数字字符
double val[MAXVAL];
int index = 0;          //index为s字符数组的下标,是一个外部变量,可以跨函数使用

int getline(char s[], int lim);
int getop(char []);
void push(double);
double pop(void);
void printf_stack_top(void);
void copy_stack_top(void);
void change_stack_top(void);
void empty_stack(void);

int main(void)
{
	int type, i;
	double op2;
	double prev;        //记录最近打印的值
	char s[MAXOP];
	double var[MAXVAR];//包含26个单个英文字母的变量数组
	int print = 0;     //记录最近是否有打印的值
	int mask = 0;      //标记变量是否已赋值

	for(i = 0; i < MAXVAR; i++)//对每个变量的值进行初始化
		var[i] = 0.0;

	while(getline(s, MAXOP) > 0)
	{
		while((type = getop(s)) != '\0')
		{
			switch(type)
			{
		    case NUMBER:
				push(atof(number));
			    break;

		    case '+':
			    push(pop() + pop());
			    break;

		    case '*':
			    push(pop() * pop());
			    break;

		    case '-':
			    op2 = pop();
			    push(pop() - op2);
			    break;

		    case '/':
			    op2 = pop();
			    if(op2 != 0.0)
					push(pop() / op2);
			    else
				    printf("error: zero divisor\n");
			    break;

		    case '%':
				op2 = pop();
			    if(op2 != 0.0)
					push((int)pop() % (int)op2);
			    else
				    printf("error: zero divisor\n");
			    break;

			case 'd'://打印栈顶元素
				printf_stack_top();
				break;

		    case 'f'://复制栈顶元素
			    copy_stack_top();
			    break;

		    case 'j'://交换栈顶两个元素的值
			    change_stack_top();
			    break;

		    case 'q'://清空栈
			    empty_stack();
			    break;

		    case 's'://sin函数,注意sin、cos、tan接受的参数为弧度,不是角度
			    push( sin( (pop() / RAD_TO_DEG) ) );//将输入的角度转化为弧度
			    break;

		    case 'c'://cos函数
			    push( cos( (pop() / RAD_TO_DEG) ) );
			    break;

		    case 't'://tan函数
			    op2 = pop();
			    if(op2  != 90)
					push( tan( (pop() / RAD_TO_DEG) ) );
			    else
					printf("tan90 is invalid value\n");
			    break;

		    case 'e'://exp函数,返回e的指数幂
				push( exp( pop() ) );
			    break;

		    case 'p'://pow函数,返回参数1的参数2次幂,即假设pow(2, 3),返回2^3的值
			    op2 = pop();
			    push( pow( pop(), op2 ) );
			    break;

		    case 'v':
			    if(print)
					printf("The most recently printed value is %.8g\n", prev);
				else
					printf("No recently printed values!\n");
				break;

			case '\n':
				prev = pop();
			    print = 1;
			    printf("\t%.8g\n", prev);
			    break;

			default:
			    if(type >= 'A' && type <= 'Z')
				{
					if(mask == 0)
					{
						var[type - 'A'] = pop();
					    mask = 1;
					}
				    else
					    push(var[type - 'A']);
				}
			    else
				    printf("error: unkown command %s\n", s);
			    break;
            }
        }
		printf("继续输入\n");
		index = 0;//将index重置为0
    }
	return 0;
}

void push(double f)
{
	if(sp < MAXVAL)
		val[sp++] = f;//按照从栈尾到栈顶的顺序依次压入数据
	else
		printf("error: stack full, can't push %g\n", f);
}

double pop(void)
{
	if(sp > 0)
		return val[--sp];//按照栈顶到栈尾的顺序依次取出数据
	else
	{
		printf("error: stack empty\n");
		return 0.0;
	}
}

int getop(char s[])
{
	int c;
	while(s[index] != '\0')
	{
		if (s[index] == ' ' || s[index] == '\t')//跳过空格和制表符
			index++;

	    else if (!isdigit(s[index]) && s[index] != '.')//当遇到非数字字符和非.字符返回该字符
		{
			c = s[index];
			index++;//index递增,跳过该字符
			return c;
		}

	    else if (isdigit(s[index]))
		{
			int i = 0;
			while(isdigit(s[index]))
			{
				number[i++] = s[index];
				index++;
			}

	        if(s[index] == '.')
			{
				number[i++] = s[index];
				index++;
				while(isdigit(s[index]))
				{
					number[i++] = s[index];
					index++;
				}
			}
			number[i] = '\0';//number数组此时存储一个数字的字符形式
			return NUMBER;
		}
	}
	return s[index];//返回空字符
}

void printf_stack_top(void)
{
	if(sp > 0)
		printf("top of stack: %8g\n", val[sp - 1]);
	else
		printf("stack is empty\n");
}

void copy_stack_top(void)
{
	double temp = pop();//先弹出栈顶元素,将其拷贝给临时变量,将该变量压入两次,完成复制工作

	push(temp);
	push(temp);
	printf("Done!\n");
}

void change_stack_top(void)
{
	double temp1 = pop();//temp1是栈顶第一个元素
	double temp2 = pop();//temp2是栈顶第二个元素

	push(temp1);//temp1先压入,temp2后压入,temp1变成栈顶第二个元素,temp2变成栈顶第一个元素
	push(temp2);
}

void empty_stack(void)
{
	sp = 0;
}

int getline(char s[], int lim)
{
	int c, i;
	i = 0;

	while(--lim > 0 && (c = getchar()) != EOF && c != '\n')
	{
		s[i++] = c;
	}

	if(c == '\n')
		s[i++] = c;

	s[i] = '\0';
	return i;
}

4-11:
修改getop函数,使其不必使用ungetch函数。提示,可以使用一个static类型的内部变量解决问题

/*ungetch函数的本来目的是将输入的非数字字符压入缓冲区buf[]中,例如,如果输
入123a,getop函数首先读取所有数字字符,存储到s字符数组中,然后利用ungetch
函数将字符'a'压入缓冲区buf[]中,bufp + 1,程序控制权返回给main函数,将s数
组中的数字字符转化为数字,循环迭代,重新进入getop函数,语句c = getch()调用
getch函数,判断bufp > 0,返回上一次储存在缓冲区buf中的字符'a',于是c ==
'a',继续执行getop函数中的语句
我们可以在getop函数中定义一个静态局部变量,该变量具有静态存储期、块作用域
和无链接,即该变量只能在getop函数中被使用,但是离开该函数该变量不会消失*/
int getop(char s[])
{
	int i;
	static int c = ' ';//初始化变量,静态局部变量只能初始化一次,即退出再
	//进入该函数时,变量不会再次初始化,其值为上一次退出该函数时赋的值
	
	while((s[0] = c = getch()) == ' ' || c == '\t')
		;
	s[1] = '\0';
	if(!isdigit(c) && c != '.')
		return c;
	i = 0;
	if(isdigit(c))
		while(isdigit(s[++i] = c = getch()))
			;

	if(c == '.')
		while(isdigit(s[++i] = c = getch()))
			;

	s[i] = '\0';
	
	return NUMBER;
}

4-12:
运用printd函数的设计思想编写一个递归版本的itoa函数,即通过递归调用把整数转换为字符串

#include <stdio.h>

#define MAXSIZE 1000

void itoa(int n, char s[]);

int main(void)
{
	int number = 0;
	char string[MAXSIZE];

	printf("请输入一个数字\n");
	scanf("%d", &number);
	
	itoa(number, string);
	printf("%s\n", string);
	return 0;
}

void itoa(int n, char s[])
{
	static int i = 0;
	unsigned int u;

	if(n < 0)
	{
		u = -n;
		s[i++] = '-';
	}
	else
		u = n;

	if((u / 10) > 0)
		itoa(u / 10, s);

	s[i++] = u % 10 + '0';
	
	s[i] = '\0';
}

4-13:
编写一个递归版本的reverse(s)函数,以将字符串s倒置

#include <stdio.h>
#include <string.h>

#define MAXSIZE 1000

void itoa(int n, char s[]);
void reverse(char s[]);

int main(void)
{
	int number = 123456;
	char string[MAXSIZE];
	itoa(number, string);
	printf("%s\n", string);
	return 0;
}

void itoa(int n, char s[])
{
	int i;
	unsigned int u;
	u = (n < 0) ? -n : n;

	i = 0;

	do{
		s[i++] = (u % 10) + '0';
	}while((u /= 10) > 0);

	if(n < 0)
		s[i++] = '-';
	
	s[i] = '\0';
	reverse(s);
}

void reverse(char s[])
{
	static int i = 0;
	static int j = strlen(s) - 1;
	int temp;

	if(i < j)
	{
		temp = s[i];
		s[i] = s[j];
		s[j] = temp;
		i++;
		j--;
		reverse(s);
	}
}
//感觉这个递归不怎么简洁.....

4-14:
定义宏swap(t, x, y)以交换t类型的两个参数。(使用程序块结构会对你有所帮助)

#include <stdio.h>
#include <string.h>

#define SWAP(t, x, y) { t temp = x;\
	x = y;\
	y = temp;\
	}

#define MAXSIZE 1000

void itoa(int n, char s[]);
void reverse(char s[]);

int main(void)
{
	int number = 123456;
	char string[MAXSIZE];
	itoa(number, string);
	printf("%s\n", string);
	return 0;
}

void itoa(int n, char s[])
{
	int i;
	unsigned int u;
	u = (n < 0) ? -n : n;

	i = 0;

	do{
		s[i++] = (u % 10) + '0';
	}while((u /= 10) > 0);

	if(n < 0)
		s[i++] = '-';
	
	s[i] = '\0';
	reverse(s);
}

void reverse(char s[])
{
	int temp;
	for(int i = 0; s[i] != '\0'; i++)
		;
	i--;
	for(int j = 0; i > j; j++, i--)
	{
		SWAP(int, s[i], s[j]);
	}
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本书是由C语言设计者Brian W. Kernighan和Dennis M. Ritchie编写的一部介绍标准C语言及其程序设计方法的权威性经典著作。全面、系统地讲述了C语言的各个特性及程序设计的基本方法,包括基本概念、类型和表达式、控制流、函数与程序结构、指针与数组、结构、输入与输出、UNIX系统接口、标准库等内容。   本书的讲述深入浅出,配合典型例证,通俗易懂,实用性强,适合作为大专院校计算机专业或非计算机专业的C语言教材,也可以作为从事计算机相关软硬件开发的技术人员的参考书。 在计算机发展的历史上,没有哪一种程序设计语言像C语言这样应用如此广泛。   本书原著 即为C语言设计者之一Dennis M.Ritchie和著名的计算机科学家Brian W.Kernighan合著的 一本介绍C语言的权威经典著作。我们现在见到的大量论述C语言程序设计的教材和专著均以 此书为蓝本。原著第1中介绍的C语言成为后来广泛使用的C语言本—— 标准C的基础。人们熟知的“hell, World”程序就是由本书首次引入的,现在,这一程序已经成为所有程序设 计语言入门的第一课。 原著第2根据1987年制定的ANSIC标准做了适当的修订.引入了最新的语言形式,并增加了新的示例,通过简洁的描述、典型的示例,作者全面、系统、准确地讲述了C语言的各 个特性以及程序设计的基本方法。对于计算机从业人员来说,本书是一本必读的程序设计语 言方面的参考书。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值