⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 examples.doc

📁 Unix下的MUD客户端程序
💻 DOC
字号:
VTC ExamplesPurpose-------This file is intended to help programmers learn how to effectively use VTC by providing examples.	It is assumed that the programmer is somewhat familiar with the basics of the language, which are described in vtc.doc.Text processing---------------This is an example of a function which processes a string.  Itconverts sequences beginning with '^' in a string into controlcharacters.// Translate ^x sequences in a stringfunc ctrl(str) [r, ptr] {	r = "";				// Initialize return string	while (ptr = strchr(str, '^')) {		strcat(r, str, ptr - str); // Copy up to ^		if (*++ptr == '^')	// Compress ^^ to ^			strcat(r, "^");		else if (*ptr == '?')	// ^? is a DEL			strcat(r, "\177");		else if (*ptr)		// Regular control char			r[strlen(r)] = ucase(*ptr) - 'A' + 1;		str = ptr + 1;		// Move past ^ combo	}	r += str;			// Copy last part of str	return r;}This function illustrates a general optimization principle: avoidtraversing a string when possible.  VT can traverse the string with aprimitive like strchr() much more quickly than VTC can with a loop.The time difference can be important in a frequently-used function.Text processing functions can take advantage of VTC's memorymanagement in a number of ways.  First, you don't ever need to worryabout allocating memory for a string, or reading or writing out of thebounds of allocated memory.  The statement 'r[strlen(r)] = ...;'causes VT to extend the string as necessary to add the extracharacter, and to add its own null terminator at the end.  You canalso count on the elements beyond the end of a string and before thebeginning to be 0.  The only thing to watch for is writing before thebeginning of a string, which will produce an error.Another convenience is the ability to call ctrl(), use the value, andforget about it.  VT will automatically clean it up.  For instance,	bind(ctrl(s), funcptr);will not leak memory.Sometimes it is necessary to traverse a string, as in the followingfunction, which converts control characters in a string to sequencesbeginning with '^'.func dispstr(str) [r] {	for (r = ""; *str; str++) {	// Traverse str		if (c > 31 && c != 127) // Ordinary char, just copy			*r++ = *str;		else {			// Write as control char			*r++ = '^';			*r++ = (*str == 127) ? '?' : *str + 'A' - 1;		}	}	return base(r);}This could be done more efficiently using strcspn(), but the codewould be highly unreadable.  Also, since this routine is likely onlyto be used in I/O routines, speed is probably not important.Note the use of the base() primitive, which allows us to forget aboutthe beginning of the string pointed to by r until the end of thefunction.Finally, here is an application of VTC string management to formatting:// Return a string of a given lengthfunc field(str, len) [r] {	strcpy(r = "", str);		// Copy string	r[len] = '\0';			// Lengthen or shorten	return r;}If str is longer than len, the second statement will shorten it, as inC.  If str is shorter, the second statement will add spaces up untillen.Variable-argument functions---------------------------Often it is natural to want to design a function that works on avariable number of arguments.  For instance, the following functionsimplifies the task of constructing an array:// Return a table containing the arguments as elementsfunc table() [t] {	t = alloc(argc);	acopy(t, argv, argc);	return t;}Because VT places the arguments to a function call in an array, we canuse the acopy() primitive to copy this array into a newly-allocatedtable.  This is much preferrable to assigning the elements one-by-one.Optional arguments are also useful in improving the flexibility of afunction interface.  Consider a function getline(), which reads a linefrom a remote and aborts the current function if the remotedisconnects before the line could be read.  If we do not specify anargument for the remote connection, it should default to the currentremote.func getline(/ rmt) [line] {	rmt ?:= cur_rmt;	// Default to current remote	line = read(rmt);	if (line)		// Line successfully read		return line;	abort();	// Remote connection closed}The argument after the '/' in the argument list is optional.  If wecall getline() with no arguments, rmt defaults to NULL.  We caninitialize it using the '?:=' operator, which changes a variable'svalue only if it contains a false value (NULL or 0).You can also specify multiple optional arguments for functions, aswell as mandatory and optional arguments.  The general syntax is:	func name(arg1, arg2, ... / optarg1, optarg2, ...)Remote I/O and text formatting: two-column WHO list---------------------------------------------------The 'extras' directory in the VT archive contains code to get commandresponses from remote connections that are based on MUDs.  Thisexample obtains a WHO list from a mud and formats it into two columns.two_col_who() makes use of regexps to to its formatting.  This isoften a useful technique for pulling pieces out of a line that has acomplicated syntax.  Parts of a line matching parenthesizedexpressions in a regexp can be pulled out with regmatch().two_col_who() also makes use of the list-handling primitives in thedistribution's util.vtc.  A 'list' in this sense is a VTC array suchthat if l is a list, *l is the length of the list and l[1..*l] are theelements in l.  add_list(list, elem) adds an element to the end of alist.  add_list(list, elem, pos) inserts an element at <pos> in thelist.  del_list(list, pos) deletes the element at <pos>.First, if you have not already done so:Load("rmtio");Then:wpat = regcomp("^([^ ]+) +(([0-9]+d)? [^ ]+ +[^ ]+)");func two_col_who(/ rmt, win) [who, i, width, name, conn, mid, p] {	// Get WHO list	who = get_cmd_response("WHO", rmt);	del_list(who, 1);	// Strip off header	del_list(who, *who);	// Strip off tail	// sort(who); would go here (see below)	// Reformat lines	width = cols / 2;	for (i = 1; i <= *who; i++) {		if (!regexec(wpat, who[i]))			return output("Error: invalid who list entry\n");		name = regmatch(wpat, 1); // Name field		conn = regmatch(wpat, 2); // Connect+idle time		who[i] = field(name, width - 15 - strlen(conn)) + conn;	}	// Now form second column from latter half of list	mid = (*who + 1) / 2;	// Number of rows in two-column list	for (i = 1; i <= mid; i++) {		// The strcpy() will add spaces as needed.		if (who[mid + i])			strcpy(who[i] + width, who[mid + i]);	}	// Display the list	for (i = 1; i <= mid; i++)		output(who[i] + "\n", S_NORM, win);}Changing the format of the two-column list is fairly easy; simplymodify the regexp and/or the first for loop to produce lines of thedesired format.If we wish to sort the list by names, we can do so with a simpleinsertion sort:func sort(l) [i, j] { // Insertion sort using stricmp()	for (i = 1; i <= *l; i++) {		for (j = 1; j < i && stricmp(l[j], l[i]) < 0; j++);		if (i != j) {			add_list(l, l[i], j);			del_list(l, i + 1);		}	}}and then add 'sort(who);' in the place marked in the function above.Scheme interpreter------------------The file scheme.vtc is a documented example of a large-scale VTCapplication, a Scheme interpreter.  It illustrates a number of VTCfeatures not presented in this file.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -