🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.c.moderated
Article #2181

Re: Question on DATA STRUCTURES

#2181
From: Richard A. O'Keefe
Date: Tue, 05 Mar 1996 12:25
263 lines
7625 bytes
titan@pegasus.odyssee.net (Molle Anthony) writes:
>#include <stdio.h>
>#include <conio.h>

Don't know what this does.  Not standard.

>#include <alloc.h>

I see you are using malloc().  Perhaps that's what this is for.
But the standard says malloc() is in <stdlib.h>

>#define VERS 1.0

>int stack1_top;
>int stack2_top;
>char letter_retrieved;
>int *stack1_ptr = &stack1_top;
>int *stack2_ptr = &stack2_top;
>void push(char letr);

This forward reference is quite pointless.  Just put the function
definition before its use.  It so happens that in this case, as in
many others, that this is the order I need to _read_ your program.


Where are the /*comments*/?

>typedef struct letter_tag
>{
>   char element;
>   struct letter_tag *next;
>} LETTER_TYPE;


Since the rest of the program manipulates pointers rather than records,
you will find life simpler if you write

	typedef struct Letter_Record *Letter_Pointer;

	struct Letter_Record {
	    Letter_Pointer next;
	    char           element;
	};

Another warning is that if you actually want to process *letters*, you
can't use 'char'.  The C standard allows char to range from -128 to +127,
and in many C compilers that _is_ the range.  That means that a great
many letters (62 of them in ISO Latin 1, more in IBM code page 850) will
be negative, which will give you trouble.  Let's clear this up a bit.


	typedef unsigned char Character;
	
	typedef struct Letter_Record *Letter_Pointer;
	struct Letter_Record {
	    Letter_Pointer next;
	    Character      element /* where isalpha(->element) */
	};


>void push(char letr)
>{
>   LETTER_TYPE *temp_ptr;
>   temp_ptr=(LETTER_TYPE*)malloc(sizeof(LETTER_TYPE));
>   if (temp_ptr==NULL)
>   {
>      printf("\nNot Enough Ram.");
>      return;
>   }
>   temp_ptr->element = letr;
>   temp_ptr->*next = temp_ptr;
>   stack1_ptr = temp_ptr;
>   stack1_ptr++;

>   return;
>}

