Developers Heaven Forum
News: Free Image Hosting:
http://image-host.developers-heaven.net
Share your images free!!!
 
*
Welcome, Guest. Please login or register.
Did you miss your activation email?
March 19, 2010, 08:18:57 PM


Login with username, password and session length


Pages: [1]   Go Down
  Print  
Author Topic: First steps ... via example programs in C++ and C ...  (Read 331 times)
0 Members and 1 Guest are viewing this topic.
David
Full Member
***
Offline Offline

Posts: 103

OS:
Windows XP
Browser:
Firefox 3.0.7


View Profile
« on: March 27, 2009, 09:18:56 PM »

This is a preface added for beginning students ... squeezed in ... at the front of these links ...

http://developers-heaven.net/forum/index.php/topic,127.0.html
http://developers-heaven.net/forum/index.php/topic,106.0.html

Here ... I hope to better present some simpler programs ... in a step-wise fashion ... the same order as many students seem to ask for solutions, (to their problems) ...

So here ... is a beginning type program ... (However ... the logic used here ... and some of the crash proofing and input validation tricks used here ... seem sadly often poorly demonstrated to new students ... if ever ...)

Please enjoy ... and profit too.

Shalom,
David
2009-03-27



The goal here  ... is to try to get the exact same output requested via the exact same input suggested ... Wink

(This is just ONE ... example way ... a solution to this problem might be coded. That is part of the perks in programming ... seeing NEW ways to code a solution.)

Code:
/*

Sample 1:
Enter two characters and an integer: $ * 3

$*$
*$*
$*$

Sample 2:
Enter two characters and an integer: / \ 6
/\/\/\
\/\/\/
/\/\/\
\/\/\/
/\/\/\
\/\/\/

*/

#include <iostream>
using namespace std;

int main()
{
    cout << "Enter two characters and an integer: " << flush;
    char c1, c2, tmp;
    int n;
    cin >> c1 >> c2 >> n;
    // If you wish to make a loop to ask for new input what problem(s) might you encounter?
    // ... and how could you resolve them?

    for( int i = 0; i < n; ++i )
    {
        for(int j = 0; j < n; ++j )
        {
            cout << c1;
            // don't forget ... the index's are 0,1 ... not 1,2 ...
            // if j is the last one ... and if j is 'odd' ... then
            if( j==n-1 && j%2==0 ) break; // skip this last 'odd' one
            else
            {
                cout << c2;
                ++j;
            }
        }
        
        // now print a new line ...
        cout << endl;
        
        // and swap c1 and c2 for the next line ...
        tmp = c1;
        c1 = c2;
        c2 = tmp;
    }

    cout << "\n\nPress 'Enter' to continue ... " << flush;
    cin.sync(); // flush cin stream  ...
    cin.get(); // now wait for enter key to be pressed ...
    return 0;
}

A first trick here is to swap the 2 output characters, with each other ...

(var1 will then hold the contents of var2  ... and var2 will then hold the contents of var1 ...
 Of course you WILL NEED to use a tempVar to hold one of the values ...
 BEFORE you overwrite that old value with a NEW value ...)

... i.e. swap before you proceed to output the next line.

Keep the idea of swapping ... in your bag of tricks.

The idea of nesting a loop within a loop is also a very common trick ... if you mess with the counters, in a for loop ... be careful and test well your output ... You might prefer to use while loops at first and manger your counter values yourself ... Then you (should) KNOW what value they have at ever step ...

The 3rd trick here ... is knowing how to stop the output for some particular discrete values ... like the first or last values output in a loop... or the last, if and only if it is an odd num ...or whatever imaginable condition someone, (like your Prof?), might dream up ... and so it might keep you ... from your proper sleep Wink
« Last Edit: January 25, 2010, 03:17:15 AM by David » Logged
David
Full Member
***
Offline Offline

Posts: 103

OS:
Windows XP
Browser:
Firefox 3.0.7


View Profile
« Reply #1 on: March 27, 2009, 10:33:40 PM »

An other common first step ... and problem faced ... is getting rid of unexpected ... (by beginners) ... and sometimes unwanted ... characters STILL left in the cin instream ...

THIS problem may NOT face you ... until you first try coding a loop ... where you ask repeatedly to get more data.

See if you can C the tricks used here to manage this sometimes BIG beginner problem ...

Code:
#include <iostream> // <iostream.h> is not accepted in modern compilers of C++ code
using namespace std; // namespaces are very important in modern C++

/*
    This is just a basic input which keeps asking for input of
    characters ... until the answer is 'n' or 'N'. If you enter
    any other characters, the output 'more' appears ...
    EXCESS char's in the input buffer ... are EATEN UP by the neat
    action of cin.sync() or by careful use of more cin.get()'s ...
    if your OLD compiler does not have the C++ standard cin.sync()
*/


int main()
{
    // note cin.get() returns an int value if you enter a char also
    // try it out and see what the ASCII values are for A..Z and a..z

    // Note: reply NEEDS this scope. Why? LOOK up 'scope'. DO yourself a favour.
    int reply;
    do
    {
        cout << "Continue ... (waits for 'n' or 'N' to be entered) : ";
        reply = cin.get();
        cin.sync(); // flush cin of '\n' and any other char's ...
        cout << "You entered " << (char)reply << " or " << reply << endl;
        
    }while( !(reply=='n' || reply=='n') ); // hint: 'reply' IS needed OUTSIDE
    
    cout << "You entered " << (char)reply << " or " << reply
         << "\nPress 'Enter' to continue ... " << flush;

    while( cin.get() != '\n' ) ; // ok here, to stop/pause for 'enter' here like this
    
    int c;
    do
    {
        cout << "Enter a char ... (waits for 'n' or 'N' to be entered) : ";
        reply = c = cin.get();
        while(c != '\n') c=cin.get(); // flush cin of '\n' and any other char's
        cout << "You entered " << (char)reply << " or " << reply << endl;

    }while( !(reply=='n' || reply=='n') ); // hint: 'reply' IS needed OUTSIDE

    cout << "You entered " << (char)c << " or " << c
         << "\nPress 'Enter' to continue ... " << flush;

    cin.get();

}


