Author Topic: Send in your C++ or C student coding problem, with code inside code tags (#)  (Read 110499 times)

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Update:  please see this next link:

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

You can contact me via this link ...

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

(my/editor gmail link is on the 2nd page)

Ok students beginning C or C++ ... this page is for you to get help with your beginning computer programming problems in C or C++.

Please include your code inside code tags ...

After you click on the Reply icon below, on the new page presented to you to write about your problem and submit your code ...
Click on the above # icon to ....
Code: [Select]
  // your code goes here ... //
insert your code between these two start and stop code tags ...[ code ] // your code goes here ... // [ /code ]  Only don't add spaces inside the tags as I did here, so that you could SEE something of what code tags look like.  The code tags will preserve the indentation of your C/C++ code.

Please include a statement of the problem given and the problem(s) you are having ... and allow some time for a reply, as this help is being offered on a trial experimental gratuitous basis.

BEFORE you click on Post/Save at the bottom of your page, please click on Preview ...

and make sure you correct any typos ...

and that the problem is stated clearly ...

using good grammar and helpful punctuation.


Shalom shalom,

David
« Last Edit: September 06, 2018, 02:59:48 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Here is an example, to follow please :) ... and to get started ...

This student problem, is to code in C, merging two arrays of integers into a 3rd array so that the 3rd array only has unique elements ... i.e. a value occurs at most once in the 3rd array of merged values ... and the values are to be entered into the first two arrays from the keyboard.

Below is an example of some working code to start ... (i.e. a working shell to get started.)

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

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

#include <stdio.h>

#define MAX_SIZE 5 /* keep this number small while still testing/debugging */

void printAry( const int ary[], int num )
{
    int i;
    for( i = 0; i < num; ++i )
        printf( "%d ", ary[i] );
}

int main()
{
    /* create some arrays to hold your test data and the merged unique data */
    int ary1[MAX_SIZE], ary2[MAX_SIZE], ary3[2*MAX_SIZE];
   
    int i;
    for( i = 0; i < MAX_SIZE; ++i )
    {
        printf( "For ary1, enter integer %d: ", i+1 ); fflush( stdout );
        scanf( "%d", &ary1[i] );
        printf( "For ary2, enter integer %d: ", i+1 ); fflush( stdout );
        scanf( "%d", &ary2[i] );
        ary3[i] = ary1[i];
        ary3[MAX_SIZE+i] = ary2[i];
    }
   
    while( getchar() != '\n' ) ; /* flush stdin ... */
   
    printf( "\nary1 is: " );
    printAry( ary1, MAX_SIZE );

    printf( "\nary2 is: " );
    printAry( ary2, MAX_SIZE );

    printf( "\nary3 is: " );
    printAry( ary3, 2*MAX_SIZE );

    fputs( "\nPress 'Enter' to continue/exit ... ", stdout); fflush( stdout );
    getchar(); /* keep 'Window' open until 'Enter' key is pressed ... */
    return 0;
}

A very common student problem at this stage is that the code compiles and runs ... but the student can't SEE any output because the window closes so quickly upon running ... because this following line, (or equivalent coding), was left off ...

Code: [Select]
while( getchar() != '\n' ) ; /* flush stdin ... */
Recall that scanf, when used to get a number from keyboard, skips over any leading whitespace, gets the number (if there), but stops AND LEAVES any trailing whitespace char's (like the '\n' char), or all char's after any non-numeric char's accidently entered, in the stdin buffer ...

So then the getchar() at the end of the program, gets that first whitespace char, or non-numeric char, still left in the stdin buffer, and thus will NOT WAIT for the Enter key to be pressed before exiting your program.

So, the goal here, as a first step, is to get some working code ... and some output THAT YOU CAN SEE IS the EXACT expected output for your test input.

Then you can add/edit from this starting working code ... to move ever closer to the full functionality you desire in your final program.

Note the 3rd array here contains ALL the values in arrays 1 and 2, but that is ok for now.

Note also that if the first non-whitespace char entered is a NON numeric char, this program will crash.  A way to handle numeric input, to avoid crashes on invalid input, follows below.

« Last Edit: July 14, 2011, 11:52:32 PM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
The version below adds validation to your integer input from the keyboard, so that your program will not crash on bad input.  Also, each array is entered separately, and will accept data up to the maximum size permitted at compile time.

This is just one way to handle this problem.  Another way, see below, might be to add all array 1 to array 3 ... then add after that, all of array 2 to array 3 ... then to transform array 3 into an array of unique elements, perhaps by way of first sorting it ...

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

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

#include <stdio.h>

#define MAX_SIZE 5 /* keep small while testing/debugging ... */

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;
}

/* returns the entered array ('by reference') and the size of the array entered,
   size can be in range 0..max */
