[Techtalk] Re: [Newchix] learning c

Devdas Bhagat devdas at dvb.homelinux.org
Fri Mar 26 03:02:23 EST 2004


On 25/03/04 11:53 -0800, Alice Moomlyn wrote:
<snip bit about being a C newbie>
This should go to techtalk. Not newchix. Followups set.

> 1. if I've written code which will be really
> inefficient.
> 
> 2. if I've done something the hard way when there was
> a library function which I could have used.`
> 
> 3. if my code is ugly, unreadable, badly commented or
> generally lacking in style.
> 
> 4. if there are bugs that I didn't spot.
> 
> 
> Here's my first program.
> 
> It reads a string from input that may be of *any*
> length (less than 20470 characters).
> 
> Not very exciting, I know, but its the kind of thing I
> miss from python :^P
> 
> P.S I'm using yahoo mail, so if its really badly
> formatted, that'd be why. Sorry. 8^<
> ..................................................
/* 
 * C style comments follow
 */
/*
 * Handling strings in C is hard to get correct. The edge cases are the
 * worst, and failure to check those usually leads to those nasty buffer
 * overflow bugs.
 */
> 
> #include <stdio.h>
> #include <string.h> 
> #include <stdlib.h>

/* 
 * C programmers generally do not use a boolean type.
 * If you really want a boolean, use enum instead.
 */
/* 
 * #defined terms are generally CAPITALIZED. This is not necessary, but
 * is a convention for simple constants. Macros which replace functions
 * are almost always lowercase.
 */
> #define bool int
> #define True 1
> #define False 0
> 
/*
 * Comments precede the function. If I am reading code, I want to know
 * what that code is supposed to do before I start looking at it.
 */
> char *alice_getstring();
> /* returns a pointer to a string read from standard input,
>    of maximum length 20470 characters. */
> 
> bool alice_endline(char *string, int size);
> /* searches through a string for the newline character,
>    returns the number of characters searched if found,
>    or False if not found. */
> 
/*
 * int main(void) just to be explicit in your code
 */
> int main()
> {
>    fputs("Enter a string of any length: ", stdout);
/*
 * You need to declare variables before invoking any code. Also, you
 * have not allocated any memory for s. Have you even compiled and run
 * this program?
 */
>    char *s = alice_getstring();
>    fputs("\nThis is the string you entered:", stdout);
>    fputs(s, stdout);
> 
>    return 0;
> }
> 
> 
> char *alice_getstring()
> {
>    int buffsize = 10;
>    int maxbuffers = 10;
>    int totalbuff = 0;
> 
>    char *p[maxbuffers]; /* an array of pointers to character strings */
> 
/*
 * Shouldn't this comment be before the function declaration?
 */
>    /* 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 'maxbuffers'   */
>       
>    int endline; /* stores number of position actually used 
>                    to store input in the final buffer */
> 
>    int counter = 0;
>    bool finished = False;
>    while (finished == False)
>    {
>       p[counter] = malloc(buffsize*sizeof(char)); 
/*
 * What happens if malloc() fails?
 */
>       p[counter] = fgets(p[counter], buffsize*sizeof(char), stdin); 
/*
 * Whitespace around those brackets. Whitespace is good.
 */
/*
 * What happens if I give a larger input to this function than your
 * arbitrary size limit? Should you not check that buffsize does not
 * exceed some fixed limit and error out?
 */
>       endline = (alice_endline(p[counter],buffsize));
>       if (endline == False) /* still more input */
>       {
>          totalbuff += buffsize;
>          buffsize *= 2;
>          counter++;
>       }
>       else /* end of input */
>       {
>          totalbuff += endline; /* the last buffer will probably not be full */
/*
 * Are you sure your buffer space is not really and truly full? Probably
 * is not good enough.
 */
>          finished = True;
>       }
>    };
> 
/*
 * Why would you not use realloc here? That is exactly why it exists.
 */
>    /* combine all the buffers into one */
>   
>    char *result = malloc(totalbuff*sizeof(char));
> 
>    buffsize = 10;
>    result = strncpy(result, p[0], buffsize);
> 
>    if (counter == 0)
>       return result;
> 
/*
 * This is not C++ or Python. Variables have to be declared at the
 * beginning of the function declaration.
 */
>    int loopvar = 1;
>    while (loopvar < counter)
>    {
>        buffsize *= 2;
>        result = strncat(result, p[loopvar], buffsize);
>        free(p[loopvar]);
>        loopvar++;
>    }
>    result = strncat(result, p[loopvar], endline);
>   
>    return result;
> }
> 
> bool alice_endline(char *string, int size)
> {
>     int counter = 0;
>     while (counter < size)
>     {
>        if (string[counter] == '\n')
>           return (counter + 1);
>        else
>           counter++;
>     };
> 
>     return False;  /* newline not found */
>    
> }

Devdas Bhagat


More information about the Techtalk mailing list