Jump to content
Larry Ullman's Book Forums

Necuima

Members
  • Posts

    359
  • Joined

  • Last visited

  • Days Won

    7

Posts posted by Necuima

  1. Hi,

     

    I could not get script 6.2 (address.cpp) or script 6.3 (pointers1.cpp) to print out the addresses in my Dev-C++ IDE. The typecasting gave compiler errors in both cases.

     

    The following worked for me courtesy Mr Google and Stack Overflow:

    #include <cstdlib>
    #include <iostream>
    #include <sstream>
    
    int main() {
    
    	// Create some variables and pointers.
    	int a = -12;
    	int *addr_of_a = &a;
    	unsigned long ul;   
            std::stringstream ss;
    	
    	// Print the address of a.
    	std::cout << "The address of a is "
    	<< addr_of_a << std::endl;  // hex value
    	
        ss << std::hex << addr_of_a;
        ss >> ul;
        std::cout << "The address of a is " << static_cast<unsigned long>(ul) << std::endl;  // decimal value
      
    std::cout << "Press Enter or Return to continue.\n";
    	std::cin.get();
    
    	return 0;
    	
    } // End of the main() function.
    
    I checked and the conversion from hex to decimal was correct.

     

    Cheers from Oz.

     

    P.S., my environment is Windows 7, 64 bit with Dev-C++ 5.8.3

  2. OK, got it but I don't really understand why!!

     

    Just had to add "return" to:

     

    if ( rc < 0 )
         {
              // If the word occurs, it must be in the left subtree.
            return treeContains( root->left, a_word ); //******************added 'return' *************************************************
         }
         else
         {
              // If the word occurs, it must be in the right subtree.
           return treeContains( root->right, a_word ); //******************added 'return' *************************************************
         }
    

    in the treeContains function.

     

    If anyone can explain this to me I will appreciate it a lot.

     

    Cheers from Oz.

     

    P.S., the C++ binary tree works fine now :-)

  3. Hi,

     

    On page 432, Larry mentions binary trees as good containers for data in certain circumstances.

     

    Having recently created a small C program which implemented a binary tree, I am now trying to replicate that in C++.  But I am having an issue that I can't find the answer to in other forums so I'm wondering if someone can guide me in this case. 

     

    Here's extracts of my code:

    using std::string; // rather than using the whole std namespace
    
    struct TreeNode
    {
        // A structure of type TreeNode represents one node in a binary tree of words.
       string the_word;     // The word in this node.
       int counter;     // The count of the number of times this word was read from the input file
       TreeNode *left;     // Pointer to left subtree.
       TreeNode *right;    // Pointer to right subtree.
       TreeNode(string str = "")
         {
               // Constructor, defined for convenience.
               // Make a node containing the specified word.
            the_word = str;
            counter = 1;
            left = NULL;
            right = NULL;
         }
    };  // end struct TreeNode
    
    ...... intervening code OK to here - now I want to see if the word is in the tree already
     
    TreeNode * root = NULL;
    TreeNode * tmp;
     
     tmp = treeContains(root, word_list[i]); // tests to see if the word is already in the tree
            std::cout << "tested word was " << word_list[i] << ", tmp is " << tmp << std::endl;
    ************************* tmp not being set as NULL when it should be??????????????????
            if (tmp == NULL)
             { // The word is not in the tree - add it
              treeInsert(root, word_list[i]);
              std::cout << "After inserting a node for " << word_list[i] << ", root is " << root << std::endl;
              word_count++;
          }
         else
          { // the word is in the tree - increment its counter
           tmp->counter += 1;
          }
     
    ....... after the search via TreeContains, tmp is not showing zero or null when it should be (it does show the correct tree node address if a match is found)
     
    ................
     
    TreeNode * treeContains( TreeNode *root, string a_word )
    { std::cout << "Entering treeContains, root is " << root << ", a_word is " << a_word << std::endl;
       // Return the address of the node if the word is one of the words in the binary tree
       if (root == NULL)
       {
             // This sub-branch of the tree is empty, so it certainly doesn't contain a_word.
             // This will also pick up the NULL when the tree is totally empty.
          std::cout << "treeContains indicates that root is NULL for " << a_word << std::endl;  
          return NULL;     ********************************************************************************************
       }
       else if ( a_word == root->the_word )
       {
             // Yes, the word has been found in the node currently being examined.
          return root;
       }
       else
        { 
         int rc = 0;
      rc = caseicompare(a_word, root->the_word); // case insensitive string compare
      std::cout << "Comparing " << a_word << " with " << root->the_word << " in treeContains, rc is " << rc << std:: endl;
         if ( rc < 0 )
         {
              // If the word occurs, it must be in the left subtree.
            treeContains( root->left, a_word );
         }
         else
         {
              // If the word occurs, it must be in the right subtree.
           treeContains( root->right, a_word );
         }
     }
      
    }  // end treeContains()
    

    The ************** line of code above is either not returning NULL properly or I am not invoking the call to the treeContains function properly.

     

    My environment is Windows 7, 64 bit with Dev-C++ as the IDE.

     

    Any advice will be most appreciated and thank you in anticipation.

     

    Cheers from Oz.

  4. Hi Larry,

     

    As per your "Tips" on page 351, I found the binary tree suggestion in the 4th bullet point a really good one to get a better understanding of  memory management as well as using recursion in C.

     

    Thanks for the suggestion.

     

    My little program reads in a text file with some words in it, parses out the words and then adds them to a binary tree stored in alphabetic word order.  If the word is already in the tree, it adds to a counter of that word; if it is not in the tree it adds it and sets the count for that word to one.

     

    At the end of the file, the program prints out the words in the tree in alphabetic order plus the word counts and then deletes all the nodes of the tree.

     

    I found this exercise to be a great one in the spirit of 'revue and pursue'.

     

    Cheers from Oz.

  5. OK, I found my error. In my sort where I compare the two words, I was not following Larry's example properly.  The strcmp should not be comparing the words directly from the array, but the words pointed to by the pointers.

     

    The correct comparison in my example is:

    temp_1 = *ws_pointers[l];
    
    temp_2 = *ws_pointers[m];
    
    rc = strcasecmp(temp_1.the_word, temp_2.the_word); // the compare ignores the case
    ...
    

    And I changed it to a case insensitive compare.

     

    Thanks to anyone who looked at this and pondered on a solution.

     

    Cheers from Oz.

  6. Hi,

     

    I am developing a variation of Larry's script 11.6 and am having trouble understanding how to apply the pointers bubble sort in my context.

     

    In a nutshell, my application reads in lines of ordinary text from a small .txt file I created.  I then read the file line by line and then parse each line for words.  I store the words in a struct:

    /* Define the structure. */
    
    struct word_store
    
    {
    
     char the_word[WORD_SIZE];
    
     int counter;
    
     struct word_store *next;
    
     struct word_store *previous;
    
    };
    
     
    
    /* Use typedef to create an alias. */
    
    typedef struct word_store ws;
    

    At the moment I am not using the two pointers in the struct but I will want to use them later as I want to extend this to use a b-tree to store an array of these struct elements.

     

    If the word from the line parse is already in the struct array, I increment the counter for that word; if it is not, then I add the word to the struct array with a counter value of one and add an address pointer to the array element in an array of these pointers.

     

    All this works fine.

     

    But when I have finished reading and parsing, I want to sort the words alphabetically and I'm trying to adapt the pointer sort example starting on page 281.

     

    But the words are not getting sorted properly and I'm wondering if my strcmp is not giving me the result I expect when I compare, for example, the words 'a' and 'and'. Here's my code:

    for (l = 0; l < (store_index - 1); l++)
    
      { // loop through each word in the store
    
       for (m = (l + 1); m < store_index; m++)
    
       { // loop through each word again
    
        if (strcmp(word_array[l].the_word, word_array[m].the_word) > 0)
    
         { // if the result is > 0, word_arry[m].the_word should come before word_array[l].the word so we need to swap their pointers
    
          temp_pointer = ws_pointers[l];
    
          ws_pointers[l] = ws_pointers[m];
    
          ws_pointers[m] = temp_pointer;
    
         } // end if
    
       } // end inner loop
    
      } // end outer loop
    
      
    
      printf("The words stored and their frequency are:\n");
    
      for (j = 0; j < store_index; j++)
    
      {
    
       // get the next word and put it into hold_it
    
       hold_it = *ws_pointers[j];
    
       printf("%s (%d)\n", hold_it.the_word, hold_it.counter);
    
      }
    

    where store_index holds the count of the number of struct elements in the array.

     

    The pointers are declared as:

    ws word_array[ARRAY_SIZE]; // ARRAY_SIZE is defined in defws.h
    
     ws *ws_pointers[ARRAY_SIZE]; // an array of pointers to ws typedefs (word_store structs)
    
     ws *temp_pointer;
    
     ws hold_it;
    

    The supposedly sorted words are not printing in alphabetic order.

     

    My environment is Windows 7 with Dev-C++ as the IDE.

     

    Any advice will be most appreciated and thanks in anticipation.

  7. Welcome to the forum.

     

    To enable you to be better assisted, can you please let us know the computing environment within which you are trying this and also at least the portion of the code that you are trying to execute.

     

    Also, I presume that you have set up the tasks table in the test database? (as per page 9 of the book).  Are there any records in the tasks database table?

     

    I have found that this tasks exercise is an excellent one so good luck.

     

    Cheers.

  8. Ok, I've got the solitary enter bit sorted as per:

    /* Get up to NUM_STRINGS words. */
    
     for (i = 0; i < NUM_STRINGS; ++i)
    
     {
    
      /* Prompt and read in a word. */
    
      printf("Enter a word up to %d characaters in length (or 0 or 'enter' to quit): ", STR_LEN-1);
    
      fgets(input, STR_LEN-1, stdin);
    
      discard_input();
    
        //  Now test for a solitary newline character or a zero
    
          if ((((p = strchr(input, '\n')) != NULL) && strlen(input) == 1) || input[0] == '0')
    
            { // i.e., the characater entered was a solitary keyboard 'enter' or a zero
    
             break;
    
     // now replace the new line character with an end of string zero (\0)
      if ((p = strchr(input, '\n')) != NULL)
            *p = '\0';  }
    
      strncpy(words[i], input, (STR_LEN - 1));
    
         count++;
    
       }
    

    Where p is declared as char *p; But now I have to hit 'enter' twice to progress to the request for the next input.  I'll keep trying!!

     

    Cheers.

  9. Mmmm, I think "the penny just dropped".  This is an expression used here in Oz to indicate that you just realised something that you should have realised before.  I wonder if the expression is used in North America?

     

    It seems that the scanf is just ignoring my keyboard 'enters' and is still waiting for some input that it is prepared to accept.  Which is why it never gets to the following printf.  And also why it will accept a word even after several 'enter's. And once it receives a word, then the printf 'fires'.

     

    Which still leaves my query open that I hope someone can help me with - is there a way to test for a keyboard enter in the context of this code?

     

    Thanks again.

  10. I think that I now understand why my test for a return code from scanf does not work.

     

    Here's my code:

     /* Get up to NUM_STRINGS words. */
    
     for (i = 0; i < NUM_STRINGS; ++i) {
    
      
    
      /* Prompt and read in word. */
    
      printf("Enter a word (or 0 to quit): ");
    
      
    
      rc = scanf("%9s", input);
    
      printf("The return code from scanf is %d\n", rc);
    ...
    ...
    ...
    

    The retrun code (rc) printf does not show at all if all I enter is 'enter' at the scanf. And on page 87 Larry says that scanf will not work "if the function encounters input that does not match the formatting signifier...".  But I still don't understand why the printf would not show anything?

     

    Again, any advice will be most appreciated.

     

  11. Hi Larry,

     

    I am up to page 277, script 11.5 called copy.c.

     

    I am interested how you could test for just a keyboard 'enter' as well as testing for a zero (about code line 30).  I have Googled a bit but nothing seems to work. 

     

    I have tried testing the scanf return code but I can't seem to get that to work either.

     

    I am using a relatively recent version of Dev-C++ as the IDE in Windows 7 64 bit.

     

    Any help will be most appreciated.

     

    Thanks, and cheers from Oz.

  12. Hi Larry,

     

    Well your C book finally arrived down here in the antipodes:-)  And I'm enjoying going through it a lot.  It is helping to clarify some mis-conceptions that I had.

     

    On page 146, the first line in fact, you have a signifier %lu but the downloaded code has %llu. Is this a minor errata or am I seeing double??

     

    I checked the book errata but it's not there.

     

    Thanks again for a great book.

     

    Cheers from Oz.

     

     

     

     

  13. Hi Larry,

     

    With Visual C++ and creating a Windows form, you can access the local (Windows) file system using the .NET capability.  I don't know if the form bit is necessary but that's how I managed to do it (just recently).

     

    I don't know that this approach can be used on non-Windows system but I suspect not.

     

    Cheers from Oz.

  14. Hi, in Larry's book PHP Advanced and OO Programming, there is a great structure set out which covers this in chapter 2. I think that it is also in the PHP5 Advanced book too. In a nutshell, his modularised approach includes a config.inc.php module which sets up some constants and variables, one of which indicates whether you are running in a development environment or a production environment. This variable ($local) is a Boolean which is set to either true or false. When an error message is to be displayed, a test is made against this Boolean so you can vary the message displayed accordingly.

     

    Hope it helps. Cheers.

  15. Hi,

     

    This is another of my 'lessons learned' posts that may be of use to someone attempting a similar endeavour.

     

    After countless hours and a lot of help, I have managed to get an AIR Native Extension incorporating simple Image Magick functionality working.  Although, so far at least, I have not achieved my ultimate objective, I do have an AIR native extension incorporating simple Image Magick functionality working on my PC.

     

    The 'ultimate objective' was to create a Windows exe file/application which could be installed on anyone's PC without the need for that PC to have Image Magick also installed - that has so far eluded me, but if that PC has Image Magick installed in the manner necessary, then the application will indeed work on another PC.

     

    The basic development process is as follows:

     

    1) build a dll which has both Image Magick and AIR native extension connectivity (I used MS Visual C++ 2010 Express Edition as my IDE).

    2) build a library (I used Flash Builder 4.6) incorporating a class and then from that build an ane file.

    3) build a Flash Builder AS3/Flex project to use the functionality developed in steps 1 and 2 which incorporates the ane file from step 2.

     

    Detailed guidance for the AIR bits can be found at http://easynativeextensions.com/windows-tutorial-introduction/ which did not exist when I started this endeavour but many thanks to Radoslava Leseva for her invaluable help in this bit.

     

    I used the Wand interface to Image Magick and guidance on that can be found at http://members.shaw.ca/el.supremo/MagickWand/ and http://www.imagemagick.org/discourse-server/viewtopic.php?t=11757

     

    The application, via a simple user interface (UI - step3), allows the user to select a jpg image file for downsizing.  The UI also requests a new pixel size parameter as well as a jpg quality/compression factor.

     

    The class (step 2) has an instance constructor and a method.  The UI calls the method passing it the full path name of the jpg image file to be downsized as well as the size and quality parameters.  The method then calls a resize function in the dll which in turn uses the Image Magick Wand interface to do the actual resizing.

     

    I know that there are easier ways to downsize a jpg image but I wanted to learn how to develop an AIR native extension!

     

    I am impressed with the quality of the downsized images.  As a test I downsized an 18Mb high quality image to a file about 150Kb in size and on my 24 inch screen I cannot detect any reduction in the visual quality of the image.  That of course is due to the Image Magick functionality.

     

    I hope that this may be of help to someone!

     

    Cheers from Oz.

  16. Hi,  I thought that I'd post another of my 'lessons learned' - this time interfacing between a C++ dll (though I suppose it doesn't need to be a dll) and Image Magick. 

     

    After much Googling it seems that there are 3 ways for a C++ program to invoke Image Magick functionality:

     

    1) via the 'core' C API

    2) via Magick++

    3) via Wand

     

    In my case I only wanted basic Image Magick functions.  I eventually found a nice simple example which showed the difference between approach 1) and approach 3).  Approach 3 - i.e., via Wand was far simpler.

     

    I could not get approach 2 to work for me at all but I'm sure that someone knowledgeable could.

     

    So I proceeded to experiment with the Wand interface.

     

    I am using Visual C++ 2008 Express Edition as my IDE.  There is some very good advice re the settings that you need to make in the IDE so that the compiler and linker can find the files they need - see http://www.imagemagick.org/discourse-server/viewtopic.php?t=11757 and in particular el_supremo's post dated 2008-07-26T08:05:28-07:00.

     

    My C++/Wand code just reads in a jpg image file, sets size and quality parameters and then writes the resized file out with its new size and quality and a new file name, all using Wand methods.

     

    It took me about 3 weeks and hundreds of Google searches to get to this outcome, or maybe I'm just a slow learner :-)

     

    Cheers from Oz.

  17. I use XAMPP too. I don't think that the version of PHP is an issue (FYI I use version 5.5.3 which came with the XAMPP that I installed about a year ago). What is an issue if you want to use the PHP Imagick dll is the version synchronisation between the dll and Image Magick installed on your PC.

     

    I.e., for the PHP dll to work you also have to have the version-aligned ImageMagick installed.

     

    So my suggestion is to try the windows installation exe as per above which will install ImageMagick on your PC. Then to use ImageMagick functionality in PHP you must separately install the version-aligned php_imagick.dll and 'tell' PHP about it.

     

    I specifically had to go back to the installation exe "ImageMagick-6.8.6-9-Q16-x86-dll.exe" (you may be able to find that specific version with a Google search). That version aligned with the php_imagick.dll file that I had for PHP. I think that that dll is still available by extracting it from the Imagick PECL install from the 'Net.

     

    I'll be interested to hear how you get on.

     

    It's now night time here in Oz so I'll sign off for tonight and check the forum tomorrow.

     

    Cheers from Oz.

×
×
  • Create New...