int enterAry( const char prompt[], int ary[], int max )
{
    int i = 0, numGoodVals;
    printf( "%s (max size %d)\n", prompt, max ); fflush( stdout );
    do
    {
        printf( "enter integer %d: ", i+1 ); fflush( stdout );
        numGoodVals = scanf( "%d", &ary[i] );
        while( getchar() != '\n' ) ; /* flush stdin ... */
        if( numGoodVals != 1 )
        {
            printf( "Please enter only integers ...\n" );
            continue; /* jump to test at end of do..while loop right NOW! */
        }
        /* else ... */
        ++i;
        if( i == max ) break;
    }while( more() );

    return i; /* the number of int's entered ... 'i' is in range 0..max */
}

void printAry( const int ary[], int num )
{
    int i;
    for( i = 0; i < num; ++i )
        printf( "%d ", ary[i] );
}


int exist( const int ary[], int size, int val )
{
    int i;
    for( i = 0; i < size; ++i )
        if( ary[i] == val ) return 1;

    return 0;
}


int main()
{
    int ary1[MAX_SIZE], ary2[MAX_SIZE], ary3[2*MAX_SIZE],
        i, size1, size2, size3;
   
    size1 = enterAry( "Enter ary1 ...", ary1, MAX_SIZE );
    size2 = enterAry( "Enter ary2 ...", ary2, MAX_SIZE );
   
    printf( "\nary1 is: " ); printAry( ary1, size1 );
   
    printf( "\nary2 is: " ); printAry( ary2, size2 );
   
    size3 = 0;
    for( i = 0; i < size1; ++i )
    {
        if( !exist(ary3, size3, ary1[i]) )
        {
            ary3[size3] = ary1[i];
            ++ size3;
        }
    }

    for( i = 0; i < size2; ++i )
    {
        if( !exist(ary3, size3, ary2[i]) )
        {
            ary3[size3] = ary2[i];
            ++ size3;
        }
    }

    printf( "\nary3 is: " ); printAry( ary3, size3 );
   
    fputs( "\nPress 'Enter' to continue/exit ... ", stdout); fflush( stdout );
    getchar(); /* keep 'Window' open until 'Enter' key is pressed ... */
    return 0;
}

Here is that other way that was suggested that you might proceed ... solving this problem by merging two arrays into a new array of sorted unique elements ...

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

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

#include <stdio.h>

#define SIZE 5

void printAry( const int ary[], int num )
{
    int i;
    for( i = 0; i < num; ++i )
        printf( "%d ", ary[i] );
}

void bubblesort( int ary[], int size )
{
    int j, swap, tmp;
    do
    {
        swap = 0; // if array is sorted ... then DONE after the next pass
        // only have to check, each loop, up to to size-1 places
        for( j = 1; j < size; ++j )
        {
            if( ary[j-1] > ary[j] ) // swap value at j-1 with value at j
            {
                tmp = ary[j];
                ary[j] = ary[j-1];
                ary[j-1] = tmp;
                swap = 1;
            }
        }
        --size;
    }while( swap );
}

int getUnique( int ary[], int size )
{
    int i = 0, j =1;
    for( ; j < size ; ++j )
    {
        if( ary[i] != ary[j] ) if( ++i != j ) ary[i] = ary[j];
    }
    return i+1; // return updated size, now of unique elements
}



int main()
{
    int i, unique, ary1[SIZE], ary2[SIZE], ary3[2*SIZE];
   
    for( i = 0; i < SIZE; ++i )
    {
        printf( "For ary1, enter integer %d: ", i+1 ); fflush( stdout );
        scanf( "%d", &ary1[i] );
        printf( "For ary2, enter integer %d: ", i+1 ); fflush( stdout );
        scanf( "%d", &ary2[i] );
        ary3[i] = ary1[i];
        ary3[SIZE+i] = ary2[i];
    }
    while( getchar() != '\n' ) ; /* flush stdin ... */
   
    printf( "\nary1 is: " );
    printAry( ary1, SIZE );
   
    printf( "\nary2 is: " );
    printAry( ary2, SIZE );
   
    printf( "\nary3 is: " );
    printAry( ary3, 2*SIZE );
   
    bubblesort( ary3, 2*SIZE );
    printf( "\nary3 sorted is: " );
    printAry( ary3, 2*SIZE );

    unique = getUnique( ary3, 2*SIZE );
    printf( "\nunique ary3 size is %d and ary3 is: ", unique );
    printAry( ary3, unique );

    fputs( "\nPress 'Enter' to continue/exit ... ", stdout); fflush( stdout );
    getchar(); /* keep 'Window' open until 'Enter' key is pressed ... */
    return 0;
}