Now C this ... into C++ Wink

Code:
/* validating numeric entry in C and use of 'do( ... )while( more() );' loop */

#include <stdio.h>
#include <ctype.h> /* re. toupper */

int more() /* defaults to yes ... unless 'n' or 'N' are entered */
{
    int c, reply;
    printf("\nMore ... (y/n) ? ");
    reply = c = toupper( getchar() );
    while( c != '\n' ) c = getchar(); /* flush stdin ...*/
    return reply != 'N';
}

int main() /* testing more() ...*/
{
    int i, numGood;
    do
    {
        printf("Enter a positive integer : ");
        numGood = scanf("%d", &i );
        while( getchar() != '\n' ) ; /* flush stdin ... */
        if( numGood != 1 || i < 0 )
        {
            if( numGood != 1) puts("\nEntry error! INTEGERS only please ...");
            if( i < 0 ) puts("\nEntry error! POSITIVE integers only please ...");
            continue;
        }

        printf("Yeah ... you can read and type.  You entered %d\n", i);
        
    }while( more() );
    
    return 0;
}


You may have noticed ... that when coding using (older) C compilers ... all the variables used in a block {} are declared at the TOP of that block {}... C89 compilers will insist on this ... or they won't compile.  Note that many C++ compilers also compile C code ... so you may get away with not having a strict conformance to having all your variables first declared at the top of each block {}.

You may have noted, the preferred C++ style that goes along with the C++ encapsulation concept, i.e. to keep things together that are related. Using this C++ programming style... the programmer declares the variables just ahead of use, with just as much scope as needed, so that the person reading the program can easily see the type of variable being used ... and even more ... to limit the scope of the variables to all that is needed by the program.  So ... if you are using a C89 compiler for these C demo programs, and I may have reverted, unintentionally, to a little C++ style there, and thus that xxx.c program will NOT compile with your C compiler, please check for this Potential PROBLEM.
« Last Edit: March 14, 2010, 07:11:51 PM by David » Logged
David
Full Member
***
Offline Offline

Posts: 103

OS:
Windows XP
Browser:
Firefox 3.0.7


View Profile
« Reply #2 on: March 27, 2009, 11:55:26 PM »

Some fast steps ... into arrays of char's and int's and doubles ... in C ... pointing out, in the comments, some things to note ... so please run these programs ... and note ...

And again ... see if you can re-code these in C++ ... for some easy practice ...

NOTE: C strings are just 'null terminated' arrays of char's ... and arrays are just blocks of memory to hold (normally) adjacent data, one after the other, in equal chunks of memory, for each element ...  For example, a 'char' takes 1 byte ( 8 bits) ... and at present, 2008-2009, an 'int' is usually 4 bytes, i.e. 32 bits.  In a 32 bit addressing mode system, pointers, ( i.e. variables that hold addresses ), will use 32 bits of memory ... 4 bytes.

NOTE 2: If you want to jump now to see a C++ student array type problem, solved step by step, click on this next link now ...

http://developers-heaven.net/forum/index.php/topic,106.15.html

Code:
#include <stdio.h>

int main ()
{
    /* a NULL terminated array of characters, i.e. a 'C string' */
    char book[] = "It was a dark and stormy night."; /* compiler adds 0 at end */

    char test1[]= { 'a', 'b', 'c','\0'};/*NOTE: last '0' if want C string */

    char test2[4] ={'X','Y','Z'};/* NOTE: reserve a 4th spot for '0' */
    /* now ... */
    test2[3] =0; /* null terminate ... to convert array to C string */

    char letter = book[3]; /* 'w' = book[3] i.e. w is the 4th char in the string */

    /* an array of integers */
    int coin[] = {1, 2, 5, 10, 20, 50, 100, 200}; /* compiler COUNTS int's */

    /* an empty array to hold two int */
    int cost[2];

    /* set values ... */
    cost[0] = coin[2]; /*  5 = coin[2] ... i.e. the 3rd position coin ... */
    cost[1] = coin[4]; /* 20 = coin[4] ... i.e. the 5th position coin ... */

    printf("Item %i costs %3i cents.\n", 1, cost[0]);
    printf("Item %d costs %3d cents.\n", 2, cost[1]);

    printf("book = %s\n", book );
    printf("4th letter in book at index=3 is %c\n", letter);
    printf("5th letter in book at index=4 is %c\n", book[4]);
    printf("1st letter in book at index=0 is %c\n", book[0]);

    printf("Some test C strings 1:%s 2:%s ", test1, test2);

    getchar(); /* to hold window open until 'Enter' key pressed ... */
    return 0;
}


Passing (simple 1-D) arrays to functions ... (note: in C/C++ arrays are always automatically passed by reference)

Code:
#include <stdio.h>

