Re: Stupid Newbie Needs Help

From: John Bode (john_bode_at_my-deja.com)
Date: 11/18/03


Date: 18 Nov 2003 12:04:17 -0800


"Rich Strang" <riky_rang@hotmail.com> wrote in message news:<99cub.3137$Ea6.28431414@news-text.cableinet.net>...
> Hi group I am just starting out in C so please go easy on me :)

I'll try. You have a few style issues that I'm going to harp on, but
be aware I rant because I just want to make you a better programmer
(i.e., more like me ;-).

>
> I have started to write a small command line interpreter, I have got the
> program to break down the commands successfully until I introduce a loop
> into the main function. Without the loop the program works fine with the
> loop the cout doesn't seem to work,

Describe exactly what you mean by "doesn't seem to work". FWIW, I
compiled and ran the program below (modulo swapping out the C++ bits
for C) and it worked, mostly (as in, it spat back out what I typed in,
plus a lot of garbage that I didn't enter). You really want to work
with 0-terminated strings, that way you can take advantage of C's
string processing routines.

> I know I am probably being real stupid
> but I would really appreciate some help. Please find the code below:
>
> Thanks Guys
>
> Rich
>
> // **** Rich's Command Line Interpreter ****
> // Author: Rich Strang
> // Date: 08/10/03
>
> #include <stdio.h>
> #include <iostream.h>
> #include <ctype.h>
>
> //Set Global
> const int iDim1Size=10;
> const int iDim2Size=80;
>

First style rant: names should be descriptive, meaningful, and
describe usage, *not type*. What, exactly, do iDim1Size and iDim2Size
represent other than array dimensions? What are they to be used for?
It's somewhat clear from the context below that iDim2Size represents
the maximum line length, but I'm not sure how you intend to use
iDim1Size. From the code below it looks like you intend cTokens to
hold up to 10 tokens, where each token may be up to 80 characters
long; is that what you mean? IOW, each input line may contain at most
10 tokens. If that's the case, then maybe iDim1Size should be named
maxTokens or something like that. And instead of iDim2Size, use a
name like lineLength or maxChars or something like that. The name
should give a clue of how the variable/constant/function/macro is
supposed to be used (in a high-level, real-world sense, not in terms
of the specific implementation). I generally frown on Hungarian
notation, at least as it's commonly used. Encoding the type in the
variable name seems like a good idea at first, but what if the base
type of the variable ever has to change?

>
> //Function Prototypes:
> int GetLine(char[]);
> int ParseLine(char[], char[][iDim2Size], int);
> int PrintTokens(char[][iDim2Size]);
>
> int main(void)
> {
> char cInput[iDim2Size];
> int iInputSize=0;
> char cTokens[iDim1Size][iDim2Size];
> int iExit=0;
>
> while(iExit==0)
> {
> // Prints prompt to screen
> printf("$ ");
    
    fflush (stdout); /* since you aren't printing a newline */
                     /* you may need to force a flush of the */
                     /* line buffer to standard output */
>
> // Retrieve user input
> iInputSize = GetLine(cInput);
>
> if(cInput[0] != 'e' && cInput[1] != 'x' && cInput[2] != 'i' && cInput[3]
> != 't' )

You might want to reverse the sense of this test (actually, you might
want to work with 0-terminated strings so you can use C's string
library functions like strcmp(), but that's a subject for another
day). C does what's called "short-circuit evaluation" of Boolean
expressions like the above. If you have an expression like "a && b &&
c && d" and a evaluates to false, then the whole expression evaluates
to false regardless of b, c, and d, so they aren't evaluated at all.
So if the first character on your input line is 'e', the above test
will fail, and it won't bother testing against cInput[1], cInput[2],
or cInput[3]. So if you type "evaluate", the loop will still exit.

It might be better to rework this as

    if (cInput[0] == 'e' && cInput[1] == 'x' && cInput[2] == 'i' &&
cInput[3] == 't')
    {
        iExit = 1;
    }
    else
    {
        /* parse and print tokens */
    }

> {
> // Split user input into tokens
> ParseLine(cInput, cTokens, iInputSize);
>
> //Print tokens to screen
> PrintTokens(cTokens);
> }
> else
> {
> iExit=1;
> }
> }
>
> return 0;
> }
>
> //GetLine Function
> int GetLine(char cInput[])
> {
> int iInputSize=0;
> char ch;
>
> for( iInputSize = 0; (iInputSize < 80) && ((ch = getchar()) != EOF) && (ch
> != '\n'); iInputSize++ )
> {
> cInput[iInputSize] = (char)ch;
> }
> return iInputSize;
> }
>
> //ParseLine Function
> int ParseLine(char cInput[], char cTokens[][iDim2Size], int iInputSize)
> {
> int iIndex=0;
> int iA1=0;
> int iA2=0;
>
> for( iIndex = 0; (iIndex < iInputSize); iIndex++ )
> {
> if(cInput[iIndex] != ' ' && cInput[iIndex] != '\t')
> {
> cTokens[iA1][iA2] = cInput[iIndex];
> iA2++;
> }
> else
> {
> iA1++;
> iA2=0;
> }
> }
> return 0;
> }
>
> //Print Tokens Function
> int PrintTokens(char cTokens[][iDim2Size])
> {
> int iIndex1=0;
> int iIndex2=0;
>
> for( iIndex1 = 0; (iIndex1 < iDim1Size); iIndex1++ )
> {
> for( iIndex2 = 0; (iIndex2 < iDim2Size); iIndex2++ )
> {
> if ( isalpha(cTokens[iIndex1][iIndex2]) ||
> isdigit(cTokens[iIndex1][iIndex2]))
> {
> cout << cTokens[iIndex1][iIndex2];

      putchar (cTokens[iIndex1][iIndex2]);

> }
> }
> cout << "\n";

   putchar ('\n');
   fflush (stdout);

> }
>
> return 0;
> }



Relevant Pages

  • Re: C# coding guidelines: use "this." or not when referring to member fields/properties within the
    ... Alphabetic for strings isn't quite so ... One example of where people go wrong is when they want to optimise loop ... implementation so that each iteration takes 10% less time will only ...
    (microsoft.public.dotnet.languages.csharp)
  • RE: Error handling in a Do Loop
    ... I made the changes you suggested to my strings - blanking them correctly now. ... have any further suggestion or pointers, ... > When loop is able to ping a computer and able to pull the information, ... when the loop does not ping a computer/unable to ...
    (microsoft.public.windows.server.scripting)
  • Re: timeit module: am I missing something obvious?
    ... Why am I passing strings around when functions are ... best of 3 trials: 0.792 usec per loop ... quickly choosing number of iterations. ... - The result from the final pass through the convergence loop ...
    (comp.lang.python)
  • Re: looking for implementation of strtok
    ... contains a ',' character. ... we enter the ugly loop that simply implements strspn: ... loop sets spanp to delim, then loops while seting sc (the "span ... If there are no more tokens, we set *lastp to NULL (this is, I ...
    (comp.lang.c)
  • Re: Please, please, please Help !!!
    ... I have a set of 100,000 ascii strings, up to 255 chars each. ... Each string has 1 or more words (tokens), ... if I have strings in: mary poppins, brad pitt, yygr ...
    (microsoft.public.sqlserver.xml)