« Last Edit: July 14, 2011, 11:58:12 PM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
This version demos using dynamic arrays ... sort (just a simple bubble sort here) ... and unique functions ...

Code: [Select]
/* mergeTwoArysStep3.c */ /* using dynamic arrays, sort and unique functions */

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

#include <stdio.h>
#include <stdlib.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 getValidInt( const 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 ..." );
    }
}

/* get memory to hold an array of size int's .. and return pointer to memory */
int* getIntAryMemory( int size )
{
    int* ary = malloc( sizeof(int)*size );
    if( ary == NULL )
    {
        fprintf( stderr,
                 "malloc failed in 'getIntAryMemory' for size = %d\n", size );
        fputs( "Press 'Enter' to continue/exit ... ", stderr );
        getchar();
        exit(1);
    }
    else return ary; // returns pointer to new array
}

/* Note:
   any unused array memory in function below is NOT accessable after exiting
   the function unless the 'max' value is returned, (NOTE: 'size' returned here)
*/
/* returns filled new array and the size of the new array entered ... */
int enterAry( const char prompt[], int** ary ) /* passing in pointer to pointer */
{
    int i = 0;
    int max = getValidInt( "Enter max size for this array of integers: " );
    *ary = getIntAryMemory( max ); /* de-reference address to get to pointer */
    do
    {
        printf( "Enter integer %d: ", i+1 );
        (*ary)[i++] = getValidInt( "" );
        if( i == max )
        {
            printf( "You have reached the maximum size of %d elements "
                    "for this array.\n", max );
            break;
        }
    }while( more() );

    return i; /* i hold the number of int's entered ... i is in range 0..max */
}



void printAry( const int ary[], int num )
{
    int i;
    for( i = 0; i < num; ++i )
        printf( "%d ", ary[i] );
}

void bubblesort( int ary[], int size )
{
    int j, swap, tmp;
    do
    {
        swap = 0; /* if array is sorted ... then DONE after the next pass */
        /* only have to check, each loop, up to to size-1 places */
        for( j = 1; j < size; ++j )
        {
            if( ary[j-1] > ary[j] ) /* swap value at j-1 with value at j */
            {
                tmp = ary[j];
                ary[j] = ary[j-1];
                ary[j-1] = tmp;
                swap = 1;
            }
        }
        --size;
    }while( swap );
}

int getUnique( int ary[], int size )
{
    int i = 0, j = 1;
    for( ; j < size ; ++j )
    {
        if( ary[i] != ary[j] ) if( ++i != j ) ary[i] = ary[j];
    }
    return i+1; // return updated size, now of unique elements
}



int main()
{
    /* Note: below ... ary1, ary2, ary3 are pointers to int,
       i.e. variables to hold the address of an int,
       or the address to the first int in a block (an array) of int's */
    int *ary1, *ary2, *ary3, i, size1, size2, size3, uniqueSize;

    size1 = enterAry( "Enter ary1 ...", &ary1 ); /* passing in a 'reference' */
    putchar( '\n' );
    size2 = enterAry( "Enter ary2 ...", &ary2 ); /* i.e. pass in pointer address */
   
    printf( "\nary1 is: " ); printAry( ary1, size1 );
    printf( "\nary2 is: " ); printAry( ary2, size2 );
   
    size3 = size1 + size2;
    ary3 = getIntAryMemory( size3 ); /* get memory to hold array 3 ... */
   
    /* copy ary1 into first part of ary3 */
    for( i = 0; i < size1; ++i )
        ary3[i] = ary1[i];
    /* copy ary2 into last part of ary3 */
    for( i = 0; i < size2; ++i )
        ary3[size1+i] = ary2[i];
       
    printf( "\nary3 is: " );
    printAry( ary3, size3 );
   
    bubblesort( ary3, size3 );
    printf( "\nary3 sorted is: " );
    printAry( ary3, size3 );

    uniqueSize = getUnique( ary3, size3 );
    printf( "\nunique ary3 size is %d and unique ary3 is ", uniqueSize );
    printAry( ary3, uniqueSize );
   
    /* free all dynamic memory when done with it ...*/
    free( ary3 );
    free( ary2 );
    free( ary1 );

    fputs( "\nPress 'Enter' to continue/exit ... ", stdout); fflush( stdout );
    getchar(); /* keep 'Window' open until 'Enter' key is pressed ... */
    return 0;
}
« Last Edit: July 15, 2011, 12:00:37 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
This next version is an upgrade of the previous version that used dynamic arrays ...  Here we are using a C vector (Cvec) structure which is really just a fancied up and re-usable dynamic array structure ... that tracks the size, the cap (capacity), if it isSorted ... and the Cvec is expandable, via push_back and reserve functions, to as much memory that is available in your PC.  It also provides several ready to use functions like merge sort, insertion sort, find, erase, and unique - which is mainly what we want here.  Cvec is an emulation in C of the STL C++ vector container, that is so very useful.  With a little practice, you may find that Cvec is a fairly frendly C emulation that you will want to use to hold your data ... int's, doubles, dynamic C strings, struct's, etc ...