/*
    Calling a function ... 'show' array ... via passing a simple 1-D array of 'int' ...
    Note: the C / C++ (compiler) automatically take/pass the address, so NO copy
    is made ... (but, a local copy of the ADDRESS is made ... that holds/points to the
    original object. Using the address (pointing to the array) ... we are working on the
    original array itself ... so any changes made to values in the array, inside a
    function ... are changes made to the array itself.
*/
void show( int a[], int num ) /* or ... // void show( int * a, int num ) */
{
    int i;
    for (i=0; i<num; ++i)
        printf("%d ", a[i]);
        
    puts( "" );

    a[0] = -1*a[0]; /* Note how we can flip / flop the values here ... each pass ...*/
    for (i=0; i<num; ++i)
        printf("%d ", *a++); /* same output as above ... */
        
  
}

int main()
{
    int myAry[] = {1,2,3,4,5};
    show( myAry, 5 );
    myAry[0] = -2*myAry[0];
    
    puts("\nOr ...");
    
    show( myAry, sizeof myAry / sizeof myAry[0] );

    printf("Press 'Enter' to continue ... ");
    getchar();
    return 0;
}


Lot's of things/tricks to note here ... jumping right into addressing ... (i.e. using pointers to hold the address of the start of blocks of new memory obtained by malloc or calloc or realloc in C ... and by new in C++)

Code:
/*
    C program to find ...  the maximum, the minimum and the average values of ...
    an array of numbers entered via the keyboard ... using a DYNAMIC ARRAY of doubles
*/

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

void getAryInfo(double* ary, int size, double* max, double* min, double* avg);

int main()
{
    double* ary; /* this is a pointer ... i.e. ary holds an address */
    int c, i, n;

    /* get variables to hold info ... note: values to be returned by 'ref' */
    double max, min, avg;

    /* get n ... */
    do
    {
        n = 0;
        printf( "Please enter the number of observations : " );
        scanf( "%d", &n );
        while( getchar() != '\n' ); /* flush stdin ... */
        if( n <= 0 ) printf("Please enter a number greater than 0 ...\n");
    }while( n <= 0 );
    
    /* now get a block of memory for the array of n doubles */
    ary = (double*) malloc(n * sizeof(double));
    if( ary == NULL )
    { fputs("Error: malloc failed to allocate memory.", stderr); exit(1); }

    /*  
        ary now holds the address of the start of memory
        just allocated to hold n 'doubles'
    */
    
    /* now ... get the numbers into the 'ary' array memory reserved above ... */
    for( i=0; i<n; ++i )
    {
        printf( "observation %-3d : ", i+1 );
        ary[i] = 0;
        scanf( "%lf", &ary[i] ); /* Note: 'lf' for correct input of doubles */
        while( getchar() != '\n' ); /* flush all chars in stdin stream */ ;
        if( ary[i] == 0 )
        {
            printf("Is this value %lf correct that you entered (y/n) ? :", ary[i]);
            c = getchar();
            if( !(c == 'y' || c =='Y') )
            {
                printf("Ok ... skipped ...\n");
                --i;
                while( c != '\n' ) c=getchar(); /* flush all chars in stdin stream */ ;
                continue;
            }
            while( c != '\n' ) c=getchar(); /* flush all chars in stdin stream */ ;
        }
    }

    /* show numbers in the array ... */
    printf( "\nYou entered ...\n\n" );
    for( i=0; i<n; ++i )
    {
        printf( "%-3d : ", i+1 );
        printf( "%g\n", ary[i] );
    }
        
    /* Note: ary below already holds an 'address' to the first 'double' in the array of doubles */
    getAryInfo( ary, n, &max, &min, &avg ); /* we pass 'addresses' to pointer variables */
    
    printf( "\nThe info you desired is ... \n\n" );
    printf( "Max: %g  Min: %g  Average: %g\n\n", max, min, avg );

    printf("Press 'Enter' to continue ... ");
    getchar();
    free( ary ); /* free the dynamic memory allocated for the array of n doubles */
    return 0;
}

/* Note .... We are catching 'addresses' .... */
/*  so inside ... we have to use the value at that address by using *var   */
void getAryInfo(double* ary, int size, double* max, double* min,  double* avg)
{
    double sum = *min = *max = ary[0]; /* use this as a 'opening' value .... */
    int i;
    for( i=1; i<size; ++i ) /* start at 1 since already used 0 above */
    {
        sum += ary[i]; /* sum = sum + ary[i] */
        if (ary[i] < *min) *min = ary[i]; /* update ... if applies */
        if (ary[i] > *max) *max = ary[i];
    }  
    /* when we reach ... we have max, min and sum ... So can find average */
    *avg = sum/size;
}


And here is a mini-tutorial on a common student problem, finding if a particular element exits in an array of elements ... here we are looking for a C++ string in an array of C++ strings and will return the index of that string, in the array, if it is found, ... otherwise ... -1 is returned

http://www.dreamincode.net/forums/showtopic99556.htm

A student presents (problematic) code like this:

Code:
int search_name(const string find_name[], const string in_name, const int size1)
{
  
    int index = 0, not_found = -1;

    while (in_name != find_name[index] && index <= size1)
        index++;

    if (in_name != find_name[index] && index > size1)
        return not_found;
    else
        return index;
  
}


A first fix suggested ... is this:

Code:
int search_name(const string find_name[], const string in_name, const int size1)
{
    for( int i=0; i<size1; ++i )
        if( in_name == find_name[i] )
            return i;
    return -1;
}


Do you recognize yet ... what is trying to be accomplished by this function ... ?

See if this following re-worked version makes it clearer to see what the function does ...?

Code:
// test if the C++ string 'name' is in the array of strings with 'ary_size' number of names
// return the index 'i' in the array, if found ... i is in the range 0..ary_size-1
// otherwise, return -1
int get_index(const string& name, const string name_ary[], const int ary_size )
{
    for( int i = 0; i < ary_size; ++i )
    {
        if( name == name_ary[i] )
        {
            return i; // found ... so return the index where it was found
        }
    }
    // else ... if reach here ... NOT found, so ...
    return -1;
}


