[prog] learning c

Alice Moomlyn alice_moomlyn at yahoo.com
Sat Mar 27 07:59:50 EST 2004


Hello Everybody.

I am teaching myself c and would like it if anybody
who has time would be able to look over what I've
written and give me some feedback.

At the moment I'm trying to get my head around strings
and pointers so I've written a little program that
reads in a string and reverses it (using two different
methods) and then prints it out again.

I don't really know what I'm doing so any and all
comments/suggestions/criticisms would be very helpful!

Sincere apologies for the formatting. 
Blame yahoo.

.....................................................


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

#define BUFFSIZE 20  /* size of initial buffer */
#define MAXBUFF 20   /* maximum number of buffers */


/* start function prototypes---------------------*/

/* returns a pointer to a string read from standard
input, of maximum length 20,971,500 characters.
This function uses malloc so it may fail if there
isn't
enough memory, in which case it will return a NULL
pointer.

The function will also return NULL if the input is
longer than 20,971,500 characters.

It is the responsibility of the programmer using the
function to free() the returned string when
finished.*/

char *alice_getstring();

/* searches through a string for the newline
character,
   returns the number of characters searched if found,
   or 0 if not found. */

int alice_endline(char *string, int size);

/* returns the length of the character string pointed
to by s, (including the NULL terminator) or 0 if s is
not properly NULL terminated 

The characters which are valid for strings are asci
32-126 (inclusive) plus tab (ascii 9)

If the string contains any other characters, including
'\n' and '\r' it will return 0 */

int alice_length(char *s);

/* returns a new string which contains letters in the
reverse order of the original string. The function
uses malloc to allocate memory for the new string. If
malloc fails the function will return NULL
   
It is the responsibility of the programmer who uses
the function to free() the returned string after use.
*/

char *alice_reverse1(char* string, int size);

/* same as alice_reverse1 but uses pointer notation
instead of array notation */

char *alice_reverse2(char* string, int size);


/* end function prototypes-------------------------*/

int main(void)
{
   char *s1, *s2, *s3;

   puts("Enter a string of any length: ");

   if ((s1 = alice_getstring()) == NULL)
   {
       puts("Out of memory!");
       return -1;
   };
   puts("\nThis is the string you entered:");
   puts(s1);

   if ( (s2 = alice_reverse1( s1, alice_length(s1) ) )
== NULL)
   {
       puts("Out of memory!");
       return -1;
   };
   puts("\nReversed using array notation:");
   puts(s2);

   if ( (s3 = alice_reverse2( s1, alice_length(s1) ) )
== NULL)
   {
        puts("Out of memory!");
        return -1;
   };
   puts("\nReversed using pointer notation:");
   puts(s3);

   free(s1);
   free(s2);
   free(s3);

   return 0;
}