The following code uses the two files that follow ... "CvecOfInt.h" and "Cvec.h"

Make sure these are in the same directory/folder as your program file ... "mergeTwoCvecOfInt.c"  ... before you compile the program in C.


Code: [Select]
/* mergeTwoCvecOfInt.c */  /* 2016-10-09 */


/* using CvecOfInt.h that emulates some of the C++ STL vector */

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


#define myType double /* not needed here if using default #define myType int */

#include "CvecOfInt.h" /* changed to CvecOfDouble by above pre-define of myType */
/*
    "CvecOfInt.h" also includes <stdio.h>, <stdlib.h>, <string.h> and myAssert(..)
    and also includes the file "Cvec.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;
}

void enterCvec( const char prompt[], Cvec* cv )
{
    int i = 0, numGoodVals;
    Rec r;
    puts( prompt ); fflush( stdout );
    do
    {
        printf( "enter number %d: ", i+1 ); fflush( stdout );
        numGoodVals = scanf( "%lf", &r.val );
        while( getchar() != '\n' ) ; /* flush stdin ... */
        if( numGoodVals != 1 )
        {
            printf( "Please enter only integers ...\n" );
            continue;
        }
        ++i;
        push_backCvec( cv, &r );
    }while( more() );
}

void printCvec( Cvec* cv )
{
    int i;
    for( i = 0; i < cv->size; ++i )
        printf( "%.2f ", cv->ary[i].val );
    printf( "cap = %d, size = %d\n", cv->cap, cv->size );
}

/*
int exist( Cvec* cv, myType val )
{
    int i;
    for( i = 0; i < cv->size; ++i )
    {
        if( cv->ary[i].val == val ) return 1;
    }
    return 0;
}
*/



int main()
{
    int i;
    myType testVal;
    Cvec cv1, cv2, cv3;
    initCvec( &cv1 ); /* NOTE: MUST initial before using for Cvec to work ... */
    initCvec( &cv2 );
    initCvec( &cv3 );
   
    enterCvec( "Enter Cvec1 ...", &cv1 ); /* Note: passing a 'reference' ... */
    enterCvec( "\nEnter Cvec2 ...", &cv2 );

   
    /* method ONE ... adding ONLY elements, NOT already present, to new cv3 */
   
    for( i = 0; i < cv1.size; ++i )
    {
        /* if( !exist( &cv3, cv1.ary[i].val) ) */
        if( findCvec( &cv3, cv1.ary[i].val) == -1 )
        {
            push_backCvec( &cv3, &cv1.ary[i] );
        }
    }

    for( i = 0; i < cv2.size; ++i )
    {
        /* if( !exist( &cv3, cv2.ary[i].val) ) */
        if( findCvec( &cv3, cv2.ary[i].val ) == -1 )
        {
            push_backCvec( &cv3, &cv2.ary[i] );
        }
    }

    printf( "\ncv1 is: " ); printCvec( &cv1 );
    printf( "cv2 is: " ); printCvec( &cv2 );
    printf( "cv3 is: " ); printCvec( &cv3 );
    msortCvec( &cv3 );
    printf( "\nAfter msort( &cv3 ) ...\n" );
    printf( "cv3 is: " );printCvec( &cv3 );

   
    /* method TWO ... append cv2 to cv1, then sort cv1 and get unique cv1 */
   
    puts( "\nTesting uniqueCvec ... but first, cv2 appended to cv1:" );
    /*
    for( i = 0; i < cv2.size; ++i )
    {
        push_backCvec( &cv1, &cv2.ary[i] );
        printf( "cv1.cap = %d, sv1.size = %d\n", cv1.cap, cv1.size );
    }
    */
    reserveCvec( &cv1, cv1.size + cv2.size ); /* get just enough memory ... */
    for( i = 0; i < cv2.size; ++i )
    {
        cv1.ary[cv1.size ++] = cv2.ary[i]; /* increment size AFTER assignment */
        printf( "cv1.cap = %d, cv1.size = %d\n", cv1.cap, cv1.size );
    }
    puts( "After appending cv2 to cv1 ..." );
    printf( "cv1 is: " ); printCvec( &cv1 );
   
    testVal = cv1.ary[cv1.size-1].val; /* get copy of last val for future use */

    puts( "Testing supplied isortCvec( &cv1 ) ...\n"
          "(NOT really needed here because uniqueCvec will call msort if !isSorted)" );
    isortCvec( &cv1 );
    printf( "After isortCvec( &cv1 ) ...\n" );
    printf( "cv1 is: " ); printCvec( &cv1 );
   
    printf( "\nTesting find %.2f and erase ...\n", testVal );
    i = findCvec( &cv1, testVal );
    if( i != -1 ) eraseCvec( &cv1, i );
    printf( "cv1 is: " ); printCvec( &cv1 );
   
   
    uniqueCvec( &cv1 );
    puts( "After unique ... " );
    printf( "cv1 is: " ); printCvec( &cv1 );

    clearCvec( &cv3 );
    clearCvec( &cv2 );
    clearCvec( &cv1 );
   
    fputs( "\nPress 'Enter' to continue/exit ... ", stdout); fflush( stdout );
    getchar(); /* keep 'Window' open until 'Enter' key is pressed ... */
    return 0;
}
« Last Edit: October 09, 2016, 08:35:45 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Here is the first file, "CvecOfInt.h" ...
http://developers-heaven.net/forum/index.php/topic,2580.msg2863.html#msg2863