Now see this ...

Re. some recommendations for student hand-ins ... for top marks:

* included appropriate comments with functions re. what is passed in and back ...
   and ... what the function does, if the function name is not self explanatory

* use brackets for each block of code in if(...){ ...;}else if(...){ ...;}else{...;}
  (Some schools insist on this ... others just insist on clarity of logic flow.)

* rather than passing a copy, by value, into a function, where appropriate,
  pass in by const reference, especially for large C++ obj's

* use as descriptive names as possible to help see the program logic flow
  and to self-document, as you go, what is happening there ...
« Last Edit: March 14, 2010, 07:23:15 PM by David » Logged
David
Full Member
***
Offline Offline

Posts: 103

OS:
Windows XP
Browser:
Firefox 3.0.8


View Profile
« Reply #3 on: April 19, 2009, 11:13:47 AM »

Ok ... here is an example step by step solution to a common student problem ... (See if you can re-do this C version into C++)


step 1: get a clear 'map' of the problem ... and then get a working shell compiled and running ok ...

Code:
/*
 
  http://en.wikipedia.org/wiki/Anagram

  A program to test whether two strings are anagrams (i.e. have the same
  characters, but occurring in a different order)

  Example Input/Output ...

    Enter string: Smartest
    Enter string: Mattress
    Anagram
    Enter string: dumbest
    Enter string: stumble
    Not anagram
    Enter string: William Shakespeare
    Enter string: I'll make a wise phrase
    Anagram


 *  Read the first string, then write a loop that uses an array of 26 int's
    to count how many times each letter has been seen.
    Read the second string, this time decrement each letter’s count in the
    int array.

    The strings are anagrams if every element in the int array is 0

 *  Ignore any characters that aren’t letters.
    Treat upper-case letters as the same as their lower-case equivalent.
    Help on this is given below.

  Functions:

    You are required to use the following functions.
    You design appropriate parameters and return types.
    You may add other functions, if they make your program simpler and clearer.

  * main()

  * initialize()
    Clears the contents of all of your char and int arrays
    before you read the first string.
    (Use the null character ‘\0‘ for char arrays.)

  * getString()
    Prompts for and reads a string from input.
    Call the standard library function gets() from <stdio.h> as you do this.
    Function prototype is:
  * void gets(char s[]);
    reads the next line from input into the strings,
    terminating the string with ‘\0’

  * setLetters()
    Loops over every character in the first string,
    and updates the count for that letter in the int array.

    Call the following standard library functions from <ctype.h> as you do this.
    Function prototypes are:

  * int isalpha(char c)
    returns non-zero (true) if character c is a lower- or upper-case letter

  * char tolower(char c)
    if character c is an upper-case letter, returns the lower-case letter;
    otherwise it returns c

    To convert a lower-case character in the range a..z to an index in the range
    0..25 use:
  * char ch;
    int index;
    . . .
    index = ch – ‘a’;

  * checkLetters()
    Loops over every character in the second string, and subtracts 1 from the
    count for that letter in the int array. Very similar to setLetters()

  * isZero()
    Loops over the int array. Returns TRUE if every element is 0, ELSE FALSE

  Required:

    Use the inputs given above when you hand-in your work, followed by a few
    other carefully chosen test cases that demonstrate your program is correct.
    Thoroughly test your program first, checking all kinds of inputs until you
    are certain that the program is correct. (Hint: put an infinite loop in
    main() to run your program many times. Use ctrl-c to break out of the loop.)

  Your program must look like the work of a professional computer programmer:
  * correct layout and indentation
  * every function must have a comment, plus comment anything that is not
    simple and clear
  * clear, meaningful variable and function names
  * #define symbolic constants where appropriate

*/

#include <stdio.h>
#include <ctype.h> /* re. tolower(someAtoZchar) */

int more() /*  defaults to 'yes' ... i.e. must enter 'n' or 'N' for 'No' */
{
    int c, reply;
    printf("\nMore ... y/n ? ");
    reply = c = tolower( getchar() );
    while( c != '\n' ) c = getchar(); /* flush stdin ... */
    return !(reply == 'n');
}


int main()
{
    do
    {
    }while( more() );
    return 0;
}


Step 2: add a function ... and re-compile until it works ...

Code:
/*
  Anagram program ...

  A program to test whether two strings are anagrams (i.e. have the same
  characters, but occurring in a different order)

  Example Input/Output ...

    Enter string: Smartest
    Enter string: Mattress
    Anagram
    Enter string: dumbest
    Enter string: stumble
    Not anagram
    Enter string: William Shakespeare
    Enter string: I'll make a wise phrase
    Anagram


 *  Read the first string, then write a loop that uses an array of 26 int's
    to count how many times each letter has been seen.
    Read the second string, this time decrement each letter’s count in the
    int array.

    The strings are anagrams if every element in the int array is 0

 *  Ignore any characters that aren’t letters.
    Treat upper-case letters as the same as their lower-case equivalent.
    Help on this is given below.

  Functions:

    You are required to use the following functions.
    You design appropriate parameters and return types.
    You may add other functions, if they make your program simpler and clearer.

  * main()

  * initialize()
    Clears the contents of all of your char and int arrays
    before you read the first string.
    (Use the null character ‘\0‘ for char arrays.)

*/

#include <stdio.h>
#include <ctype.h> /* re. tolower(someAtoZchar) */

#define MAX_LINE_LEN 1023 /* NOTE: input via 'gets' will OVERFLOW beyond this */
#define MAX_CODES 26 /* maximum unique codes to track and count */

