Author Topic: First steps ... via example programs in C++ and C ...  (Read 17939 times)

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
First steps ... via example programs in C++ and C ...
« on: March 27, 2009, 09:18:56 PM »



The following is a preface added for beginning students ... squeezed in, for beginners to see before they tackle these next 2 links:


Here ... with these following example programs, 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) ...


But first, you may want to see this next link for some very first-steps example C and C++ programs side by side:



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 ... ;)

(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: [Select]
/*

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

Run 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 ;)
« Last Edit: April 17, 2012, 05:14:12 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: First steps ... via example programs in C++ and C
« 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: [Select]
#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++ ;)

Code: [Select]
/* 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 »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: First steps ... via example programs in C++ and C
« 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: [Select]
#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' ...

i.e. the address to the 1st element is passed in ... so that the elements stored in the array 'a' ... can be individually accessed like this:

a[0], a[1], ... a[n-1] 

OR ... like this:

*a, *(a+1), *(a+2), ... *(a+n-1). 

BUT ... unlike vectors, or NULL terminated C strings, i.e. an array of char's with a terminal '\0' char, you must ALSO pass in the SIZE 'n' of the array.

Code: [Select]
#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]);
        
    putchar( '\n' );

    a[0] = -a[0]; /* Note how we can flip / flop any 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: [Select]
/*
    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: [Select]
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: [Select]
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: [Select]
// 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: September 14, 2010, 09:35:47 PM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: First steps ... via example programs in C++ and C
« 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: [Select]
/*
 
  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: [Select]
/*
  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: [Select]
/*
  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: [Select]
/*
  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 »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: First steps ... via example programs in C++ and C
« 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: [Select]
/*
  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: [Select]
/*
  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.  See *** below */
char* c_safe_getline()
{
    int buf_len = 256;
    char* buffer = (char*) malloc( buf_len );
    int len = 0, c;

    /* eats up WHOLE line ... including '\n' */
    while( ( c = getchar() ) != '\n' )
    {
        if( len == buf_len-1 ) /* skip over this block while len <= buf_len-2 */
        {
            buf_len += buf_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;
}


***click on this next link for safe readLine ...
http://developers-heaven.net/forum/index.php/topic,106.msg564.html#msg564
« Last Edit: September 14, 2010, 04:48:54 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: First steps ... via example programs in C++ and C ...
« 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 »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: First steps ... via example programs in C++ and C ...
« Reply #6 on: April 17, 2010, 06:46:00 AM »
Here is an other common student problem ... solved easily, using C++ stringstream ...

Get some stats on a line of text ...

Code: [Select]
// This program asks the user to enter a sentence
// terminated by a period.  Then the program prints
// out the number of words in the sentence and the
// average number of letters in each word ...
// and other stat's ...

// via using stringstream ...

#include <iostream>
#include <sstream>
#include <string>
#include <cctype> // re. tolower( ... )

using namespace std;

int num_vowels( const string& s )
{
    int num = 0;
    for(unsigned i=0; i < s.length(); ++i )
    {
        char c = tolower( s[i] );
        if( c=='a' || c=='e' || c=='i' || c=='o' || c=='u' )
            ++num;
    }
    return num;
}

bool isPunctuation( char c )
{
    if( c==',' || c==';' || c==':' || c=='.' || c=='?' || c=='!' )
        return true;
    // else
    return false;
}

int main()
{
    string line, word;
    int num_words = 0, letters = 0, vowels = 0, puncts = 0;

    cout << "On the next line, enter a sentence terminated by a period:" << endl;
    getline( cin, line );
    istringstream iss( line );
    
    while( iss >> word )
    {
        ++num_words;
        letters += word.length();
        if( isPunctuation( word[word.length()-1] ) )
        {
            --letters;
            ++puncts;
        }
        vowels += num_vowels( word );
    }
    
    cout << "The total number of words in the sentence  : "
         << num_words << endl
         << "and the total number of characters used    : "
         << line.length() << endl
         << "and the total number of letters used was   : "
         << letters << endl
         << "and the total number of vowels used was    : "
         << vowels << endl
         << "and the total number of consonants  was    : "
         << letters - vowels << endl
         << "and the total number of puntuation marks   : "
         << puncts << endl
         << "and the average number of letters per word : "
         << double(letters) / num_words << endl;


    cout << "\nPress 'Enter' to continue ... " << flush;
    cin.get();
}
« Last Edit: April 19, 2010, 09:45:39 PM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: First steps ... via example programs in C++ and C ...
« Reply #7 on: April 17, 2010, 08:28:15 PM »
And now .. an example of getting some stats, again using stringstream, on a text file ...
(see example text file below)

Code: [Select]
// This program asks the user to enter a file name
// of some 'file_name.txt' file to be analyzed ...

// Then the program prints out the number of paragraphs,
// sentences and words in that text ... and the
// average number of letters in each word ...
// and other stat's ...

// via using stringstream ...

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <cctype> // re. tolower( ... )

using namespace std;

int numVowels( const string& s )
{
    int num = 0;
    for(unsigned i=0; i < s.length(); ++i )
    {
        char c = tolower( s[i] );
        if( c=='a' || c=='e' || c=='i' || c=='o' || c=='u' )
            ++num;
    }
    return num;
}

int numPunctuations( const string& s )
{
    int num = 0;
    for( unsigned i=0; i<s.length(); ++i )
    {
        char c = s[i];
        if( c==',' || c==';' || c==':' || c=='[' || c==']' ||
            c=='(' || c==')' || c=='-' || c=='\'')
            ++num;
    }
    return num;
}

bool hasTerminalPunc( const string& s )
{
    for( unsigned i=0; i<s.length(); ++i )
    {
        if( s[i]=='.' || s[i]=='?' ||  s[i]=='!' )
            return true;
    }
    return false;
}



int main()
{
    string fname;
    cout << "Enter the file name of the text file to be processed: " << flush;
    getline( cin, fname );
    ifstream fin( fname.c_str() ); // open that file for reading ...
    
    string reply;
    cout << "Do you want to see that file on the console screen (y/n) ? " << flush;
    getline( cin, reply );
    bool show = (reply!="n" && reply!="N");

    string line, word;
    int numParas=1, numSents=0, numWords=0,
        numChars=0, letters=0, vowels=0, puncts=0;
    
    if( show ) cout << endl << endl;
    
    while( getline( fin, line ) )
    {
        numChars += line.length();      // characters

        istringstream iss(line);
        while( iss >> word )            // words
        {
            if( show) cout << word << " ";
            ++numWords;

            vowels += numVowels( word );// vowels
            
            int wordLen = word.length();
            letters += wordLen;        // letters
            
            int numPuncts = numPunctuations( word );
            if( numPuncts )
            {
                letters -= numPuncts;
                puncts += numPuncts;    // punctuation marks
            }
            
            if( hasTerminalPunc( word ) )
            {
                --letters;
                ++puncts;
                ++numSents;             // sentences
            }
        }
        // assume JUST ONE blank line at the end of each paragraph ...
        if( !fin.eof() )
        {
            if( line.length() == 0 )
            {
                if( show ) cout << endl << endl;
                ++numParas;             // paragraphs
            }
        }
    }
    
    cout << "\n\nThe total number of paragraphs in the text: "
         << numParas << endl
         << "The total number of sentences in the text : "
         << numSents << endl
         << "The total number of words in the text was : "
         << numWords << endl
         << "and the total number of characters used   : "
         << numChars << endl
         << "and the total number of letters used was  : "
         << letters << endl
         << "and the total number of vowels used was   : "
         << vowels << endl
         << "and the total number of consonants  was   : "
         << letters - vowels << endl
         << "and the total number of puntuation marks  : "
         << puncts << endl;
        
    if( numWords == 0 ) numWords = 1; // so don't divide by zero ...
    cout << "and the average number of letters per word: "
         << double(letters) / numWords << endl;
        
    cout << "\nCross-check of data:\n"
         << "'spaces between words' + 'letters' + 'punctuation marks' ...\n"
         << numWords-1 << " + " // = num of spaces, but need -1 (NO space at end)
         << letters << " + "
         << puncts << " = "
         << numWords-1 + letters + puncts
         << " ?== " << numChars << " (total number of char's in the text.)" << endl;

    cout << "\nPress 'Enter' to continue ... " << flush;
    cin.get();
}


Here is an example 'text file' to test the above program ... (I named this file test.txt) ...

Quote
In the beginning was the Word, and the Word was with God, and the Word was God. The same was in the beginning with God. All things were made by him; and without him was not any thing made that was made. In him was life; and the life was the light of men. And the light shineth in darkness; and the darkness comprehended it not.

There was a man sent from God, whose name [was] John. The same came for a witness, to bear witness of the Light, that all [men] through him might believe. He was not that Light, but [was sent] to bear witness of that Light. [That] was the true Light, which lighteth every man that cometh into the world. He was in the world, and the world was made by him, and the world knew him not. He came unto his own, and his own received him not. But as many as received him, to them gave he power to become the sons of God, [even] to them that believe on his name: Which were born, not of blood, nor of the will of the flesh, nor of the will of man, but of God. And the Word was made flesh, and dwelt among us, (and we beheld his glory, the glory as of the only begotten of the Father,) full of grace and truth.

John bare witness of him, and cried, saying, This was he of whom I spake, He that cometh after me is preferred before me: for he was before me. And of his fulness have all we received, and grace for grace. For the law was given by Moses, [but] grace and truth came by Jesus Christ. No man hath seen God at any time; the only begotten Son, which is in the bosom of the Father, he hath declared [him].

And this is the record of John, when the Jews sent priests and Levites from Jerusalem to ask him, Who art thou? And he confessed, and denied not; but confessed, I am not the Christ. And they asked him, What then? Art thou Elias? And he saith, I am not. Art thou that prophet? And he answered, No. Then said they unto him, Who art thou? that we may give an answer to them that sent us. What sayest thou of thyself? He said, I [am] the voice of one crying in the wilderness, Make straight the way of the Lord, as said the prophet Esaias. And they which were sent were of the Pharisees. And they asked him, and said unto him, Why baptizest thou then, if thou be not that Christ, nor Elias, neither that prophet? John answered them, saying, I baptize with water: but there standeth one among you, whom ye know not; He it is, who coming after me is preferred before me, whose shoe’s latchet I am not worthy to unloose. These things were done in Bethabara beyond Jordan, where John was baptizing.

The next day John seeth Jesus coming unto him, and saith, Behold the Lamb of God, which taketh away the sin of the world. This is he of whom I said, After me cometh a man which is preferred before me: for he was before me. And I knew him not: but that he should be made manifest to Israel, therefore am I come baptizing with water. And John bare record, saying, I saw the Spirit descending from heaven like a dove, and it abode upon him. And I knew him not: but he that sent me to baptize with water, the same said unto me, Upon whom thou shalt see the Spirit descending, and remaining on him, the same is he which baptizeth with the Holy Ghost. And I saw, and bare record that this is the Son of God.

Again the next day after John stood, and two of his disciples; And looking upon Jesus as he walked, he saith, Behold the Lamb of God! And the two disciples heard him speak, and they followed Jesus. Then Jesus turned, and saw them following, and saith unto them, What seek ye? They said unto him, Rabbi, (which is to say, being interpreted, Master,) where dwellest thou? He saith unto them, Come and see. They came and saw where he dwelt, and abode with him that day: for it was about the tenth hour. One of the two which heard John [speak], and followed him, was Andrew, Simon Peter’s brother. He first findeth his own brother Simon, and saith unto him, We have found the Messias, which is, being interpreted, the Christ. And he brought him to Jesus. And when Jesus beheld him, he said, Thou art Simon the son of Jona: thou shalt be called Cephas, which is by interpretation, A stone.

The day following Jesus would go forth into Galilee, and findeth Philip, and saith unto him, Follow me. Now Philip was of Bethsaida, the city of Andrew and Peter. Philip findeth Nathanael, and saith unto him, We have found him, of whom Moses in the law, and the prophets, did write, Jesus of Nazareth, the son of Joseph. And Nathanael said unto him, Can there any good thing come out of Nazareth? Philip saith unto him, Come and see. Jesus saw Nathanael coming to him, and saith of him, Behold an Israelite indeed, in whom is no guile! Nathanael saith unto him, Whence knowest thou me? Jesus answered and said unto him, Before that Philip called thee, when thou wast under the fig tree, I saw thee. Nathanael answered and saith unto him, Rabbi, thou art the Son of God; thou art the King of Israel. Jesus answered and said unto him, Because I said unto thee, I saw thee under the fig tree, believest thou? thou shalt see greater things than these. And he saith unto him, Verily, verily, I say unto you, Hereafter ye shall see heaven open, and the angels of God ascending and descending upon the Son of man.

And the output from a 'run' ... (using the above "test.txt" file) ...

Code: [Select]
Enter the file name of the text file to be processed: test.txt
Do you want to see that file on the console screen (y/n) ? n


The total number of paragraphs in the text: 7
The total number of sentences in the text : 60
The total number of words in the text was : 1004
and the total number of characters used   : 5214
and the total number of letters used was  : 3994
and the total number of vowels used was   : 1483
and the total number of consonants  was   : 2511
and the total number of puntuation marks  : 217
and the average number of letters per word: 3.97809

Cross-check of data:
'spaces between words' + 'letters' + 'punctuation marks' ...
1003 + 3994 + 217 = 5214 ?== 5214 (total number of char's in the text.)

Press 'Enter' to continue ...


You may have noted a problem with the first of the two above programs ... with some 'test data' like that in 'test.txt' above, where some of the punctuation is NOT 'the last character in the word' ... for example: the 'word' as,) in ... AKA (or, also known as,) ...

Also, you may wish to count ()[] ... and other char's as punctuation, and NOT as letters in a word.

If so, then see below for a way to handle this ... (by using a function like countPuncs) ...
« Last Edit: April 19, 2010, 09:59:34 PM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: First steps ... via example programs in C++ and C ...
« Reply #8 on: April 19, 2010, 08:46:39 PM »
Or ... a little simpler version of the above problem ... to compare and note different 'tests' and different output ...

Code: [Select]
// a C++ program that inspects the contents of a text file ...
// and ... counts the number of:
// 1. lines, 2. words, 3. letters, and 4. punctuation marks ...
// and 5. displays this data in a table

// a simple 'first' approach ... assume:

// 1. words are spaced by ONE space only ...
// 2a. no leading or trailing spaces on a line ... thus ...
// 2b. all spacing lines (between paragraphs) are empty (of spaces)


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

#include <iostream>
#include <iomanip> // re. setw(...)
#include <fstream>
#include <string>

using namespace std;


const char FILE_NAME[] = "textToCount.txt";
const string PUNCTS = "-\"'{}<>[]():;,!?."; // the punctuation marks to be checked

int countPuncs( const string& str )
{
    int count = 0;
    for( int j = str.length()-1; j >= 0; --j )
        for( int i = PUNCTS.length()-1; i >= 0; --i ) // for each punc... see if
            if( str[j] == PUNCTS[i] )                // = this 'j' char in str
                { ++ count; break; } // break out-of-inner-for-loop RIGHT-NOW
               
    return count;
}

int countSpaces( const string& str )
{
    int count = 0;
    for( int j = str.length()-1; j >= 0; --j )
        if( str[j] == ' ' ) // check if this 'j' char in str ... is a space
            ++ count;

    return count;
}



int main()
{
    int lines = 0,
        words = 0,
        letters = 0,
        puncMarks = 0;
    string line;
   
    ifstream fin( FILE_NAME ); // open file ...

    while( getline(fin, line) ) // while a line was read ...(into string 'line')
    {
        // now ... update stats for this line ...
       
        ++ lines; // increment line counter
        int lineLen = line.length();
        if( lineLen > 0 ) // skip blank lines ...
        {
            int n_spaces = countSpaces( line );
            words += n_spaces + 1; // number of words on line is (n_spaces + 1)
            int n_puncMarks = countPuncs( line );
            puncMarks += n_puncMarks;
            letters += lineLen - n_spaces - n_puncMarks;
        }
    }

    cout << setw(12) << "LINES"
         << setw(12) << "WORDS"
         << setw(12) << "LETTERS"
         << setw(12) << "P. MARKS" << endl;

    cout << setw(12) << lines
         << setw(12) << words
         << setw(12) << letters
         << setw(12) << puncMarks << endl;

    cout << "\nPress Enter' to continue ... " << flush;
    cin.get();
    return 0;
}


// file name: textToCount.txt
/*
In the beginning was the Word,
and the Word was with God,
and the Word was God.
The same was in the beginning with God.

All things were made by him;
and without him was not any thing made that was made.

In him was life;
and the life was the light of men.

And the light shineth in darkness;
and the darkness comprehended it not.
*/

// output from a run with above textToCount.txt file ...
/*
       LINES       WORDS     LETTERS    P. MARKS
          13          66         252          10

Press Enter' to continue ...
*/

Code: [Select]
// a C++ program that inspects the contents of a text file ...
// and ... counts the number of:
// 1. lines, 2. words, 3. letters, and 4. punctuation marks ...
// and 5. displays this data in a table

// this version isolates/gets each word ... on each line ...

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

#include <iostream>
#include <iomanip> // re. setw(...)
#include <fstream>
#include <string>

using namespace std;

#define debugging false

const char FILE_NAME[] = "textToCount.txt";
const string PUNCTS = "-\"'{}<>[]():;,!?."; // the punctuation marks to be checked

string getNextWord(const string& line, int& i, int size)
{
    int j = i;
    while( j < size && line[j] != ' ' )
        ++j; // set j to one position past end of word

    string word = line.substr(i, j-i); // ok ... get this word ...
   
    i = j; // update next starting i (updated i is returned via 'pass by ref.')
   
    while( i < size && line[i] == ' ' )
        ++i; // skip over any leading spaces ...

    return word; // and return this word ...
}

int countPuncs( const string& str )
{
    int count = 0;
    for( int j = str.length()-1; j >= 0; --j )
        for( int i = PUNCTS.length()-1; i >= 0; --i ) // for each punc... see if
            if( str[j] == PUNCTS[i] )                // = this 'j' char in str
                { ++ count; break; } // break out-of-inner-for-loop RIGHT-NOW

    return count;
}


int main()
{
    int lines = 0,
        words = 0,
        letters = 0,
        pMarks = 0;
    string line;
   
    ifstream fin( FILE_NAME ); // open file ...

    while( getline(fin, line) ) // while a line was read ...(into string 'line')
    {
        // now ... update stats for this line ...
       
        ++ lines; // increment line counter
        int i = 0; // i holds index for first char in each word ...
        int size = line.length(); // size-1 is index of last char in line ...
       
        while( i < size && line[i] == ' ' )
            ++i; // skip over any leading spaces ...
           
        while( i < size-1 )
        {
            string word = getNextWord(line, i, size); // i updated by pass by ref.
            ++ words; // increment word counter
            letters += word.length(); // increment letter counter ...
            int n_pMarks = countPuncs( word );
            pMarks += n_pMarks; // increment pMarks counter
            letters -= n_pMarks; // and adjust ...
#if debugging
            cout << word << ' ';
#endif
        } // end of inner while ...
#if debugging
        cout << setw(6) << lines
             << setw(6) << words
             << setw(6) << letters
             << setw(6) << pMarks << endl;
#endif
    } // end of outer while ...

    cout << setw(12) << "LINES"
         << setw(12) << "WORDS"
         << setw(12) << "LETTERS"
         << setw(12) << "P. MARKS" << endl;

    cout << setw(12) << lines
         << setw(12) << words
         << setw(12) << letters
         << setw(12) << pMarks << endl;

    cout << "\nPress Enter' to continue ... " << flush;
    cin.get();
    return 0;
}


// file name: textToCount.txt
/*
In the beginning was the Word,
and the Word was with God,
and the Word was God.
The same was in the beginning with God.

All things were made by him;
and without him was not any thing made that was made.

In him was life;
and the life was the light of men.

And the light shineth in darkness;
and the darkness comprehended it not.
*/

// output from a run with above textToCount.txt file ...
/*
       LINES       WORDS     LETTERS    P. MARKS
          13          66         252          10

Press Enter' to continue ...
*/

Code: [Select]
// a C++ program that inspects the contents of a text file ...
// and ... counts the number of:
// 1. lines, 2. words, 3. letters, and 4. punctuation marks ...
// and 5. displays this data in a table

// this version uses stringstream ...

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

#include <iostream>
#include <iomanip> // re. setw(...)
#include <fstream>
#include <sstream>

using namespace std;

#define debugging false

const char FILE_NAME[] = "textToCount.txt";
const string PUNCTS = "-\"'{}<>[]():;,!?."; // the punctuation marks to be checked

int countPuncs( const string& str )
{
    int count = 0;
    for( int j = str.length()-1; j >= 0; --j )
        for( int i = PUNCTS.length()-1; i >= 0; --i ) // for each punc... see if
            if( str[j] == PUNCTS[i] )                // = this 'j' char in str
                { ++ count; break; } // break out-of-inner-for-loop RIGHT-NOW

    return count;
}


int main()
{
    int lines = 0,
        words = 0,
        letters = 0,
        pMarks = 0;
    string line;
   
    ifstream fin( FILE_NAME ); // open file ...

    while( getline(fin, line) ) // while a line was read ...(into string 'line')
    {
        // now ... update stats for this line ...
       
        ++ lines; // increment line counter
        istringstream issline( line ); // get object 'line' into object 'issline'
        string word;
        while( issline >> word ) // get words (separated-by/skip-over whitespaces)
        {
            ++ words; // increment word counter
            letters += word.length(); // increment letter counter ...
            int n_pMarks = countPuncs( word );
            pMarks += n_pMarks; // increment pMarks counter
            letters -= n_pMarks; // and adjust ...
#if debugging
            cout << word << ' ';
#endif
        } // end of inner while ...
#if debugging
        cout << setw(6) << lines
             << setw(6) << words
             << setw(6) << letters
             << setw(6) << pMarks << endl;
#endif
    } // end of outer while ...

    cout << setw(12) << "LINES"
         << setw(12) << "WORDS"
         << setw(12) << "LETTERS"
         << setw(12) << "P. MARKS" << endl;

    cout << setw(12) << lines
         << setw(12) << words
         << setw(12) << letters
         << setw(12) << pMarks << endl;

    cout << "\nPress Enter' to continue ... " << flush;
    cin.get();
    return 0;
}


// file name: textToCount.txt
/*
In the beginning was the Word,
and the Word was with God,
and the Word was God.
The same was in the beginning with God.

All things were made by him;
and without him was not any thing made that was made.

In him was life;
and the life was the light of men.

And the light shineth in darkness;
and the darkness comprehended it not.
*/

// output from a run with above textToCount.txt file ...
/*
       LINES       WORDS     LETTERS    P. MARKS
          13          66         252          10

Press Enter' to continue ...
*/


Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: First steps ... via example programs in C++ and C ...
« Reply #9 on: July 10, 2010, 09:29:43 AM »
Addendum:

Some very-first-steps C/C++ programs, C version side-by-side the C++ version ...

Compile and run these programs ...

Then when you see how they work ... you may like to fast-track your own programming by using these examples as 'templates' to start you off with compiling/working code ... where-ever applicable?


Code: [Select]
/* shell.c */

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

#include <stdio.h>


int main()
{
/*
    You may need to 'un-comment' the 'while( getchar != '\n' );' line BELOW,
    to pause your program, IF (char's and) a '\n' char remains after/if 'input'
    // effect of line below is same as 'clear/empty' all char's in stdin
    // while( getchar != '\n' ); // 'flush' stdin buffer ...
*/
    fputs( "\nPress 'Enter' to continue/exit ... ", stdout); fflush( stdout );
    getchar(); /* keep 'Window' open until 'Enter' key is pressed ... */
    return 0;
}


Code: [Select]
// shell.cpp

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

#include <iostream>

using namespace std;

int main()
{
    // You may need to 'un-comment' the 'cin.sync();' line BELOW, t0 pause your
    // program, IF (char's and) a '\n' char remains after/if 'input above' ...
    // cin.sync(); // effect is same as 'clear/empty' all char's in cin stream

    cout << "\nPress 'Enter' to continue/exit ... " << flush;
    cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
}


Code: [Select]
/* more.c */

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

#include <stdio.h>

int more()/* defaults to 'true'/'yes'/'1' ... unless 'n' or 'N' entered ... */
{
    int c, reply;
    fputs( "More (y/n) ? ", stdout ); fflush( stdout );
    reply = c = getchar();
    while( c != '\n' ) c = getchar(); /* 'flush' stdin buffer ...  */
    if( reply == 'n' || reply == 'N' ) return 0;
    /* else ... */
    return 1;
}


int main()
{
    int count = 0, sum = 0;
   
    for( ; ; ) /* an example C/C++ forever loop ... until 'break' ... */
    {
        int numGood, testInt;
       
        fputs( "Enter next integer to sum: ", stdout ); fflush( stdout );
        numGood = fscanf( stdin, "%d", &testInt );
        while( getchar() != '\n' ); /* 'flush' stdin ... */
        if( numGood != 1 )
        {
            puts( "Invalid input! Integers only please ..." );
            continue; /* go to top of 'for loop' right now ... */
        }
       
        /* else ... */
        ++count;
        sum += testInt;
       
        /* make sure stdin buffer is 'empty' before calling 'more()' ... */
        if( !more() ) break;
    }
   
    printf( "\nFor %d numbers entered, sum was %d and average was %.2f\n",
            count, sum, (float)sum/count );
           
    fputs( "\nPress 'Enter' to continue/exit ... ", stdout); fflush( stdout );
    getchar(); /* keep 'Window' open until 'Enter' key is pressed ... */
    return 0;
}


Code: [Select]
// more.cpp

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

#include <iostream>

using namespace std;

bool more()/* defaults to 'true'/'yes' ... unless 'n' or 'N' entered ... */
{
    cout << "More (y/n) ? " << flush;
    int reply = cin.get();
    cin.sync(); /* 'flush' cin stream  ...  */
    if( reply == 'n' || reply == 'N' ) return false;
    /* else ... */
    return true;
}


int main()
{
    int count = 0, sum = 0;

    for( ; ; ) /* an example C/C++ forever loop ... until 'break' ... */
    {
        int testInt;

        cout << "Enter next integer to sum: " << flush;
        cin >> testInt;
        if( !cin.good() )
        {
            cin.clear(); // clear cin error flag(s) ...
            cin.sync(); // 'flush' cin stream ...
            cout << "Invalid input! Integers only please ...\n";
            continue; /* go to top of 'for loop' right now ... */
        }

        /* else ... */
        cin.sync(); // 'flush' cin stream ... as  we go ...
        ++count;
        sum += testInt;

        /* make sure cin stream is 'empty' before calling 'more()' ... */
        if( !more() ) break;
    }

    cout << "\nFor " << count << " numbers entered, sum was " << sum
         << " and average was " << float(sum)/count << endl;


    cout << "\nPress 'Enter' to continue/exit ... " << flush;
    cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
}


Code: [Select]
/* getValidInt.c */

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

#include <stdio.h>

int getValidInt( char prompt[] )
{
    for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' ... */
    {
        int numGood, testInt;
        fputs( prompt, stdout ); fflush( stdout );
        numGood = fscanf( stdin, "%d", &testInt );
        while( getchar() != '\n' ); /* 'flush' stdin ... as we go ... */
        if( numGood == 1 ) return testInt;
        /*else ...*/
        puts( "Invalid input! Integers only please ..." );
    }
}

int more()/* defaults to 'true'/'yes'/'1' ... unless 'n' or 'N' entered ... */
{
    int c, reply;
    fputs( "More (y/n) ? ", stdout ); fflush( stdout );
    reply = c = getchar();
    while( c != '\n' ) c = getchar(); /* 'flush' stdin buffer ...  */
    if( reply == 'n' || reply == 'N' ) return 0;
    /* else ... */
    return 1;
}


int main()
{
    int count = 0, sum = 0;
   
    do
    {
        int testInt = getValidInt( "Enter next integer to sum: " );
        ++count;
        sum += testInt;
       
        /* make sure stdin buffer is 'empty' before calling 'more()' ... */
    }
    while( more() );
   
    printf( "\nFor %d numbers entered, sum was %d and average was %.2f\n",
            count, sum, (float)sum/count );
           
    fputs( "\nPress 'Enter' to continue/exit ... ", stdout); fflush( stdout );
    getchar(); /* keep 'Window' open until 'Enter' key is pressed ... */
    return 0;
}


Code: [Select]
// getValidInt.cpp

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

#include <iostream>

using namespace std;

int getValidInt( char prompt[] )
{
    for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' ... */
    {
        cout << prompt << flush;
        int testInt;
        cin >> testInt;
        if( cin.good() )
        {
            cin.sync(); // 'flush' cin stream as we go ...
            return testInt;
        }
        // else ...
        cin.clear(); // clear cin error flag(s) ...
        cin.sync();
        cout << "Invalid input! Integers only please ...\n" ;
    }
}

bool more()/* defaults to 'true'/'yes' ... unless 'n' or 'N' entered ... */
{
    cout << "More (y/n) ? " << flush;
    int reply = cin.get();
    cin.sync(); /* 'flush' cin stream  ...  */
    if( reply == 'n' || reply == 'N' ) return false;
    /* else ... */
    return true;
}


int main()
{
    int count = 0, sum = 0;

    do
    {
        int testInt = getValidInt( "Enter next integer to sum: " );
        ++count;
        sum += testInt;

        /* make sure cin stream is 'empty' before calling 'more()' ... */
    }
    while( more() );

    cout << "\nFor " << count << " numbers entered, sum was " << sum
         << " and average was " << float(sum)/count << endl;

    cout << "\nPress 'Enter' to continue/exit ... " << flush;
    cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
}
« Last Edit: July 14, 2010, 05:21:17 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: First steps ... via example programs in C++ and C ...
« Reply #10 on: September 14, 2010, 09:43:32 AM »
Here is an often asked student coding problem ... converting an integer to Roman Numerals ...


Code: [Select]
// intToRomanNumerals.cpp // this revision 2010-09-14 //

/*
    Demo of converting DECIMAL NUMERALS to ROMAN NUMERALS ...
    Modified for strings, and to use the MSD, (Most Significant Digit)
    rather than the LSD (Least Significant Digit) method used by Randy.
    Randall Hyde is the author of HLA (High Level Assembly) ... See ...
    http://webster.cs.ucr.edu/AoA/index.html
    http://developers-heaven.net/forum/index.php/topic,46.0.html
*/

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;

string iToString( int i ) // convert integer 'i' to a string
{
    ostringstream oss;
    oss << i;
    return oss.str(); // return as a string ...
}

string convert( int n )
{
    if( n > 3999 ) return "Largest number handled is 3999";
    if( n < 1 ) return "Smallest number handled is 1";

    string nStr = iToString( n ); // now n is in nStr ...

    string rm; // construct an empty string to hold the growing Roman Num...

    for( size_t i = 0; i < nStr.length(); ++i ) // traverse nStr ...
    {
        // On each pass ... extract the NEXT Most Significant Digit (MSD)
        // from the number 'n' ... i.e. from 'nStr'
        int msd = nStr[i] - '0'; // ok ... now have next Most Significant Digit

        // Here is the trick, (from Randy of HLA), that makes this work ...
        // On each pass ... 'multiply' the previous Roman Num by 10
        // This is achieved by swapping the characters in the char string 's1'
        // with their corresponding character in char string 's2' below ...
        char s1[] = "IVXLCDM";
        char s2[] = "XLCDM**"; // each valid 'char' here is 10 times the above

        // On each pass, the folowing set of nested loops will 'multiply by 10',
        // (similar to a 'left shift' for decimal numbers), the value in string
        // rm (string rm holds the growing Roman Numeral value, empty to start)

        // Note: next loops are skipped on first pass when rm.size() is still 0
        for( size_t j = 0; j < rm.size(); ++j ) // for each digit in nStr, get rm[j]
        {
            for( size_t k = 0; k < 7; ++k ) // for each Roman digit above, traverse s1
            if( rm[j] == s1[k] ) // find k... so can ... 'multiply by 10'
            {
                rm[j] = s2[k];
                break; // since k was found ... and x10 was done
            }
        }
       
        // Ok ... all previous Roman Numerals have been multiplied by 10 ... so
        // now ... convert the current MSD int ... to a Roman Num string
        // and add in ... at the end of the growing 'rm' string ...
        string romanNum[] =
        {//  0,  1,    2,     3,    4,   5,    6,     7,     8,     9
            "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"
        };
        rm = rm + romanNum[msd];

        cout << rm << endl; // shows steps ... comment out if desired //
    }
    return rm; // return the string holding the Roman Numerals ...
}


int main()
{
    int n;
    string prompt = "Enter a number from the keyboard (q to quit) : ";

    // the while loop will exit if the 'n' that was input was NOT a valid int
    while( cout << prompt << flush  &&  cin >> n )
        cout << "The number " << n << " converted is " << convert(n) << endl;
}


And the other way ...

Note:  you will need a C++ 11 or better compiler to compile the following (only lightly tested) demo code ...

Code: [Select]
// romanNumeralsToInt.cpp // this revision 2017-01-30 //

// Compile with a C++ 11 compiler (or better) //

/*
    Demo of converting ROMAN NUMERALS to DECIMAL NUMERALS ...
    http://developers-heaven.net/forum/index.php/topic,46.0.html
*/

#include <iostream>
#include <string>

using namespace std;

struct NumToInt
{
    string nStr;
    int val;
};


const NumToInt ConvTable[] =
{
    {"MMM",3000}, {"MM",2000}, {"MCM",1900},
    {"MDCCC",1800}, {"MDCC",1700}, {"MDC",1600}, {"MCD",1400}, {"MD",1500},
    {"MCCC",1300}, {"MCC",1200}, {"MC",1100}, {"CM",900}, {"M",1000},
    {"DCCC",800}, {"DCC",700}, {"DC",600}, {"CD",400}, {"D",500},
    {"XC",90}, {"CCC",300}, {"CC",200}, {"C",100},
    {"LXXX",80}, {"LXX",70}, {"LX",60}, {"XL",40}, {"L",50}, {"VIII",8}, {"XXX",30}, {"XX",20},
    {"IX",9}, {"X",10}, {"IV",4},  {"VI",6}, {"VII",7}, {"VIII",8},
    {"V",5}, {"III",3}, {"II",2}, {"I",1}
};


int convert( string nStr )
{
    //if( n > 3999 ) return "Largest number handled is 3999";
    //if( n < 1 ) return "Smallest number handled is 1";

    int val = 0;
    for( auto item : ConvTable ) // traverse array ...
    {
        size_t pos;
        if( (pos = nStr.find(item.nStr)) != string::npos )
        {
            val += item.val;
            nStr.erase(pos, item.nStr.size());
            if( !nStr.size() ) break;
        }
    }
    return val;
}


int main()
{
    string nStr;
    string prompt = "Enter a valid Roman Numeral from the keyboard (q to quit) : ";

    // the while loop will exit if the 'n' that was input was NOT a valid int
    while( cout << prompt << flush  &&  cin >> nStr )
    {
        if( nStr == "q" ) return 0;
       
        cout << "The number " << nStr << " converted is " << convert(nStr) << endl;
    }
}


« Last Edit: January 30, 2017, 11:41:54 AM by David »