Note: CvecOfInt.h needs Cvec.h  ... see link below
« Last Edit: July 19, 2011, 02:32:11 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
And the second of the two files that are used above, "Cvec.h" ...
http://developers-heaven.net/forum/index.php/topic,2580.msg2862.html#msg2862
« Last Edit: July 19, 2011, 02:33:44 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
You may find that using a linked-list structure better suits some data handling ... so here is a solution to the above problem, to merge two lists into one list of unique elements, providing here, both unsorted and sorted list versions.  Note: Clist is a single link linked-list structure that emulates the C++ STL list container ... Clist tracks the head and tail, (front and end), size, if it isSorted ... and is expandable to as much memory that is available in your PC.  It also provides several ready to use functions like merge sort, insertion sort, insert in sorted order, find, erase, and unique - which is mainly what we want here.

Note: The following program needs the two files (below) named "ClistOfInt.h" and "Clist.h" in the same folder/directory ... before you compile it.

Code: [Select]
/* mergeTwoClistOfInt.c */  /* 2016-10-09 */


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

/* includes <stdio.h>, <stdlib.h>, <string.h> & myAssert and then "Clist.h" */


#include "ClistOfInt.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;
}

void enterClist( const char prompt[], Clist* cl )
{
    int i = 0, numGoodVals;
    Node myLst;
    puts( prompt ); fflush( stdout );
    do
    {
        printf( "enter integer %d: ", i+1 ); fflush( stdout );
        numGoodVals = scanf( "%d", &myLst.val );
        while( getchar() != '\n' ) ; /* flush stdin ... */
        if( numGoodVals != 1 )
        {
            printf( "Please enter only integers ...\n" );
            continue;
        }
        ++i;
        push_backClist( cl, &myLst );
    }while( more() );
}
/*
int exist( Clist* cv, int val )
{
    pNode p;
    for( p = cv->start; p != NULL; p = p->next )
    {
        if( p->val == val ) return 1;
    }
    return 0;
}
*/

void printClist( Clist* c )
{
    pNode cur = c->start;
    for( ; cur != NULL; cur = cur->next ) printf( "%d ", cur->val );
    printf( "size is %d\n", c->size );
}



int main()
{
    pNode p;
    int testVal;
    Clist c1, c2, c3;
    initClist( &c1 );
    initClist( &c2 );
    initClist( &c3 );
   
    enterClist( "Enter Clist1 ...", &c1 );
    enterClist( "\nEnter Clist2 ...", &c2 );
   
   
    /* using method ONE ... append to new list if not there already ... */
   
    for( p = c1.start; p != NULL; p = p->next )
    {
        /* if( !exist( &c3, p->val )) */
        if( !findClist( &c3, p->val ))
        {
            push_backClist( &c3, p );
        }
    }

    for( p = c2.start; p != NULL; p = p->next )
    {
        /* if( !exist( &c3, p->val )) */
        if( !findClist( &c3, p->val ))
        {
            push_backClist( &c3, p );
        }
    }

    printf( "\nc1 is: " ); printClist( &c1 );
    printf( "c2 is: " ); printClist( &c2 );
    printf( "c3 is: " ); printClist( &c3 );
   
    msortClist( &c3 );
    printf( "\nAfter msort( &c3 ) ...\n" );
    printf( "c3 is: " ); printClist( &c3 );
   
   
    /* using method TWO ... append list 2 to end of list 1, then call unique */

    c1.end->next = c2.start; /* link end of list 1 to start of list 2 ... */
    c1.end = c2.end; /* now ... update c1 end pointer */
    c1.size += c2.size; /* update size of new list 1 ... */
    c1.isSorted = 0; /* re-set isSorted flag to 0, i.e. NOT sorted ... */

    printf( "\nBefore unique, the appended list ...\n" );
    printf( "c1 is: " ); printClist( &c1 );
   
    testVal = c1.end->val; /* get a copy ... */
   
    printf( "\nTesting isortClist( &c1 ); ...\n" );
    isortClist( &c1 );
    printf( "c1 is: " ); printClist( &c1 );
   
    printf( "\nTesting find and erase %d ...\n", testVal );
    p = findClist( &c1, testVal );
    if( p ) eraseClist( &c1, p );
    printf( "c1 is: " ); printClist( &c1 );
   
   
    uniqueClist( &c1 ); /* unique will first call msort (if needed) ... */
    printf( "\nAfter unique ...\n" );
    printf( "c1 is: " ); printClist( &c1 );


    /* Note: list 2 was appended to list 1, so is cleared when list 1 cleared */
    clearClist( &c1 );
    clearClist( &c3 );
   
    fputs( "\nPress 'Enter' to continue/exit ... ", stdout); fflush( stdout );
    getchar(); /* keep 'Window' open until 'Enter' key is pressed ... */
    return 0;
}
« Last Edit: October 09, 2016, 08:41:42 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Here is the first file, "ClistOfInt.h" ...
http://developers-heaven.net/forum/index.php/topic,2582.msg2880.html#msg2880