/* returns '1' for 'Yes more' or '0' for 'No more' ... */
int more() /*  defaults to 'yes' ... i.e. must enter 'n' or 'N' for 'No' */
{
    int c, reply;
    printf("\nMore ... y/n ? ");
    reply = c = tolower( getchar() );
    while( c != '\n' ) c = getchar(); /* flush stdin ... */
    if(reply == 'n')
        return 0; /* No more ... */
    
    /* else ...*/
    return 1; /* Yes more ... */
}

/* recall, in C ... 'arrays are auto-matically passed by ref.' */
/* note: uses global values MAX_LINE_LEN and MAX_CODES */
void initialize(char a1[], char a2[], int a[])
{
    int i;
    for( i=0; i<=MAX_LINE_LEN; ++i )
        a1[i] = a2[2] = 0;
    for( i=0; i<MAX_CODES; ++i )
        a[i] = 0;
}


int main()
{
    char c_ary1[MAX_LINE_LEN+1];
    char c_ary2[MAX_LINE_LEN+1];
    int  i_ary[MAX_CODES];
    
    do
    {   /* initialize all array elements to 0 */
        initialize( c_ary1, c_ary2, i_ary );
    }while( more() );
    return 0;
}


Step 3: add ... compile ... fix ... compile and fix ... until ok

Code:
/*
  Anagram program ...

  A program to test whether two strings are anagrams (i.e. have the same
  characters, but occurring in a different order)

  Example Input/Output ...

    Enter string: Smartest
    Enter string: Mattress
    Anagram
    Enter string: dumbest
    Enter string: stumble
    Not anagram
    Enter string: William Shakespeare
    Enter string: I'll make a wise phrase
    Anagram


 *  Read the first string, then write a loop that uses an array of 26 int's
    to count how many times each letter has been seen.
    Read the second string, this time decrement each letter’s count in the
    int array.

    The strings are anagrams if every element in the int array is 0

 *  Ignore any characters that aren’t letters.
    Treat upper-case letters as the same as their lower-case equivalent.
    Help on this is given below.

  Functions:

    You are required to use the following functions.
    You design appropriate parameters and return types.
    You may add other functions, if they make your program simpler and clearer.

  * main()

  * initialize()
    Clears the contents of all of your char and int arrays
    before you read the first string.
    (Use the null character ‘\0‘ for char arrays.)

  * getString()
    Prompts for and reads a string from input.
    Call the standard library function gets() from <stdio.h> as you do this.
    Function prototype is:
  * void gets(char s[]);
    reads the next line from input into the strings,
    terminating the string with ‘\0’

*/

#include <stdio.h>
#include <ctype.h> /* re. tolower(someAtoZchar) */

#define MAX_LINE_LEN 1023 /* NOTE: input via 'gets' will OVERFLOW beyond this */
#define MAX_CODES 26 /* maximum unique codes to track and count */

/* returns '1' for 'Yes more' or '0' for 'No more' ... */
int more() /*  defaults to 'yes' ... i.e. must enter 'n' or 'N' for 'No' */
{
    int c, reply;
    printf("\nMore ... y/n ? ");
    reply = c = tolower( getchar() );
    while( c != '\n' ) c = getchar(); /* flush stdin ... */
    if(reply == 'n')
        return 0; /* No more ... */
    
    /* else ...*/
    return 1; /* Yes more ... */
}

/* recall, in C ... 'arrays are auto-matically passed by ref.' */
/* note: uses global values MAX_LINE_LEN and MAX_CODES */
void initialize(char a1[], char a2[], int a[])
{
    int i;
    for( i=0; i<=MAX_LINE_LEN; ++i )
        a1[i] = a2[2] = 0;
    for( i=0; i<MAX_CODES; ++i )
        a[i] = 0;
}

/* gets a whole line via stdin. Note: will OVERFLOW if more than MAX_LINE_LEN */
void get_line(char s[]) /* recall in C arrays 'auto-matically passed by ref' */
{
    printf("Enter string: ");
    gets( s );
}


int main()
{
    char c_ary1[MAX_LINE_LEN+1];
    char c_ary2[MAX_LINE_LEN+1];
    int  i_ary[MAX_CODES];
    
    do
    {   /* initialize all array elements to 0 */
        initialize( c_ary1, c_ary2, i_ary );
        get_line( c_ary1 );
        get_line( c_ary2 );
            
    }while( more() );
    return 0;
}


Step 4: add ... compile ... fix ... compile and fix ... until ok

Code:
/*
  Anagram program ...

  A program to test whether two strings are anagrams (i.e. have the same
  characters, but occurring in a different order)

  Example Input/Output ...

    Enter string: Smartest
    Enter string: Mattress
    Anagram
    Enter string: dumbest
    Enter string: stumble
    Not anagram
    Enter string: William Shakespeare
    Enter string: I'll make a wise phrase
    Anagram


 *  Read the first string, then write a loop that uses an array of 26 int's
    to count how many times each letter has been seen.
    Read the second string, this time decrement each letter’s count in the
    int array.

    The strings are anagrams if every element in the int array is 0

 *  Ignore any characters that aren’t letters.
    Treat upper-case letters as the same as their lower-case equivalent.
    Help on this is given below.

  Functions:

    You are required to use the following functions.
    You design appropriate parameters and return types.
    You may add other functions, if they make your program simpler and clearer.

  * main()

  * initialize()
    Clears the contents of all of your char and int arrays
    before you read the first string.
    (Use the null character ‘\0‘ for char arrays.)

  * getString()
    Prompts for and reads a string from input.
    Call the standard library function gets() from <stdio.h> as you do this.
    Function prototype is:
      * void gets(char s[]);
        reads the next line from input into the strings,
        terminating the string with ‘\0’

  * setLetters()
    Loops over every character in the first string,
    and updates the count for that letter in the int array.

    Call the following standard library functions from <ctype.h> as you do this.
    Function prototypes are:

      * int isalpha(char c)
        returns non-zero (true) if character c is a lower- or upper-case letter

      * char tolower(char c)
        if character c is an upper-case letter, returns the lower-case letter;
        otherwise it returns c

        To convert a lower-case character in the range a..z to an index in the range
        0..25 use:
      * char ch;
        int index;
        . . .
        index = ch – ‘a’;
*/

