🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: comp.lang.functional
2 messages
2 total messages Started by Mike Goodrich Wed, 23 Dec 1992 21:07
Completely functional program in C
#935
Author: Mike Goodrich
Date: Wed, 23 Dec 1992 21:07
110 lines
2727 bytes
Greetings,
	The following is an example of a functional program in C I wrote after
reading MaClannan's book on FP. I would like to invite comments from the FP
community. I was pleased to find that the Sun C optimizer knows about tail recursion optimization so that this program runs as fast as the conventional
C version that it is based on.





/*
 * Hexdmp.c
 * 
 * Author: Mike Goodrich (804) 864-1790   goodrich@128.155.25.38  (goodrich@lynx.larc.nasa.gov)
 * 
 * Purpose to dump a given file to STDOUT in hex and ascii
 *
 * NOTE: This version was rewritten to adhere to the 'functional program' paradigm
 *
 * Usage:	hexdmp <filename>
 * 
 * Note:	If compiling under Microsoft C must use -J to overide signed char
 * default.
 */



#include	<stdio.h>
#define REC_SIZE	16
static unsigned char HexTab[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f'};

void            PutHexLine(), PutTextLine(), DoLine(), DumpFile();


main(argc, argv)
	int             argc;
	char          **argv;
{
	unsigned char   buff[REC_SIZE];

	if (argc < 2) {
		printf("\nUsage: hexdmp <filename>\n");
		exit(0);
	}
	DumpFile(fopen(argv[1], "rb"), buff);
}

void
PutTextLine(NumRead, buff)
	short           NumRead;
	unsigned char  *buff;
{
	switch (NumRead) {
	case 0:
		return;
	default:
		if (*buff < ' ' || *buff > '~') {	/* printable ? */
			printf(".");
		} else {
			printf("%c", *buff);
		}
		PutTextLine(NumRead - 1, buff + 1);
	}
}

void
PutHexLine(NumRead, buff)
	short           NumRead;
	unsigned char  *buff;
{
	switch (NumRead) {
	case 0:
		printf("\t");
		return;
	default:
		printf("%02x ", *buff);
		PutHexLine(NumRead - 1, buff + 1);
	}
}

void
DoLine(NumRead, buff, count, fp)
	short           NumRead, count;
	unsigned char  *buff;
	FILE           *fp;
{
	switch (NumRead) {
	case 0:
		return;
	default:
		printf("\n<%d>\t", count * REC_SIZE);
		PutHexLine(NumRead, buff);
		PutTextLine(NumRead, buff);
		DoLine(fread(buff, 1, REC_SIZE, fp), buff, count + 1, fp);
	}
}

void 
DumpFile(fp, buff)
	FILE *fp;
	unsigned char  *buff;
{
	if (fp == NULL) {
		printf("Error: cannot open input file\n");
		exit(-1);
	}
	DoLine(fread(buff, 1, REC_SIZE, fp), buff, 0, fp);
}
Re: Completely functional program in C
#936
Author: Fergus James HENDERSON
Date: Fri, 25 Dec 1992 18:02
110 lines
3280 bytes
goodrich@lynx.larc.nasa.gov (Mike Goodrich) writes:

>Greetings,
>	The following is an example of a functional program in C I wrote after
>reading MaClannan's book on FP. I would like to invite comments from the FP
>community.

I would not describe this program as particularly "functional".
It does have a lot of tail recursion, but there is not much else that
could be called functional.

[...]
>main(argc, argv)
>	int             argc;
>	char          **argv;
>{
>	unsigned char   buff[REC_SIZE];
>
>	if (argc < 2) {
>		printf("\nUsage: hexdmp <filename>\n");
>		exit(0);
>	}
>	DumpFile(fopen(argv[1], "rb"), buff);
>}

- exit(0) is not very functional
- failing to return a value from main() is not very functional
  (not to mention that it's not very good C either ;-)
- passing uninitialized parameters (buff) is not very functional

>void
>PutTextLine(NumRead, buff)
>	short           NumRead;
>	unsigned char  *buff;
>{
>	switch (NumRead) {
>	case 0:
>		return;
>	default:
>		if (*buff < ' ' || *buff > '~') {	/* printable ? */
>			printf(".");
>		} else {
>			printf("%c", *buff);
>		}
>		PutTextLine(NumRead - 1, buff + 1);
>	}
>}

Why the switch statements? What's wrong with using if statements?

Also, purely functional programs should have declarative I/O.
Since this is impossible, the next best thing is to confine all your
I/O to the very top-level of your program, or alternately to pass
pretend state-of-the-world arguments to and from a library of declarative
I/O functions (OK, admittedly that's a bit silly in this context, but
then it's a pretty silly context ;-)

>
>void
>PutHexLine(NumRead, buff)
>	short           NumRead;
>	unsigned char  *buff;
>{
>	switch (NumRead) {
>	case 0:
>		printf("\t");
>		return;
>	default:
>		printf("%02x ", *buff);
>		PutHexLine(NumRead - 1, buff + 1);
>	}
>}
>
>void
>DoLine(NumRead, buff, count, fp)
>	short           NumRead, count;
>	unsigned char  *buff;
>	FILE           *fp;
>{
>	switch (NumRead) {
>	case 0:
>		return;
>	default:
>		printf("\n<%d>\t", count * REC_SIZE);
>		PutHexLine(NumRead, buff);
>		PutTextLine(NumRead, buff);
>		DoLine(fread(buff, 1, REC_SIZE, fp), buff, count + 1, fp);
>	}
>}
>
>void 
>DumpFile(fp, buff)
>	FILE *fp;
>	unsigned char  *buff;
>{
>	if (fp == NULL) {
>		printf("Error: cannot open input file\n");
>		exit(-1);
>	}
>	DoLine(fread(buff, 1, REC_SIZE, fp), buff, 0, fp);
>}

fread() is not a very functional function, since the buff array is 
effectively passed by reference rather than by value.

-- 
Fergus Henderson             fjh@munta.cs.mu.OZ.AU      
This .signature virus is a self-referential statement that is true - but 
you will only be able to consistently believe it if you copy it to your own
.signature file!
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads