{"id":6788,"date":"2025-02-01T00:01:03","date_gmt":"2025-02-01T08:01:03","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=6788"},"modified":"2025-01-11T10:06:50","modified_gmt":"2025-01-11T18:06:50","slug":"finding-structures-with-the-bsearch-function","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=6788","title":{"rendered":"Finding Structures with the <em>bsearch()<\/em> Function"},"content":{"rendered":"<p>It&#8217;s easy to explain the <em>bsearch()<\/em> function when using integers. One step up is to search for strings, covered in <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6779\">last week&#8217;s Lesson<\/a>. At the pinnacle of insanity, however, is searching through an array of structures.<br \/>\n<!--more--><br \/>\nThe <em>bsearch()<\/em> function locates a structure based on one of its members. The issues are setting the key as a structure (something I had to figure out), and coding the <em>compare()<\/em> function to properly manipulate the structures.<\/p>\n<p>To test the function, I use this structure, <em>potus<\/em>:<\/p>\n<p><code>struct potus {<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;int index;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;char *name;<br \/>\n};<\/code><\/p>\n<p>And this array of <em>potus<\/em> structures, named <code>presidents[]<\/code>:<\/p>\n<p><code>struct potus presidents[] = {<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;{ 1, \"Washington\" }, { 2, \"Adams\" }, { 3, \"Jefferson\" },<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;{ 4, \"Madison\" }, { 5, \"Monroe\" }, { 6, \"Adams\" }<br \/>\n};<\/code><\/p>\n<p>You can search this array for any member of the structure &mdash; but only one member. You cannot search for an entire structure as they must be sorted. In a database, sorting is based upon a specific key. For this example, I&#8217;m sorting based on the <code>name<\/code> string. Even so, the search key must be another structure; it cannot be a string by itself.<\/p>\n<p>The following code shows how to search for a specific structure based on its <code>name<\/code> (string) member.<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2025_02_01-Lesson.c\" rel=\"noopener\" target=\"_blank\">2025_02_01-Lesson.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;string.h&gt;\r\n\r\nstruct potus {\r\n    int index;\r\n    char *name;\r\n};\r\n\r\nint compare(const void *a, const void *b)\r\n{\r\n    char *name1 = ((struct potus *)a)-&gt;name;\r\n    char *name2 = ((struct potus *)b)-&gt;name;\r\n    return( strcmp(name1,name2) );\r\n}\r\n\r\nint main()\r\n{\r\n    struct potus presidents[] = {\r\n        { 1, \"Washington\" }, { 2, \"Adams\" }, { 3, \"Jefferson\" },\r\n        { 4, \"Madison\" }, { 5, \"Monroe\" }, { 6, \"Adams\" }\r\n    };\r\n    struct potus *r,*key;\r\n    char input[32];\r\n    int size;\r\n\r\n    <span class=\"comments\">\/* obtain array size *\/<\/span>\r\n    size = sizeof(presidents)\/sizeof(presidents[0]);\r\n\r\n    <span class=\"comments\">\/* obtain input *\/<\/span>\r\n    printf(\"President: \");\r\n    scanf(\"%s\",input);\r\n    <span class=\"comments\">\/* the key must be a structure to match\r\n       the index member need not be set *\/<\/span>\r\n    <span class=\"comments\">\/* allocate storage for both the structure\r\n       as well as the name *\/<\/span>\r\n    key = malloc( sizeof(struct potus) );\r\n    key-&gt;name = malloc( sizeof(char) * 32 );\r\n    if( key== NULL || key-&gt;name==NULL )\r\n    {\r\n        fprintf(stderr,\"Unable to allocate structure\\n\");\r\n        exit(1);\r\n    }\r\n    strcpy(key-&gt;name,input);\r\n\r\n    <span class=\"comments\">\/* sort the list *\/<\/span>\r\n    qsort(presidents,size,sizeof(struct potus),compare);\r\n\r\n    <span class=\"comments\">\/* locate a value *\/<\/span>\r\n    r = bsearch( key, presidents, size, sizeof(struct potus), compare );\r\n    if( r!=NULL )\r\n        printf(\"Key %s found!\\n\",r-&gt;name);\r\n    else\r\n        printf(\"Key %s not found.\\n\",key-&gt;name);\r\n\r\n    return 0;\r\n}<\/pre>\n<p>The array&#8217;s size is obtained by dividing the total array size, <code>sizeof(presidents)<\/code>, by the size of a single member, <code>sizeof(presidents[0])<\/code>:<\/p>\n<p><code>size = sizeof(presidents)\/sizeof(presidents[0]);<\/code><\/p>\n<p>The next step is to allocate the <code>key<\/code> structure, which is the same type of structure used in the array. Also &mdash; and this is important &mdash; the <code>name<\/code> member of the structure must also be allocated:<\/p>\n<p><code>key = malloc( sizeof(struct potus) );<br \/>\nkey-&gt;name = malloc( sizeof(char) * 32 );<\/code><\/p>\n<p>(An issue might exist if the <code>key<\/code> allocation fails before trying <code>key-&gt;name<\/code>. In my example I test both together, though they should be tested separately to create more secure code.)<\/p>\n<p>Once allocated, user input (stored in variable <code>input<\/code>) is copied into the <code>key<\/code> structure&#8217;s <code>name<\/code> member:<\/p>\n<p><code>strcpy(key-&gt;name,input);<\/code><\/p>\n<p>You need not assign a value to the <code>index<\/code> member as it&#8217;s unused, so whatever garbage in memory is okay.<\/p>\n<p>Next the <em>qsort()<\/em> function sorts on the array based upon the <code>name<\/code> member. The <em>compare()<\/em> function uses two local pointers to obtain the name strings, then the <em>strcmp()<\/em> function is used in the <em>return<\/em> statement to cough up the results:<\/p>\n<p><code>char *name1 = ((struct potus *)a)-&gt;name;<br \/>\nchar *name2 = ((struct potus *)b)-&gt;name;<br \/>\nreturn( strcmp(name1,name2) );<\/code><\/p>\n<p>Finally, <em>bsearch()<\/em> is called. But note that no ampersand prefixes the <code>key<\/code> argument as it&#8217;s already an address:<\/p>\n<p><code>r = bsearch( key, presidents, size, sizeof(struct potus), compare );<\/code><\/p>\n<p>Here&#8217;s a sample run:<\/p>\n<p><code>President: Jefferson<br \/>\nKey Jefferson found!<\/code><\/p>\n<p>As I wrote earlier, it took me a while to figure out that the first argument in the <em>bsearch()<\/em> function must be of the same data type (the <em>potus<\/em> structure) as the items in the array. I tried using a string again and again, but the program crashed merrily. Only when I looked at the <em>compare()<\/em> function did I realize that the data types must match for the code to run successfully.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Things can get crazy fast when searching through an array of structures. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6788\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-6788","post","type-post","status-publish","format-standard","hentry","category-main"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6788","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6788"}],"version-history":[{"count":6,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6788\/revisions"}],"predecessor-version":[{"id":6814,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6788\/revisions\/6814"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6788"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6788"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6788"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}