#include <stdio.h>
#include <string.h> /* re. strlen */
#include <ctype.h> /* re. tolower(someAtoZchar) */

#define MAX_LINE_LEN 1023 /* NOTE: input via 'gets' will OVERFLOW beyond this */
#define MAX_CODES 26 /* maximum unique codes to track and count */

/* returns '1' for 'Yes more' or '0' for 'No more' ... */
int more() /*  defaults to 'yes' ... i.e. must enter 'n' or 'N' for 'No' */
{
    int c, reply;
    printf("\nMore ... y/n ? ");
    reply = c = tolower( getchar() );
    while( c != '\n' ) c = getchar(); /* flush stdin ... */
    if(reply == 'n')
        return 0; /* No more ... */

    /* else ...*/
    return 1; /* Yes more ... */
}

/* recall, in C ... 'arrays are auto-matically passed by ref.' */
/* note: uses global values MAX_LINE_LEN and MAX_CODES */
void initialize( char a1[], char a2[], int a[] )
{
    int i;
    for( i=0; i<=MAX_LINE_LEN; ++i )
        a1[i] = a2[2] = 0;
    for( i=0; i<MAX_CODES; ++i )
        a[i] = 0;
}

/* gets a whole line via stdin. Note: will OVERFLOW if more than MAX_LINE_LEN */
void get_line( char s[] ) /* recall in C arrays 'auto-matically passed by ref' */
{
    printf("Enter string: ");
    gets( s );
}

/*
    Loops over every character in the first string,
    and updates the count for that letter in the int array.

    Call the following standard library functions from <ctype.h> as you do this.
    Function prototypes are:

      * int isalpha(char c)
        returns non-zero (true) if character c is a lower- or upper-case letter

      * char tolower(char c)
        if character c is an upper-case letter, returns the lower-case letter;
        otherwise it returns c

        To convert a lower-case character in the range a..z to an index in the range
        0..25 use:
      * char ch;
        int index;
        . . .
        index = ch – ‘a’;
*/
/* track only a..z letters in char array c, keep count of each in int array a */
void set_letters( char c[], int a[] )
{
    int i;
    for( i = 0; i<strlen( c ); ++i )
        if( isalpha( c[i] ) ) /* keep count of only a..z and A..Z char's */
            a[tolower(c[i]) - 'a'] ++ ; /* int array 'a' index range is 0..25 */
}


int main()
{
    char c_ary1[MAX_LINE_LEN+1];
    char c_ary2[MAX_LINE_LEN+1];
    int  i_ary[MAX_CODES];

    do
    {   /* initialize all array elements to 0 */
        initialize( c_ary1, c_ary2, i_ary );
        get_line( c_ary1 );
        get_line( c_ary2 );
        set_letters( c_ary1, i_ary );

    }while( more() );
    return 0;
}

Continued on the next page below ...
« Last Edit: January 25, 2010, 06:56:59 AM by David » Logged
David
Full Member
***
Offline Offline

Posts: 103

OS:
Windows XP
Browser:
Firefox 3.0.8


View Profile
« Reply #4 on: April 19, 2009, 11:18:19 AM »

Step 5: add ... compile ... fix ... compile and fix ... until ok ... and here is a potential final version ... (But NOTE the well known buffer overflow problem associated with C gets ... Google C gets problem for more info.)

Code:
/*
  Anagram program ...

  A program to test whether two strings are anagrams (i.e. have the same
  characters, but occurring in a different order)

  Example Input/Output ...

    Enter string: Smartest
    Enter string: Mattress
    Anagram
    Enter string: dumbest
    Enter string: stumble
    Not anagram
    Enter string: William Shakespeare
    Enter string: I'll make a wise phrase
    Anagram


 *  Read the first string, then write a loop that uses an array of 26 int's
    to count how many times each letter has been seen.
    Read the second string, this time decrement each letter’s count in the
    int array.

    The strings are anagrams if every element in the int array is 0

 *  Ignore any characters that aren’t letters.
    Treat upper-case letters as the same as their lower-case equivalent.
    Help on this is given below.

  Functions:

    You are required to use the following functions.
    You design appropriate parameters and return types.
    You may add other functions, if they make your program simpler and clearer.

  * main()

  * initialize()
    Clears the contents of all of your char and int arrays
    before you read the first string.
    (Use the null character ‘\0‘ for char arrays.)

  * getString()
    Prompts for and reads a string from input.
    Call the standard library function gets() from <stdio.h> as you do this.
    Function prototype is:
      * void gets(char s[]);
        reads the next line from input into the strings,
        terminating the string with ‘\0’

  * setLetters()
    Loops over every character in the first string,
    and updates the count for that letter in the int array.

    Call the following standard library functions from <ctype.h> as you do this.
    Function prototypes are:

      * int isalpha(char c)
        returns non-zero (true) if character c is a lower- or upper-case letter

      * char tolower(char c)
        if character c is an upper-case letter, returns the lower-case letter;
        otherwise it returns c

        To convert a lower-case character in the range a..z to an index in the range
        0..25 use:
      * char ch;
        int index;
        . . .
        index = ch – ‘a’;

  * checkLetters()
    Loops over every character in the second string, and subtracts 1 from the
    count for that letter in the int array. Very similar to setLetters()

  * isZero()
    Loops over the int array. Returns TRUE if every element is 0, ELSE FALSE

  Required:

    Use the inputs given above when you hand-in your work, followed by a few
    other carefully chosen test cases that demonstrate your program is correct.
    Thoroughly test your program first, checking all kinds of inputs until you
    are certain that the program is correct. (Hint: put an infinite loop in
    main() to run your program many times. Use ctrl-c to break out of the loop.)

  Your program must look like the work of a professional computer programmer:
  * correct layout and indentation
  * every function must have a comment, plus comment anything that is not
    simple and clear
  * clear, meaningful variable and function names
  * #define symbolic constants where appropriate

*/