Note: ClistOfInt.h loads in Clist.h
« Last Edit: July 19, 2011, 02:35:45 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
« Last Edit: July 19, 2011, 02:36:51 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Now ... just to round out this demo ... here are "CvecOfString.h" and "ClistOfString.h" versions ... that use readLine.h also, to emulate using C++ getline and C++ string.

Using readLine allows you to easily get dynamic memory C strings of any length (up to the max free memory of your PC) via file or (stdin) keyboard input that gets the whole line of any length up to the '\n' (newline) character or the EOF character ... which ever comes first.  (But remember to free these dynamic memory C strings when done with them ... to prevent memory leaks.  See the file "readLine.h" for more information ... and the following programs to see readLine being used to get a whole line into a dynamic memory C string ... via the keyboard.)

First, the program "mergeTwoCvecOfString.c" ... (which uses "CvecOfString.h" and "readLine.h" that follow, as well as "Cvec.h" provided above) ...

Code: [Select]
/* mergeTwoCvecOfString.c */  /* 2016-10-09 */


/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
 
#include "CvecOfString.h" /* also includes "readLine.h" that includes ...
                                                stdio.h, stdlib.h, string.h,
                                                myAssert, newCopy
                             also includes "Cvec.h"
                        */
void enterCvec( const char prompt[], Cvec* cv )
{
    int i = 0;
    Rec r;
    puts( prompt ); fflush( stdout );
    do
    {
        printf( "enter string %d: ", i+1 ); fflush( stdout );
        r.str = readLine( stdin ); /* readLine gets new dynamic memory C string */
        ++i;
        push_backCvec( cv, &r ); /* copies C string pointer into ary of pointers */
    }while( more() );
}

/*
void printCvec( Cvec* cv )
{
    int i;
    for( i = 0; i < cv->size; ++i )
        printf( "%s ", cv->ary[i].str );
}

int exist( Cvec* cv, char* s )
{
    int i;
    for( i = 0; i < cv->size; ++i )
    {
        if( strcmp(cv->ary[i].str, s) == 0 ) return 1;
    }
    return 0;
}
*/