Let's clear up some snags here.  First, error messages are supposed to be
written to the standard ERROR stream (stderr), not the standard OUTPUT
stream.  Second, the \n newline character is for ENDING lines, not for
beginning them.  In C this turns out to matter a lot, because ordinary
output to stdout is not shipped out to the terminal in most C implementations
until you write a newline, and it if the last line of output to a text stream
is not properly terminated with a newline a C implementation is allowed to
discard that line and not send it _anywhere_.  I have used C implementations
which took advantage of that.  So

	void push(Character letter) {
	    Letter_Pointer p;

	    p = malloc(sizeof *p);
	    if (p == NULL) {
		fprintf(stderr, "Cannot allocate %lu bytes\n",
			sizeof *p);
		exit(EXIT_FAILURE);
	    }
	    p->element = letter;

But now what can we put in p->next?  (temp_ptr->*next is not meaningful.)
We need a value of type Letter_Pointer.  If you want to keep a stack of
these things, then you need a variable that represents the stack.  So

	Letter_Pointer letter_stack;

	void push(Character letter) {
	    Letter_Pointer p;

	    p = malloc(sizeof *p);
	    if (p == NULL) {
		fprintf(stderr, "Cannot allocate a Letter_Record\n");
		exit(EXIT_FAILURE);
	    }
	    p->element = letter;
	    p->next = letter_stack;
	    letter_stack = p;
	}
			
>main()
>{
>  

>   
>   do
>   {
>      letter_retrieved= getchar();
>      push(letter_retrieved);
>   } while (letter_retrieved !='\n');

>   return;
>}


(1) main() is an int function and should either call exit() or return
    an int value.  letter_retrieved should be local.

(2) You keep on saying "letter", but I find to my shock and dismay
    that it isn't _true_.  Nowhere do you check whether the things
    you put on your stack are letters.  They can be any characters.

(3) Why is letter_retrieved a global variable?

(4) What do mean "retrieved"?  The value stored in that variable is
	the next character read in
    not a letter than is retrieved from anywhere.

	int main(void) {
	    int next_character;	/* Character values + EOF */

	    for (;;) {
		next_character = getchar();
		if (next_character == EOF || next_character == '\n') break;
		push(next_character);
	    }

	    return 0;
	}


Now let's put the pieces together.

	/*----------------------------------------------------------------------
	    File   : chrstack.c
	    Author : Richard A. O'Keefe
	    Updated: 5 March 1996
	    Purpose: Read a line of characters from standard input
		     and store them in a stack, represented as a
		     one-way linked list.
	----------------------------------------------------------------------*/

	#include <stdlib.h>
	#include <stdio.h>


	/*  The type 'Character' is used to hold 8-bit characters.
	    It may hold anything that getchar() returns except EOF.
	*/
	typedef unsigned char Character;
		
	/*--------------------------------------------------------------------*/

	/*  The type 'Char_Stack' implements a stack of characters
	    as a one-way linked list.
	*/
	typedef struct Char_Stack_Record *Char_Stack;
	struct Char_Stack_Record {
	    Char_Stack *next;
	    Character   element /* any 8-bit char */;
	};

	/*  There are four traditional operations on a stack:
	    1. create an empty stack
	    2. test whether a stack is empty
	    3. push a new element onto a stack
	    4. pop an element off a stack and return it
	    We'll give all these operations a reference to a stack
	    as their first parameter, because 1, 3, 4 all need to
	    modify the stack.
	    In C, references are represented by pointers.
	*/

	void make_empty(Char_Stack *stack) {
	    *stack = NULL;
	}

	int is_empty(const Char_Stack *stack) {
	    return *stack == NULL;
	}

	void push(Char_Stack *stack, Character element) {
	    Char_Stack p;

	    p = malloc(sizeof *p);
	    if (p == NULL) {
		fprintf(stderr, "Cannot allocate a Char_Stack_Record\n");
		exit(EXIT_FAILURE);
	    }
	    p->element = element;
	    p->next    = *stack;
	    *stack = p;
	}
	    
	Character pop(Stack_Stack *stack) {
	    Char_Stack p = *stack;
	    Character element;

	    if (p == NULL) {
		fprintf(stderr, "Cannot pop() an empty stack\n");
		abort();
	    }
	    element = p->element;
	    *stack  = p->next;
	    free(p);
	    return element;
	}

	/*--------------------------------------------------------------------*/

	int main(void) {
	    Char_Stack the_stack;
	    int the_next_character;

	    make_empty(&the_stack);
	    for (;;) {
		the_next_character = getchar();
		if (the_next_character == EOF) {
		    fprintf(stderr, "Unexpected end of input\n");
		    return EXIT_FAILURE;
		}
		if (the_next_character == '\n') {
		    break;
		}
		push(&the_stack, the_next_character);
	    }

	    /*  Why isn't the stack used here? */

	    return EXIT_SUCCESS;
	}


-- 
The election is over, and Australia lost; the idjits elected _politicians_!
Richard A. O'Keefe; http://www.cs.rmit.edu.au/~ok; RMIT Comp.Sci.
Technical Details
Message-ID: <4hhbsc$cdl@solutions.solon.com>
Path: arc1-ca.pugleaf.net!solon.com!not-for-mail
References: <4hdqop$8sd@solutions.solon.com>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!solon.com!not-for-mail
From: ok@cs.rmit.edu.au (Richard A. O'Keefe)
Newsgroups: comp.lang.c.moderated
Subject: Re: Question on DATA STRUCTURES
Date: 5 Mar 1996 06:25:48 -0600
Organization: Comp Sci, RMIT, Melbourne, Australia
Sender: clc@solutions.solon.com
Approved: clc@solutions.solon.com
Message-ID: <4hhbsc$cdl@solutions.solon.com>
References: <4hdqop$8sd@solutions.solon.com>
NNTP-Posting-Host: solutions.solon.com
X-Newsreader: NN version 6.5.0 #0 (NOV)