#include <stdio.h>
#include <string.h> /* re. strlen */
#include <ctype.h> /* re. tolower(someAtoZchar) */

#define MAX_LINE_LEN 1023 /* NOTE: input via 'gets' will OVERFLOW beyond this */
#define MAX_CODES 26 /* maximum unique codes to track and count */

/* returns '1' for 'Yes more' or '0' for 'No more' ... */
int more() /*  defaults to 'yes' ... i.e. must enter 'n' or 'N' for 'No' */
{
    int c, reply;
    printf("\nMore ... y/n ? ");
    reply = c = tolower( getchar() );
    while( c != '\n' ) c = getchar(); /* flush stdin ... */
    if(reply == 'n')
        return 0; /* No more ... */

    /* else ...*/
    return 1; /* Yes more ... */
}

/* recall, in C ... 'arrays are auto-matically passed by ref.' */
/* note: uses global values MAX_LINE_LEN and MAX_CODES */
void initialize( char a1[], char a2[], int a[] )
{
    int i;
    for( i=0; i<=MAX_LINE_LEN; ++i )
        a1[i] = a2[2] = 0;
    for( i=0; i<MAX_CODES; ++i )
        a[i] = 0;
}

/* gets a whole line via stdin. Note: will OVERFLOW if more than MAX_LINE_LEN */
void get_line( char s[] ) /* recall in C arrays 'auto-matically passed by ref' */
{
    printf("Enter string: ");
    gets( s );
}

/* track only a..z letters in char array c, keep count of each in int array a */
void set_letters( char c[], int a[] )
{
    int i;
    for( i = 0; i<strlen( c ); ++i )
        if( isalpha( c[i] ) ) /* keep count of only a..z and A..Z char's */
            a[tolower(c[i]) - 'a'] ++ ; /* int array 'a' index range is 0..25 */
}

/*
    Loops over every character in the second string, and subtracts 1 from the
    count for that letter in the int array. NOTE: VERY similar to setLetters()
*/
void check_letters( char c[], int a[] )
{
    int i;
    for( i = 0; i<strlen( c ); ++i )
        if( isalpha( c[i] ) ) /* keep count of only a..z and A..Z char's */
            a[tolower(c[i]) - 'a'] -- ; /* int array 'a' index range is 0..25 */
}


/* Loops over the int array. Returns TRUE if every element is 0, ELSE FALSE */
int is_zero( int a[] )
{
    int i;
    for( i = 0; i<MAX_CODES; ++i )
        if( a[i] ) /* if value in a[i] is not zero ... then return false */
            return 0;
    /* else ...*/
    return 1; /* i.e true */
}


int main()
{
    char c_ary1[MAX_LINE_LEN+1];
    char c_ary2[MAX_LINE_LEN+1];
    int  i_ary[MAX_CODES];

    do
    {
        initialize( c_ary1, c_ary2, i_ary );/* initialize all array elements to 0 */
        get_line( c_ary1 );
        get_line( c_ary2 );
        set_letters( c_ary1, i_ary );
        check_letters( c_ary2, i_ary );
        printf( "%s", is_zero( i_ary ) ? "Anagram" : "Not anagram" );

    }while( more() );
    return 0;
}


Step 6: BONUS version ... that does NOT use the well known and dangerous C gets with a buffer OVERFLOW problem

Code:
/*
  Anagram program ...

  A program to test whether two strings are anagrams (i.e. have the same
  characters, but occurring in a different order)

  Example Input/Output ...

    Enter string: Smartest
    Enter string: Mattress
    Anagram
    Enter string: dumbest
    Enter string: stumble
    Not anagram
    Enter string: William Shakespeare
    Enter string: I'll make a wise phrase
    Anagram


 *  Read the first string, then write a loop that uses an array of 26 int's
    to count how many times each letter has been seen.
    Read the second string, this time decrement each letter’s count in the
    int array.

    The strings are anagrams if every element in the int array is 0

 *  Ignore any characters that aren’t letters.
    Treat upper-case letters as the same as their lower-case equivalent.
    Help on this is given below.

  Functions:

    You are required to use the following functions.
    You design appropriate parameters and return types.
    You may add other functions, if they make your program simpler and clearer.

  * main()

  * initialize()
    Clears the contents of all of your char and int arrays
    before you read the first string.
    (Use the null character ‘\0‘ for char arrays.)

  * getString()
    Prompts for and reads a string from input.
    NOTE: the standard library gets() from <stdio.h> NOT used since may OVERFLOW
          replaced here with a call to my C safe char* s = c_safe_getline();

  * setLetters()
    Loops over every character in the first string,
    and updates the count for that letter in the int array.

    Call the following standard library functions from <ctype.h> as you do this.
    Function prototypes are:
        returns non-zero (true) if character c is a lower- or upper-case letter

      * int isalpha(char c)

      * char tolower(char c)
        if character c is an upper-case letter, returns the lower-case letter;
        otherwise it returns c

        To convert a lower-case character in the range a..z to an index in the range
        0..25 use:
      * char ch;
        int index;
        . . .
        index = ch – ‘a’;

  * checkLetters()
    Loops over every character in the second string, and subtracts 1 from the
    count for that letter in the int array. Very similar to setLetters()

  * isZero()
    Loops over the int array. Returns TRUE if every element is 0, ELSE FALSE

  Required:

    Use the inputs given above when you hand-in your work, followed by a few
    other carefully chosen test cases that demonstrate your program is correct.
    Thoroughly test your program first, checking all kinds of inputs until you
    are certain that the program is correct. (Hint: put an infinite loop in
    main() to run your program many times. Use ctrl-c to break out of the loop.)

  Your program must look like the work of a professional computer programmer:
  * correct layout and indentation
  * every function must have a comment, plus comment anything that is not
    simple and clear
  * clear, meaningful variable and function names
  * #define symbolic constants where appropriate

*/