int main()
{
    int i;
    char* testStr;
    Cvec cv1, cv2, cv3;
    initCvec( &cv1 ); /* NOTE! MUST initial Cvec for it to work ... */
    initCvec( &cv2 );
    initCvec( &cv3 );
   
    enterCvec( "Enter Cvec1 ...", &cv1 ); /* passing in a 'reference' to cv1 */
    enterCvec( "\nEnter Cvec2 ...", &cv2 ); /* i.e. passing in address ... */

   
    /* method ONE ... append only unique elements to cv3 ... */
   
    for( i = 0; i < cv1.size; ++i ) /* if element 'i' not in cv3, add it */
    {
        /* if( !exist( &cv3, cv1.ary[i].str) ) */
        if( findCvec( &cv3, cv1.ary[i].str ) == -1 )
        {
            /* NOTE!!! cv3 holds ONLY copies of pointers to C strings ...
                       i.e. holds only a 'shallow copy' of the C strings */
            push_backCvec( &cv3, &cv1.ary[i] );
        }
    }
   
    for( i = 0; i < cv2.size; ++i )
    {
        /* if( !exist( &cv3, cv2.ary[i].str) ) */
        if( findCvec( &cv3, cv2.ary[i].str ) == -1 )
        {   /* ONLY 'shallow copy' made of C string made below ... */
            push_backCvec( &cv3, &cv2.ary[i] );
        }
    }

    printf( "\ncv1 is: " );
    showCvec( &cv1 ); printf( " cv1.size = %d\n", cv1.size );

    printf( "cv2 is: " );
    showCvec( &cv2 ); printf( " cv2.size = %d\n", cv2.size );

    printf( "cv3 is: " );
    showCvec( &cv3 ); printf( " cv3.size = %d\n", cv3.size );

    msortCvec( &cv3 );
    printf( "After msort( &cv3 ) ... " );
    showCvec( &cv3 ); printf( " cv3.size = %d\n", cv3.size );

   
    /* method TWO ... get cv1 and cv2 into a large enough cv3, then call unique */
   
    reserveCvec( &cv3, cv1.size+cv2.size );
    for( i = 0; i < cv1.size; ++i )
        cv3.ary[i] = cv1.ary[i];
    for( i = 0; i < cv2.size; ++i )
        cv3.ary[cv1.size + i] = cv2.ary[i];
    cv3.size = cv1.size+cv2.size;
    cv3.isSorted = 0;
   
    puts( "\nAfter copying pointers in cv1 and cv2 to cv3 ..." );
    printf( "cv3 is: " );
    showCvec( &cv3 ); printf( " cv3.size = %d\n", cv3.size );
   
    testStr = newCopy( cv3.ary[cv3.size-1].str ); /* get new copy for future use */

    puts( "\nTesting supplied isortCvec( &cv3 ) ...\n"
          "(NOT really needed here because uniqueCvec will call msort if !isSorted)" );
    isortCvec( &cv3 );
    puts( "After isortCvec( &cv3 ) ..." );
    printf( "cv3 is: " ); showCvec( &cv3 );
    printf( "cv3.cap = %d, cv3.size = %d\n", cv3.cap, cv3.size );
   

    i = findCvec( &cv3, testStr );
    if( i != -1 ) eraseCvec( &cv3, i );
    printf( "\nTesting find %s and erase ...\n", testStr );
    printf( "cv3 is: " ); showCvec( &cv3 );
    printf( "cv3.cap = %d, cv3.size = %d\n", cv3.cap, cv3.size );

   
    uniqueCvec( &cv3 ); /* also frees dynamic memory for redundant C strings */
    puts( "\nAfter uniqueCvec( &cv3 )... " );
    printf( "cv3 is: " ); showCvec( &cv3 );
    printf( " cv3.size = %d\n", cv3.size );
   
    clearCvec( &cv3 ); /* when done, rest of dynamic C string memory is free */
   
    /* now ... just free ary memory for cv1 and cv2 ... */
    free( cv2.ary ); /* initCvec( &cv2 ); */
    free( cv1.ary ); /* initCvec( &cv1 ); // if need to reuse in program // */
   
    free( testStr ); /* and free testStr ... */

    takeInChar( "\nPress 'Enter' to continue/exit ... " );
    return 0;
}
« Last Edit: October 09, 2016, 08:46:19 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
This next file also loads in and uses the files "Cvec.h" provided above ... and "readLine.h" provided below ...

CvecOfString.h
http://developers-heaven.net/forum/index.php/topic,2580.msg2865.html#msg2865
« Last Edit: July 19, 2011, 02:38:57 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
« Last Edit: July 19, 2011, 02:41:29 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Finally, the ClistOfString version ... merging two Clists of dynamic C strings into one list of unique (dynamic) C strings ...

Code: [Select]
/* mergeTwoClistOfString.c */  /* 2016-10-09 */


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


#define DELIMITS ", "
#include "split.h" /* which includes "ClistOfString.h" that includes ...
                                        "readLine.h" which also includes ...
                                            stdio.h, stdlib.h, string.h and ...
                                            functions myAssert(..) and newCopy(..)
                      Note: "ClistOfString.h" also includes "Clist.h"
                   */


void enterClist( const char prompt[], Clist* cl )
{
    int i = 0;
    Node node;
    puts( prompt ); fflush( stdout );
    do
    {
        printf( "enter string %d: ", i+1 ); fflush( stdout );
        node.str = readLine( stdin ); /* readLine gets a new dynamic C string */
        ++i;
        push_backClist( cl, &node ); /* copies new C string pointer into pointer ary */
    }while( more() );
}
/*
void printClist( Clist* cl )
{
    pNode cur = cl->start;
    for( ; cur != NULL; cur = cur->next )
        printf( "%s ", cur->str );
}

int exist( Clist* cl, char* s )
{
    pNode cur = cl->start;
    for( ; cur != NULL; cur = cur->next )
    {
        if( strcmp(cur->str, s) == 0 ) return 1;
    }
    return 0;
}
*/