char *alice_getstring()
{
   /* start variable declarations ------------*/

   int buffsize = BUFFSIZE;  /* size of first buffer
*/

   int totalbuff = 0;  /* variable to keep track of
                          number of characters already
                          read */

   int counter = 0;   /* variable to keep track of
                        number of buffers used */

   /* This variable will be True, only when an 
      '\n' has been read */
   enum { FALSE, TRUE } finished = FALSE;

   /* an array of pointers to character strings */
   char *p[MAXBUFF];

   int endline;     /* stores number of position
                       actually used to store input 
                       in the final buffer
                       (the rest will be garbage) */

   int loopvar;     /* used for looping over the 
                       number of buffers */

   char *result;    /* will contain the complete 
                       string */

   /* end variable declarations ----------------*/

   /* start 'read' loop ------------------------*/

   /* Begins by reading into a buffer of size
BUFFSIZE.
      If no newline encountered, creates a new buffer 
      of size 2*BUFFSIZE and reads into that. If still
     
      no newline encountered, creates a buffer of size

      4*buffsize and reads into that, etc..
      Each new buffer is twice the size of the last 
      one, and the maximum number of buffers is
MAXBUFF

      If malloc failes or all the buffers are filled, 
      returns NULL */

   while ((finished == FALSE) && (counter < MAXBUFF))
   {
      /* malloc memory for next buffer */
      if ( ( p[counter] = malloc(
buffsize*sizeof(char) ) )  == NULL )
      {
         /* out of memory - do some cleanup, then
            return NULL */
         loopvar = 0;
         while (loopvar < counter)
            free( p[loopvar] );

         return NULL;
      };

      /* read into next buffer */
      p[counter] = fgets( p[counter],
buffsize*sizeof(char), stdin );

      /* check for newline character */
      endline = (alice_endline(p[counter],buffsize));

      if (endline == FALSE)     /* still more input */
      {
         totalbuff += buffsize; /* keep track of
number 
                                 of characters read */
         buffsize *= 2;         /* double the size of 
                                  next buffer */
         counter++;             /* keep track of
number 
                                   of buffers used */
      }

      else                      /* end of input */
      {
         totalbuff += endline;  /* the last buffer
will 
                                probably not be full
*/
         finished = TRUE;       /* break out of 'read'
          
                                    loop */
      }
   };

   /* end 'read' loop
-----------------------------------------------------*/

   /* start highly unlikely scenario that input more
than 20 million chars */

   if (finished == FALSE)
   {
       /* cleanup then return NULL */
       loopvar = 0;
       while (loopvar < MAXBUFF)
           free ( p[loopvar] );

       return NULL;
   };

   /* end highly unlikely scenario
--------------------------------------*/

   /* start 'combine' loop 
---------------------------------------------*/

   /* make us a buffer big enough to hold the entire
string */
   if ( ( result = realloc( p[0],
totalbuff*sizeof(char) ) ) == NULL )
   {
      /* out of memory - do some cleanup, then return
NULL */
      loopvar = 0;
      while (loopvar <= counter)
         free( p[loopvar] );

      return NULL;
   };

   /* If the whole string fitted into the first buffer
then we're done */
   if (counter == 0)
   {
      result[totalbuff] = '\0'; /* add NULL terminator
*/
      return result;
   };

   /* otherwise contcatenate the remaining buffers
into one */

   /* start from 1 because we already handled the
zeroth buffer */
   loopvar = 1;

   /* we need to know how big each buffer is */
   buffsize = BUFFSIZE;

   while (loopvar < counter)
   {
       /* calculate size of next buffer */
       buffsize *= 2;

       /* append next buffer to end of result string
*/
       result = strncat(result, p[loopvar], buffsize);

       /* free memory used by temporary buffer */
       free(p[loopvar]);

       /* get next buffer */
       loopvar++;
   }

   /* the last buffer will probably not be full
      so it needs to be handled specially */

   result = strncat(result, p[loopvar], endline);
   free(p[loopvar]);

   /* end 'combine' loop
----------------------------------------------*/

   result[totalbuff] = '\0';  /* Add NULL terminator
*/
   return result;
}

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

int alice_endline(char *string, int size)
{
    int counter = 0;
    while (counter < size)
    {
       if (string[counter] == '\n')
          return counter; 
       else
          counter++;
    };

    return 0;  /* newline not found */

}

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

int alice_length(char *s)
{
   char *ptr = s;
   int counter = 0;

   while ((*ptr <= 126) && ((*ptr >= 32) || (*ptr ==
9)))
   {
       ptr++;
       counter++;
   }

   if (*ptr == 0)
      return counter;
   else;
      return 0;

}

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

char *alice_reverse1(char* string, int size)
{
   char* result;
   int i, j;

   if ((result = malloc(size*sizeof(char))) == NULL)
   {
       printf("Out of memory!");
       return NULL;
   };

   for (i=0, j=(size-2); i < (size-1); i++, j--)
   {
       result[i] = string[j];

   };


   result[size-1] = '\0';
   return result;
}

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

char *alice_reverse2(char* string, int size)
{

   char *result, *rptr, *sptr;
   result = malloc(size*sizeof(char));

   rptr = result;
   sptr = string;

   sptr += size - 2;

   while (sptr >= string)
   {
       *rptr = *sptr;
       rptr++;
       sptr--;
   };

   rptr = '\0';
   return result;
}

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

P.S If anybody knows how to instruct yahoo NOT to add
its own newline characters to cut-and-pasted text,
please let me know, or would I be better off sending
example code as an attatchment?



=====
"the only way to learn how to be clever is to say stupid things" - anon

__________________________________
Do you Yahoo!?
Yahoo! Finance Tax Center - File online. File on time.
http://taxes.yahoo.com/filing.html


More information about the Programming mailing list