#include <stdio.h>
#include <stdlib.h> /* re. calloc, realloc */
#include <string.h> /* re. strlen */
#include <ctype.h> /* re. tolower(someAtoZchar) */

#define MAX_CODES 26 /* maximum unique codes to track and count */

/* returns '1' for 'Yes more' or '0' for 'No more' ... */
int more() /*  defaults to 'yes' ... i.e. must enter 'n' or 'N' for 'No' */
{
    int c, reply;
    printf("\nMore ... y/n ? ");
    reply = c = tolower( getchar() );
    while( c != '\n' ) c = getchar(); /* flush stdin ... */
    if(reply == 'n')
        return 0; /* No more ... */

    /* else ...*/
    return 1; /* Yes more ... */
}

/* recall, in C ... 'arrays are auto-matically passed by ref.' */
/* note: uses global value MAX_CODES */
void initialize( int a[] )
{
    int i;
    for( i=0; i<MAX_CODES; ++i )
        a[i] = 0;
}

/* safe C line input from keyboard ... SAFE for ANY line LENGTH */
/* Note: you may want to/need to update the following to handle the case of memory allocation failure*/
char* c_safe_getline()
{
    int chunk_len = 256;
    int buf_len = chunk_len;
    char* buffer = (char*) calloc( buf_len, sizeof(char) );
    int len = 0, c;

    /* eats up WHOLE line ... including '\n' */
    while( (c = getchar()) != '\n' )
    {
        if( len == buf_len-1 )
        {
            buf_len += chunk_len;
            buffer = (char*) realloc( buffer, buf_len );
        }
        buffer[len++] = c;
    }

    buffer[len] = 0; /* confirm NULL terminated ... */
    return (char*) realloc( buffer, len+1 );
}

char* get_line( char prompt[] )
{
    printf( prompt );
    return c_safe_getline();
}

/* track only a..z letters in char array c, keep count of each in int array a */
void set_letters( char c[], int a[] )
{
    int i;
    for( i = 0; i<strlen( c ); ++i )
        if( isalpha( c[i] ) ) /* keep count of only a..z and A..Z char's */
            a[tolower(c[i]) - 'a'] ++ ; /* int array 'a' index range is 0..25 */
}

/*
    Loops over every character in the second string, and subtracts 1 from the
    count for that letter in the int array. NOTE: VERY similar to setLetters()
*/
void check_letters( char c[], int a[] )
{
    int i;
    for( i = 0; i<strlen( c ); ++i )
        if( isalpha( c[i] ) ) /* keep count of only a..z and A..Z char's */
            a[tolower(c[i]) - 'a'] -- ; /* int array 'a' index range is 0..25 */
}


/* Loops over the int array. Returns TRUE if every element is 0, ELSE FALSE */
int is_zero( int a[] )
{
    int i;
    for( i = 0; i<MAX_CODES; ++i )
        if( a[i] ) /* if value in a[i] is not zero ... then return false */
            return 0;
    /* else ...*/
    return 1; /* i.e true */
}


int main()
{
    char* c_ary1;
    char* c_ary2;
    int  i_ary[MAX_CODES];

    do
    {
        initialize( i_ary ); /* initialize all counts to 0 */
        c_ary1 = get_line("Enter 1st string: ");
        c_ary2 = get_line("Enter 2nd string: ");
        set_letters( c_ary1, i_ary );
        check_letters( c_ary2, i_ary );
        printf( "%s", is_zero( i_ary ) ? "Anagram" : "Not anagram" );
        free( c_ary1 );
        free( c_ary2 );

    }while( more() );
    return 0;
}
« Last Edit: March 14, 2010, 06:53:34 AM by David » Logged
David
Full Member
***
Offline Offline

Posts: 103

OS:
unknown
Browser:
unknown


View Profile
« Reply #5 on: November 23, 2009, 06:02:39 PM »

Update:

You also might like to see this new link at ...

http://sites.google.com/site/andeveryeyeshallseehim/

Shalom.

David
« Last Edit: January 25, 2010, 04:06:38 AM by David » Logged
Pages: [1]   Go Up
  Print  
 
Jump to:  

Google
   
Powered by MySQL Powered by PHP Powered by SMF 1.1.4 | SMF © 2006-2007, Simple Machines LLC

Copyright © Developers-Heaven.net 2008. All rights reserved.
Valid XHTML 1.0! Valid CSS! Dilber MC Theme by HarzeM