int main()
{
    char* testStr;
    pNode p, tmp;
    Clist c1, c2, c3;
    initClist( &c1 ); /* NOTE! MUST initial Clist for it to work ... */
    initClist( &c2 );
    initClist( &c3 );
   
    enterClist( "Enter Clist1 ...", &c1 ); /* passing in a 'reference' to cv1 */
    enterClist( "\nEnter Clist2 ...", &c2 ); /* i.e. passing in address ... */

   
    /* method ONE: append to new list if NOT present there already ... */
   
    for( p = c1.start; p != NULL; p = p->next )
    {
        /* if( !exist( &c3, p->str )) */
        if( !findClist( &c3, p->str )) /* if element not in c3, add it */
        {
            /* NOTE!!! cv3 holds ONLY copies of pointers to C strings ...
                       i.e. holds only a 'shallow copy' of the C strings */
            push_backClist( &c3, p );
        }
    }

    for( p = c2.start; p != NULL; p = p->next )
    {
        /* if( !exist( &c3, p->str ) ) */
        if( !findClist( &c3, p->str ) )
        {   /* ONLY 'shallow copy' made of C string made below ... */
            push_backClist( &c3, p );
        }
    }

    printf( "\nc1 is: " );
    showClist( &c1 ); printf( " c1.size = %d\n", c1.size );

    printf( "c2 is: " );
    showClist( &c2 ); printf( " c2.size = %d\n", c2.size );

    printf( "c3 is: " );
    showClist( &c3 ); printf( " c3.size = %d\n", c3.size );

    msortClist( &c3 );
    printf( "After msort( &c3 ) ...\nc3 is: " );
    showClist( &c3 ); printf( " c3.size = %d\n", c3.size );

   
    /* Method TWO ... append list 2 to end of list 1 and then call unique */
   
    c1.end->next = c2.start;
    c1.end = c2.end;
    c1.size = c1.size + c2.size;
    c1.isSorted = 0;
    printf( "\nAfter appending c2 to the end of c1:\nc1 is: " );
    showClist( &c1 ); printf( " c1.size = %d\n", c1.size );

    testStr = newCopy( c1.end->str );
    isortClist( &c1 );
    printf( "\nAfter isortClist:\nc1 is: " );
    showClist( &c1 ); printf( " c1.size = %d\n", c1.size );

    printf( "\nAfter calling find %s and erase:\nc1 is: ", testStr );
    p = findClist( &c1, testStr );
    if( p ) eraseClist( &c1, p ); /* clears dynamic C string AND list memory */
    showClist( &c1 ); printf( "c1.size = %d\n", c1.size );

   
    uniqueClist( &c1 ); /* clears redundant dynamic C string AND list memory */
    printf( "\nAfter calling unique, new list:\nc1 is: " );
    showClist( &c1 ); printf( " c1.size = %d\n", c1.size );
   
    printf( "\nAfter calling joinClist( &c1, \", \" ),\n" );
    testStr = joinClist( &c1, ", " ); /* testStr is in NEW dynamic memory */
    printf( "The joined testStr is: \n%s\n", testStr );
   
   
    clearClist( &c1 ); /* also frees all dynamic memory that was in list 2 */

    /* NOW ... JUST free here the list memory for c3 ... */
    for( p = c3.start; p != NULL; p = tmp )
    {
        tmp = p->next;
        free( p );
    }
    /* Note: if need to use c3 again, then need to first call initClist( &c3 ) */
   
    printf( "\nAfter calling split( &c1, testStr ),\nc1 is: " );
    split( &c1, testStr ); /* makes a list of NEW dynamnic strings */
    showClist( &c1 ); printf( " c1.size = %d", c1.size );
   
    clearClist( &c1 );
    free( testStr );

    takeInChar( "\nPress 'Enter' to continue/exit ... " );
    return 0;
}

Note: this program needs the two files, "split.h" and "ClistOfString.h", provided below, as well as the two files, "readLine.h" and "Clist.h" provided above ...
« Last Edit: October 09, 2016, 09:13:38 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
These files, "split.h" and "ClistOfString.h" are used by the the above program that merges two Clists of C strings ...

(Note: the file "split.h" loads "ClistOfString.h" that then loads/uses "readLine.h" and "Clist.h" provided above.)

First, "split.h" ...
http://developers-heaven.net/forum/index.php/topic,2584.0.html

And "ClistOfString.h" ...
http://developers-heaven.net/forum/index.php/topic,2582.msg2882.html#msg2882


Click here for some  example programs that use CvecOfString and ClistOfString  ...
http://developers-heaven.net/forum/index.php/topic,2022.msg2676.html#msg2676

Please click on the little  Pages: 2  icon in the lower left area of this page to continue ...
« Last Edit: July 19, 2011, 03:20:44 AM by David »