I don't know how to explain this in debug

  • Thread starter yungman
  • Start date
  • Tags
    Explain
In summary, the conversation discusses a program that adds names to a vector and sorts them in ascending order. The conversation also mentions a specific issue where a conditional statement does not work as expected. The conversation ends with a suggestion to check various components, such as the vector and strings, to see if they are properly initialized and allocated.
  • #1
yungman
5,718
241
I run into something strange when I step through debug. This is the program to add names one by one, and each name entered, it will sort and put in ascending order into vector DirV[]. I cannot explain why the if statement in line 51 doesn't work.

First name I enter is just 'r', I just put a single digit number for the phone eg. 5. Second name is 'e', third name is 't'.

C++:
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const static int nameLen = 25, phoneLen = 12;
struct Directory { char name[nameLen];    char phone[phoneLen]; };
std::vector<Directory>DirV;
Directory Dir;
int main()
{
  char more, displayAll;
  void add_sort();
  do
   { cout << " Enter name:  "; cin.getline(Dir.name, nameLen);
     cout << " Enter phone:  "; cin.getline(Dir.phone, phoneLen);
     add_sort();
     cout << " Do you want to enter another name?  "; cin.get(more);
     cin.ignore();
   } while (tolower(more) == 'y');
  int index = 0;
  do
   { cout << "Name stored in DirV is:  " << DirV[index].name <<
            " phone:  " << DirV[index].phone << "\n\n";
     index++;
   } while (index < DirV.size());
  return 0;
}

void add_sort()
{
  int size, element = 0;
  int startPt = 0, midPt, endPt;
  DirV.push_back(Dir);//Push to next available element of DirV.
  size = DirV.size();
  if (size > 1)//if size = 1, it's done
   { endPt = size - 2; midPt = (startPt + endPt) / 2;//endPt is last element before push_back
     do//loop until startPt = midPt = endPt.
     { if (Dir.name > DirV[midPt].name)//next loop startPt = midPt + 1
        { startPt = midPt + 1; midPt = (startPt + endPt) / 2; }
        else { endPt = midPt; midPt = (startPt + endPt) / 2; }//next loop endPt = midPt
     } while (startPt != endPt);//Repeat until startPt = midPt = endPt

     if(midPt == size - 2)// if midPt is the last original element.
        {
          if (Dir.name < DirV[midPt].name)
           { DirV[size - 1] = DirV[midPt]; DirV[midPt] = Dir; }
          else { DirV[endPt] = Dir; }
        }
     else//midPt < (size - 2)
      {
         if (DirV[midPt].name > Dir.name)
           {//Dir fit into DirV[midPt] if DirV[midPt].name > Dir.name
            //Move DirV[midPt] to DirV[size-2] down one element
               for( int ind = 1; ind < (size - midPt - 2); ind++)
                 { DirV[size - ind] = DirV[size - ind - 1]; }     
               DirV[midPt] = Dir;
           }
         else
         {//DirV[midPt].name <= Dir.name, DirV[midPt+1] = Dir
          //Move DIrV[midPt+1 to DirV[size-2] down one element.
             for (int ind = 1; ind < (size - midPt - 3); ind++)
              {  DirV[size - ind] = DirV[size - ind - 1];}
             DirV[midPt] = Dir;
         }
      }
   }// end if(size > 1)
}// end of add_sort

I put break point at line 51. This will break only after I enter the third name 't'. I verified after the program stopped at line 51 using immediate window. Dir.name='t', and DirV[midPt]='e'. Line 51 is if(DirV[midPt].name > Dir.name) which should be FALSE. The program should jump to line 61. BUT instead, it goes to line 54 as if it's TRUE!

I don't know what to make of it, I must be missing something. Please take a look.

Thanks
 
Last edited by a moderator:
Technology news on Phys.org
  • #2
What was the value of midpoint?

When I look at failing statements like this in Java I look at these components:
- DirV - is it null or a bad-pointer?
- midPt - is the value within the range of 0<= midPt < length of the array ?
- DirV[midPt] - does the DirV[midPt] string look okay or is it not initialized or not what you expect?
- Dir - is it null or a bad-pointer?
- Dir.name - is the string what you expect?

I saw where you defined the DirV structure and used char name[namelen] but in your code I don't see any strcpy of Dir.name to that string? I also saw where you assign Dir to DirV but never allocate new space for Dir. This means that DirV will contain the pointer to Dir and since you didn't allocate new space every entry in DirV will point to the same Dir and will all get changed when you change the contents of Dir.

https://www.geeksforgeeks.org/strcpy-in-c-cpp/

Does that make sense?

Line 38 I see where you're doing a string compare which is really comparing pointers and not the strings.

http://www.cplusplus.com/reference/string/string/compare/
 
Last edited:
  • Like
Likes bikashdaga and sysprog
  • #3
yungman said:
I put break point at line 51. This will break only after I enter the third name 't'. I verified after the program stopped at line 51 using immediate window. Dir.name='t', and DirV[midPt]='e'. Line 51 is if(DirV[midPt].name > Dir.name) which should be FALSE. The program should jump to line 61. BUT instead, it goes to line 54 as if it's TRUE!
@jedishrfu hints at what your problem is.

In line 51, Dir.name is NOT 't', and DirV[midPt].name is NOT 'e'. Both Dir.name and DirV[midPt].name are arrays of type char, which really means they are pointers. In your comparison if (Dir.name < DirV[midPt].name), what you are comparing are the two addresses, not the characters at these addresses.
 
  • Like
Likes jim mcnamara, sysprog, Vanadium 50 and 1 other person
  • #4
When the breakpoint at line 51 is hit, the Autos window shows the values of Dir.name and DirV[midPt].name - 0x006542d8 and 0x00fb6a90, respectively. The first address is smaller than the second address, so the if clause is executed.
The value of Dir.name, 0x006542d8, is the address of the first character in the string - 'm'. The value for DirV[midPt].name, 0x00fb6a90, is the address of the first character in that string - 'j'. The comparison is on the addresses, not the characters at those addresses. If you want to compare two C-strings, you should use a standard library function such as strcmp(), in the header file cstring.
debug.png
 
  • Like
Likes sysprog, yungman and jedishrfu
  • #5
Mark44 said:
When the breakpoint at line 51 is hit, the Autos window shows the values of Dir.name and DirV[midPt].name - 0x006542d8 and 0x00fb6a90, respectively. The first address is smaller than the second address, so the if clause is executed.
The value of Dir.name, 0x006542d8, is the address of the first character in the string - 'm'. The value for DirV[midPt].name, 0x00fb6a90, is the address of the first character in that string - 'j'. The comparison is on the addresses, not the characters at those addresses. If you want to compare two C-strings, you should use a standard library function such as strcmp(), in the header file cstring.
View attachment 272051
Wow Thanks

I did not know that
! I think of vector as array. Funny that it just happen to sort the first two ( r and e) correctly by the address.

This is the simplified version of adding and sorting for my main Directory program. I was going to use the conventional Selection Sort or Bubble Sort, but I was thinking if I add names one by one, I can sort on the spot and the vector is already sorted...And besides, what is the challenge copying the sorts from the book!

You guys still use Flow Chart? Back in the days, I was told draw the flow chart first. I spent two days on that, it did not work that well. I finally wrote out what I want to do in English yesterday, wrote out steps I want to do. That became a lot clearer and easier to implement. What is the correct way to design a program now a days?

Thanks
 
  • #6
yungman said:
You guys still use Flow Chart?
No. Most textbooks use pseudocode, which is not very strictly defined.
yungman said:
I finally wrote out what I want to do in English yesterday, wrote out steps I want to do. That became a lot clearer and easier to implement. What is the correct way to design a program now a days?
Writing the steps out in English, with some sort of notation to represent loop repetition and if-then-else logic is preferred by most.
 
  • Like
Likes sysprog, Vanadium 50 and yungman
  • #7
There is no correct way. Flowcharts are useful for some small projects but become untenable for larger ones. There were other kinds of flow diagrams but again they don’t work well with larger programs.

Also as teams develop the code, they tend not to update any associated docs as programmers are supposed to just read the code to figure out what’s going on. There are often written or unwritten coding conventions that folks follow learned by looking at what was done in the program or by personal experience. Python has coding guidelines that IDEs will invoke marking places where you’re not in compliance.

Personally, I’ve always liked the UML sequence diagram as a means of explaining my program at a high level where messages are exchanged between different objects.

https://creately.com/blog/diagrams/sequence-diagram-tutorial/
 
  • Like
Likes sysprog and yungman
  • #8
I am still on the DirV[midPt].name issue. There is a member function at(). I change to
Code:
if(Dir.name > DirV.at(midPt).name)
It still doesn't work.

I experimented and DirV.at(midPt).name works and I can display the name using this. But when I change to
Code:
if(Dir.name > DirV.at(midPt).name)

It gave the same wrong result.

The book doesn't go into vector of struct. I have no idea how to write code to deal with vector of struct. I read online quite a few, I just don't see my issue here. It's funny you can "cout" DirV[midPt].name and get the name, why can't I compare the name?

thanks
 
  • #9
yungman said:
I am still on the DirV[midPt].name issue. There is a member function at(). I change to
Code:
if(Dir.name > DirV.at(midPt).name)
It still doesn't work.
Of course it doesn't work. You are still comparing two addresses, not the strings that are stored starting at those addresses.
yungman said:
I experimented and DirV.at(midPt).name works and I can display the name using this. But when I change to
Code:
if(Dir.name > DirV.at(midPt).name)

It gave the same wrong result.
The comparison above is only a slight change from the original comparison. DirV is a vector object (an instance of the STL vector template class), so you can use the member functions of this class,
but, name is an array of type char.

You really need to memorize this concept:
C++:
char name[] = "fred";
name[0] is the character 'f', name[1] is the character 'r', and name[4] is the null character.
All by itself, name evaluates to an address in memory, the address of the first character in the string.
yungman said:
The book doesn't go into vector of struct. I have no idea how to write code to deal with vector of struct. I read online quite a few, I just don't see my issue here. It's funny you can "cout" DirV[midPt].name and get the name, why can't I compare the name?
Because the name fields are addresses.
BTW, you don't "cout" something -- you insert something in a stream with the << operator. One of the overloads of << will take the address of a char, and display the character at that address and all subsequent characters until a null character is encountered.
 
  • Like
Likes sysprog and yungman
  • #10
Mark44 said:
Of course it doesn't work. You are still comparing two addresses, not the strings that are stored starting at those addresses.
The comparison above is only a slight change from the original comparison. DirV is a vector object (an instance of the STL vector template class), so you can use the member functions of this class,
but, name is an array of type char.

You really need to memorize this concept:
C++:
char name[] = "fred";
name[0] is the character 'f', name[1] is the character 'r', and name[4] is the null character.
All by itself, name evaluates to an address in memory, the address of the first character in the string.
Because the name fields are addresses.
BTW, you don't "cout" something -- you insert something in a stream with the << operator. One of the overloads of << will take the address of a char, and display the character at that address and all subsequent characters until a null character is encountered.
AH, I see!

This has nothing to do with the vector! It is the .name part that is a c-string.

can you verify whether I am right instead of me experimenting with it:
C++:
if(strcmp(Dir.name, DirV[midPt].name) > 0);
for name in Dir > name in DirV[midPt]
 
  • #11
yungman said:
can you verify whether I am right instead of me experimenting with it:
C++:
if(strcmp(Dir.name, DirV[midPt].name) > 0);
for name in Dir > name in DirV[midPt]
Yes, that's right. Also, you can check the documentation, such as here: http://cplusplus.com/reference/cstring/strcmp/. Look in the Return Value section.
 
  • Like
Likes sysprog and yungman
  • #12
Thanks Mark, no wonder I have no luck searching on line, I was searching for vector of structs!

Now, I can go back and debug my program. Like I said, this is part of the sorting program for my Directory program, I still have to get the first name in next. This only sort the last name.

Thanks
 
  • #13
Hi, I am still debugging the program, quick question:

When I print out the source.cpp code, I lost color, there is no red color even though it shows on the computer.
I search and downloaded the Color Printing - VScodePrint for 2019 and installed it. But no change.

Is there any way to control VS on color of the print out?

Thanks
 
  • #14
Are you sure that VScodePrint 2019 is compatible with VS 2020? (I don't know the answer to that, but I've seen some accounts of version incompatibilities, including from the VSCP vendor). As a workaround, you could copy and paste into Notepad++ and print in color from there (the color conventions may differ from those of VS ##-## while you're expermimenting trying to get it to work, I suggest that you could use the 'print to PDF' option, so as to avoid wasting paper and ink.
 
  • Like
Likes yungman
  • #15
sysprog said:
Are you sure that VScodePrint 2019 is compatible with VS 2020? (I don't know the answer to that, but I've seen some accounts of version incompatibilities, including from the VSCP vendor). As a workaround, you could copy and paste into Notepad++ and print in color from there (the color conventions may differ from those of VS ##-## while you're expermimenting trying to get it to work, I suggest that you could use the 'print to PDF' option, so as to avoid wasting paper and ink.
Yes, I can just screen capture the code also or copy onto Word and retain the color.

Thanks
 
  • Like
Likes sysprog
  • #16
I finally completed this sorting program, I am NOT sure it's worth the trouble. The idea sounded much better in my head. I think this program is faster than Selection Sort. Because I sort every time I add a name, the vector DirV[] is always sorted. So when I add a new one, I can easily find the position to fit the new element, move the ones below down one position and copy the new element in. It should be faster and easier than Selection Sort. But the code is definitely longer due to different requirements when size = 1 and size = 2 comparing to size > 2.
C++:
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const static int nameLen = 25, phoneLen = 12;
struct Directory { char name[nameLen];    char phone[phoneLen]; };
std::vector<Directory>DirV;
Directory Dir;
int main()
{
  char more, displayAll;
  void add_sort();
  do
   { cout << " Enter name:  "; cin.getline(Dir.name, nameLen);
     cout << " Enter phone:  "; cin.getline(Dir.phone, phoneLen);
     add_sort();
     cout << " Do you want to enter another name?  "; cin.get(more);
     cin.ignore();
   } while (tolower(more) == 'y');
  int index = 0;
  do
   { cout << "Name stored in DirV is:  " << DirV[index].name <<
            " phone:  " << DirV[index].phone << "\n\n";
     index++;
   } while (index < DirV.size());
  return 0;
}

void add_sort()
{
    int size, element = 0, selCase;
  int startPt = 0, midPt = 0, endPt = 0;
  DirV.push_back(Dir);//Push to next available element of DirV.
  size = DirV.size();

//Below is for (size > 1).   First compare to find value of midPt
//where the element of DirV[midPt].name that is smaller or equal to Dir.name
  if (size > 1)
   { endPt = size - 2; midPt = (startPt + endPt) / 2;
   //endPt is last element before push_back, thereby endPt = size -2.
     do//loop until startPt = midPt = endPt which signals the end
      { if (strcmp(Dir.name, DirV[midPt].name) > 0)//Dir.name > DirV[midPt].name
         { startPt = midPt + 1; midPt = (startPt + endPt) / 2; }
        else { endPt = midPt; midPt = (startPt + endPt) / 2; }//next loop endPt=midPt
      }while (startPt != endPt);//Repeat until startPt = midPt = endPt
    }//END if (size > 1) value of midPt is where
     //DirV[midPt].name that is smaller or equal to Dir.name

//If midPt pointing to ORIGINAL last element before DirV.push_back(Dir)
  if (midPt == size - 2)//DirV[midPt] is the ORIGINAL last element.
    { if (strcmp(Dir.name, DirV[midPt].name) <= 0)//Dir.name <= DirV[midPt].name
  //Copy DirV[midPt] to last element and copy Dir into DirV[midPt] above last element
        { DirV[size - 1] = DirV[size - 2]; DirV[size - 2] = Dir;}
    }//END if (strcmp(Dir.name, DirV[midPt].name) <= 0)

  if (midPt < size - 2)
  { if (strcmp(Dir.name, DirV[midPt].name) <= 0)//Dir.name <= DirV[midPt].name
     //Copy DirV[midPt] to last element and copy Dir into DirV[midPt] above last element
     { int index1 = 0;
        do{ DirV[size -index1 - 1] = DirV[size -index1 - 2];
            index1++;
          } while (index1 < (size - midPt-1));
       DirV[size - index1 - 1] = Dir;
      }
    else//Dir.name > DirV[midPt].name
     {int index2 = 0;
      do { DirV[size - index2 - 1] = DirV[size - index2 - 2];
           index2++;
         } while (index2 < (size - midPt - 1));
      DirV[size - index2 - 1] = Dir;
     }
  }
}

In hind sight, I should use switch-case instead. Let me know if you have any opinion whether I should just give this up and use Selection Sort. It's a good experience though, I literally started from scratch with no reference. Took me like 3 days to get to this point and I don't like what I see. disappointing! It particularly doesn't help when I have to add a lot of lines for comment to explain what I am doing.

thanks
 
Last edited:
  • #17
yungman said:
Let me know if you have any opinion whether I should just give this up and use Selection Sort.
  1. On modern hardware sorting fewer than tens of thousands of records it doesn't really make any difference what algorithm you use.
  2. If I wanted to sort anything big I would simply use the STL std::sort library.
  3. If you want to learn about sorting algorithms then playing around with bubble, selection etc. is only going to take you so far, you need to look at merge sort, quick sort etc. Knuth is the bible here, but is expensive. A good alternative is the MIT introduction to algorithms, or you could look at this module on Khan Academy which is linked from the MIT press page.
  4. There are data structures that avoid having to sort after every addition which are more appropriate here. Again if I just wanted something that works I would use std::map, but to learn about how these work (red-black trees) the MIT book would be useful.

In 2020 we don't build everything from scratch otherwise we would not get anything done. In a 3 year computer science course you learn how to write compilers, implement sort/tree/hash and other algorithms, multi-threaded processes etc. but the purpose of acquiring this knowledge is not so that you can write a compiler, device drivers, GPUs, SSL transmission layers and whatever else before you start to write Angry Birds.
 
  • Like
Likes yungman and sysprog
  • #18
pbuk said:
Knuth is the bible here, but is expensive.
A (used 'acceptable') copy of Prof. Knuth's TAOCP Vol 3 Sorting and Searching is currently available for $4.95 on ebay https://www.ebay.com/itm/The-Art-of-Computer-Programming-Sorting-and-Searching-Volume-3-A-ACCEPTABLE/254604850809?hash=item3b47a1b679:g:eek:OYAAOSw8Rxfi6p~ or (used 'very good') for $8.95 here.

The entire series is rather advanced, but it's quite magnificent, and a joy to behold ##-## it's all laid out beautifullly in ##\TeX## (which Knuth invented).

Prof. Don is a man of wry humor ##-## e.g. at the end of page 5 of his classroom notes recounted in The correspondence between Donald E. Knuth and Peter van Emde Boas on priority deques during the spring of 1977 he says "Beware of bugs in the above code; I have only proved it correct, not tried it."
 
  • #19
I like this visual way to compare sorting algorithms.

But in the 70s, Knuth Volume 3 was pure pleasure to read. Knuth led us through best/worst/average performance analysis.

 
  • Like
Likes sysprog
  • #20
anorlunda said:
I like this visual way to compare sorting algorithms.
I like the graphics but using different size sets distorts the comparison. I think I can do better...
 
  • Like
Likes sysprog
  • #21
Some more animations:

https://commons.wikimedia.org/wiki/Category:Animations_of_sort_algorithms

https://www.toptal.com/developers/sorting-algorithms

For this link, the board software forces media tags even if I explicitly use url tags, and that results in showing only the first of 25 animations, and if you click on it a non-working url is opened, so I supressed that by using icode tags, so that you can read (but not open by clicking on it) the url ##-## to visit that link, you can copy it and paste it into a new tab: https://imgur.com/gallery/voutF

edit: I put a quick redirect to it via subdomain on my (free) sandbox site: http://sort-animations.fast-page.org
 
Last edited:
  • Like
Likes anorlunda
  • #22
pbuk said:
If you want to learn about sorting algorithms then playing around with bubble, selection etc. is only going to take you so far, you need to look at merge sort, quick sort etc.
The freely-available old C++ textbook by Astrachan discusses sorting algorithms, including quicksort, in chapter 11. That chapter also introduces algorithm analysis using O(n) (a.k.a. "big-O") notation.

Before I used C++ for this course, I used Pascal. I came up with a sorting algorithm that I called "stupid sort" which was even slower than bubble sort. I wish I could remember the details now, > 25 years later. :frown:
 
Last edited:
  • #23
jtbell said:
I came up with a sorting algorithm that I called "stupid sort" which was even slower than bubble sort.
A simple bubble sort results in the correct placement of at least one element on each pass through the elements to be sorted, so in the normal bubble sort, after each pass the number of elements to be tested is decremented by 1; failure to do that results in a less efficient bubble sort.
 
  • #24
I remember Knuth's teaching about the much more difficult problem of a tape sort.

We could never interest today's students in that, but perhaps they could analyze sort algorithm performance as a function of cache size for a number of algorithms. They could repeat the analysis where the data set to be sorted is on a hard drive too big to buffer in RAM.
 
  • Like
Likes pbuk
  • #25
jtbell said:
I came up with a sorting algorithm that I called "stupid sort" which was even slower than bubble sort.
sysprog said:
in the normal bubble sort, after each pass the number of elements to be tested is decremented by 1; failure to do that results in a less efficient bubble sort.
By Jove, that rings a bell in the back of my head! I think you've got it. :cool:
 
  • Like
Likes sysprog
  • #26
Thanks guys for the input. I know I should not spend so much time in reinventing the wheel designing the sort algorithm...BUT, I just feel like having some stimulation on the old brain. It is NOT easy, I spent like a week on this. But I really feel I learn a lot. Call it stupid sort or whatever, I did it.

I know it's pointless to optimize the speed, I just did it for the hell of it. The program ask to input information into each structure, then it immediately sort and store in the vector. So the elements of the vector are sorted already. Any new element added will be sorted and added in. Sounds easy enough, but I can assure you it's a whole lot harder than bubble or selection sort and a whole lot less steps. I don't know any other sorting method, so I just made this up. Call it stupid sort or whatever, I did this on my own.

My program not only sort the last name, I sort the first name also. I can input as many names as I want as I am using vector of structure to give me the flexibility. I made so much mistakes it's not funny. Things that work most of the time and fail occasionally. I don't know how many time I stepped through the program in debug. Finally I stopped and actually work out a table that really help me in seeing all the potential error. This is my program that ask you to input last name and first name, it will first sort the last name and then sort the first name within the same last name. Also tracking the element number of the vector array.
C++:
#include <iostream>
#include <cstring>
#include <vector>
#include <iomanip>
using namespace std;
const static int nameLen = 25, phoneLen = 12;
struct Directory { char lastName[nameLen]; char firstName[nameLen];    char phone[phoneLen]; int element; };
std::vector<Directory>DirV;
Directory Dir;
void add_sort_Lname(int&);
void sort_firstName(int&);
int main()
{
    int newName;
    char more, displayAll;
    do
    {   cout << " Enter last name:  "; cin.getline(Dir.lastName, nameLen);
        cout << " Enter first name:  "; cin.getline(Dir.firstName, nameLen);
        add_sort_Lname(newName);
        sort_firstName(newName);
        cout << " The new element added is DirV[" << newName << "] \n\n";
        cout << " Do you want to enter another name?  "; cin.get(more);
        cin.ignore();
    } while (tolower(more) == 'y');
    int index = 0;

    do
    { cout << "   Name stored in DirV[" << DirV[index].element << "]  is:   Last name: "
        << left << setw(10) << DirV[index].lastName << "    First name: " << left <<
        setw(10) << DirV[index].firstName << "    phone:  " << DirV[index].phone << "\n\n";
      index++;
    }while (index < DirV.size());
    return 0;
}

void add_sort_Lname(int& newName)
{ int size, selCase;
  DirV.push_back(Dir);//Push to next available element of DirV.
  size = DirV.size();// DirV[midPt].element = midPt; newName = midPt;
  int startPt = 0, endPt = size - 2, midPt = (endPt - startPt) / 2;
  if((size == 1) || ((strcmp(DirV[endPt].lastName, Dir.lastName) <= 0) & (size >= 2)))
      selCase = 0;//Don't have to sort or anything, Dir is in last element already
//Case 0 for first entry when size = 1 OR when Dir.lastName is
// >= to last element of DirV(Dir.lastName >= DirV[endPt].lastName.
  else
   {if((strcmp(Dir.lastName, DirV[startPt].lastName) <= 0) && (size > 1))
      selCase = 1;//If Dir smaller than DirV[0] AND (size >1)
    else
     { startPt = 0, endPt = size - 2; midPt = (endPt - startPt) / 2;
       do {  if (strcmp(Dir.lastName, DirV[midPt].lastName) <= 0)
                { endPt = midPt; midPt = (startPt + endPt) / 2; }
             else {startPt = midPt; midPt = (startPt + endPt) / 2; }
          }while (startPt != midPt);
       selCase = 2;
     }//else selCase = 2
  }
  switch(selCase)
   //(size = 1)  AND  Dir.lastName => DirV[endPt].lastName
   {case 0: { DirV[size - 1].element = size - 1; newName = size - 1; break;}
    case 1://Dir.lastName <= DirV[0].lastName
        { int i;
          for(i = 1; i <= (size - 1); i++)
           { DirV[size - i] = DirV[size - i - 1];
             DirV[size - i].element = size - i;
             DirV[size - i - 1].element = size - i - 1;
           }
          DirV[size - i] = Dir; newName = size - i;
          DirV[size - i].element = size - i;
          break;
        }
    case 2:
        { int j;
          for(j = 1; j <= (size - endPt - 1); j++)
           { DirV[size - j] = DirV[size - j - 1];
             DirV[size - j].element = size - j;
             DirV[size - j - 1].element = size - j - 1;
           }
          DirV[size - j] = Dir; newName = size - j;
          DirV[size - j].element = size - j;
          break;
        }
    }

}

void sort_firstName(int& newName)//DirV[newName] is the element of the newly added name.
{   int beginLname = newName, endLname = newName;//start out all equal
    int bubbleDown, bubbleUp;
    Directory Temp;//Temporary structure variable to store structure Directory
    Temp = DirV[newName];
    bool doneUp = false, doneDown = false, moveUp = false;
    bubbleUp = newName; bubbleDown = newName;
    while ((bubbleUp > 0) & !doneUp)//Prevent bubbleUp going negative
       {if((strcmp(DirV[newName].lastName, DirV[newName - 1].lastName) == 0)
            & (strcmp(DirV[newName].firstName, DirV[newName - 1].firstName) < 0))
          {DirV[newName] = DirV[newName - 1]; DirV[newName].element = newName;
           DirV[newName - 1] = Temp; DirV[newName - 1].element = newName - 1;      
           newName--;bubbleUp--; moveUp = true;}   
        else (doneUp = true);
       }//END while((bubbleUp > 0)& !doneUp)
    if (moveUp == false)
      {while ((bubbleDown < (DirV.size()-1)) & !doneDown)
         { if((strcmp(DirV[newName].lastName, DirV[newName + 1].lastName) == 0)
             &(strcmp(DirV[newName].firstName, DirV[newName + 1].firstName) > 0))
            { DirV[newName] = DirV[newName + 1]; DirV[newName].element = newName;
              DirV[newName + 1] = Temp; DirV[newName + 1].element = newName + 1;
              newName++; bubbleDown++; }
           else doneDown = true;
         }//END while (decrement < bubbleUp)
      }
}

This is a big step in completing my Directory program that store name, phone, address and email address. Also it uses Classes. This program really make me practice all the things I learned.

Attached is my table I used to write this program. I spent a few hours typing this in, that really helped me to see my bugs.

Thanks for all the help.
 

Attachments

  • Sorting chart1.docx
    21.4 KB · Views: 161
Last edited:
  • Like
Likes sysprog
  • #27
yungman said:
Thanks guys for the input. I know I should not spend so much time in reinventing the wheel designing the sort algorithm...BUT, I just feel like having some stimulation on the old brain. It is NOT easy, I spent like a week on this. But I really feel I learn a lot. Call it stupid sort or whatever, I did it.
I think that you are right to be pleased at having succeeded at working through some difficulties.

Just to clarify something that seems as if it may have been misunderstood: no-one here was trying to say anything derisive about your alorithm or your implementation of it ##-## the reference to "stupid sort" was in the context of discussion of sort algorithms in general, and of a classroom example that was decades ago presented as cautionary illustration of a possible inefficiency that could be brought into a sorting algorithm, due to failing to fully think it through.

Good on you for doing the work to keep your mental faculties in good shape.
 
  • Like
Likes yungman
  • #28
sysprog said:
I think that you are right to be pleased at having succeeded at working through some difficulties.

Just to clarify something that seems as if it may have been misunderstood: no-one here was trying to say anything derisive about your alorithm or your implementation of it ##-## the reference to "stupid sort" was in the context of discussion of sort algorithms in general, and of a classroom example that was decades ago presented as cautionary illustration of a possible inefficiency that could be brought into a sorting algorithm, due to failing to fully think it through.

Good on you for doing the work to keep your mental faculties in good shape.
Thanks

I like the challenge too. It's one thing to learn all the names and their meanings, it's another thing to let the rubber hit the road. It really started out thinking that was easy, you have a vector that is already sorted, how hard can it be to add a new one in the right place? NOT! It sounded so easy to set the starting point, the end point and middle = ( start + end)/2 and if new one is smaller than middle, end = middle, middle = ( start + end)/2 and do it over...... WRONG! That's how I spent 5 days going no where. Finally I created the chart, keeping tract of the start (S), middle (M) and end(E) as you see in subscripts in the word file. Then you can see how they being set. They don't behave the same depending on the position and the length of the original vector( ' --- ' in the chart shows where the new name fits in the existing vector). Took me 4 hours to generate the file, then one day to implement and debug to make it work. this is live and learn.

This reminds me in kick boxing, people keep admiring the round house kick and side kick that look so hard. They think front kick is easy, just pick up your foot and kick.....WRONG! Round and side kick has a steep learning curve, but once you get good, you are good. That stupid front kick looks so easy, believe me, it takes YEARS to master it to generate the power. You wonder why in MMA and other kick boxing tournaments seldom use front kicks? It's NOT easy to generate power. Last thing you want is you land a kick and the opponent just look at you!

Anyway, I am happy, I almost going to give up and put in the selection sort...But I guess it's not in my nature. Now that my study schedule is out the window delayed by this! 😊

The next step is displaying a range of selected names, choose one I want to delete and resort the file, that complete the sorting. Last step is to implement this back to my main program of Directory of names with address, phone, email and store in file using Classes.
 
Last edited:
  • Like
Likes sysprog
  • #29
yungman said:
I like the challenge too. It's one thing to learn all the names and their meanings, it's another thing to let the rubber hit the road. It really started out thinking that was easy, you have a vector that is already sorted, how hard can it be to add a new one in the right place? NOT! It sounded so easy to set the starting point, the end point and middle = ( start + end)/2 and if new one is smaller than middle, end = middle, middle = ( start + end)/2 and do it over...... WRONG! That's how I spent 5 days going no where. Finally I created the chart, keeping tract of the start (S), middle (M) and end(E) as you see in subscripts in the word file. Then you can see how they being set. They don't behave the same depending on the position and the length of the original vector( ' --- ' in the chart shows where the new name fits in the existing vector). Took me 4 hours to generate the file, then one day to implement and debug to make it work. this is live and learn.

Ah, I see what you have done. Rather than sorting, you have maintained the vector in a sorted state by inserting each new element into the right place. The algorithm you have used is called binary search if you want to look into this further.

yungman said:
Anyway, I am happy, I almost going to give up and put in the selection sort...But I guess it's not in my nature. Now that my study schedule is out the window delayed by this! 😊
Not much point in sorting a vector that is already sorted. There are better ways of organising this kind of data in a tree as I think I mentioned above, but this is a whole new subject that will take some time to master.

yungman said:
The next step is displaying a range of selected names, choose one I want to delete and resort the file, that complete the sorting.
Again you won't need to resort it, will you?
 
  • Like
Likes yungman
  • #30
pbuk said:
Ah, I see what you have done. Rather than sorting, you have maintained the vector in a sorted state by inserting each new element into the right place. The algorithm you have used is called binary search if you want to look into this further.Not much point in sorting a vector that is already sorted. There are better ways of organising this kind of data in a tree as I think I mentioned above, but this is a whole new subject that will take some time to master.Again you won't need to resort it, will you?
Thanks

I cannot find a better word than "sort"! Yes, the vector is sorted, just want to insert the new element into it. I read the name binary search and tree in later chapters. I just decided to be adventurous and do it. I don't want to wait and wait until I learn all the tools before attempt doing something. That's part of the adventure!

thanks
 
  • Like
Likes sysprog
  • #31
yungman said:
Thanks

I cannot find a better word than "sort"! Yes, the vector is sorted, just want to insert the new element into it. I read the name binary search and tree in later chapters. I just decided to be adventurous and do it. I don't want to wait and wait until I learn all the tools before attempt doing something. That's part of the adventure!

thanks
What you're doing is an insertion sort with a binary search instead of iterative comparisons to determine the insertion point ##-## there's a C++ example here: https://www.geeksforgeeks.org/binary-insertion-sort/
 
  • Like
Likes yungman
  • #32
sysprog said:
What you're doing is an insertion sort with a binary search instead of iterative comparisons to determine the insertion point ##-## there's a C++ example here: https://www.geeksforgeeks.org/binary-insertion-sort/
Actually this is a lot easier than what I am doing. The tricky part is to start the vector with no element. If you look at the subscripts S, M and E in my word file, you'll see they are different when you first push_back into an empty file. As it turn out, I don't even have to create the second page for 6 and 7 elements, you can see the trend in the first page already. That's the reason I separate into 3 different cases, case0, case1 and case2 and have to be treated differently.

insertion .jpg
 
  • #33
yungman said:
The tricky part is to start the vector with no element.
That's not usually tricky, the implementation should go something like this:
pseudocode:
function insertElement(element, array)
    // Set the lowest and highest points possible for insertion.
    low = 0;
    high = array.length;
    // Note if the array is empty high == low == 0 so the loop
    // is not executed and the element is inserted at array[0]
    while high > low
        midpoint = floor((high + low) / 2)
        ...
 
  • #34
pbuk said:
That's not usually tricky, the implementation should go something like this:
pseudocode:
function insertElement(element, array)
    // Set the lowest and highest points possible for insertion.
    low = 0;
    high = array.length;
    // Note if the array is empty high == low == 0 so the loop
    // is not executed and the element is inserted at array[0]
    while high > low
        midpoint = floor((high + low) / 2)
        ...
high = array.length - 1. It will be negative if there is no element in the array. It is this kind of small little things that are tricky. You can have the program running correctly until you hit these kind of potholes. It was to the point that I decided to stop and wrote out the chart in the word file. Then it became clear. I literally deleted all the former work and start over new and finished in one day with the chart.
 
  • #35
I finally finish to adding name, show certain range of names, delete name. I am sure the add_sort the last name is correct, I played with the first name , display and delete, so far, it works. But I want to play with it more to confirm. FINALLY, I can go back to my original Directory project and store all the names in a file so I can call them up the next time I run the program to do adding, delete. This is my final program:
C++:
#include <iostream>
#include <cstring>
#include <vector>
#include <iomanip>
using namespace std;
const static int nameLen = 25, phoneLen = 12;
struct Directory { char lastName[nameLen]; char firstName[nameLen];    char phone[phoneLen]; int element; };
std::vector<Directory>DirV;
Directory Dir;
void addName(int&);
void sort_firstName(int&);
void showRange(char[]);
void deleteName(int);
int main()
{
    int newName, index = 0, compSize, numDelete;
    char more, displayAll, choice;
    char selName[25];
    cout << " Welcome to the directory program. You can add name, contact informations and\n";
    cout << " it will store in a file. You can display selected names and choose to delete\n";
    cout << " anyone you want.\n\n";
    do {
         cout << " Please enter 'a' to add names, 's' to dispay complete list. 'r' to show \n";
         cout << " range of names around a name. 'd' for delete a specific name. 'q' to quit.\n\n";
         cout << " Please enter what you want to do:  "; cin >> choice; cout << "\n\n";
         switch (choice)
           {
             case 'a': //Add new names and sort
               { do { cout << " Enter last name:  "; cin >> Dir.lastName;
                      //cout << " Enter first name:  "; cin >> Dir.firstName;
                      addName(newName);
                      sort_firstName(newName);
                      cout << " \n\nDo you want to enter another name?  "; cin >> more;
                    }while (tolower(more) == 'y');
                 break;
               };//End case 'a'
             case 's': //Display entire list of names and info
               { index = 0;
                 if(DirV.size() > 0)
                   { do { cout << "   Element #" << DirV[index].element <<
                          "]  is:   Last name: " << left << setw(10) << DirV[index].lastName <<
                          " first name: " << left << setw(10) << DirV[index].firstName << "\n\n";
                          index++;
                        } while (index < DirV.size()); break;
                    } else cout << " There is no name in the file.\n\n";
               };//End case 's'
             case 'r':
               { if (DirV.size() > 0)
                  { cout << " Enter the first 2 character of the last name to search.";
                    cin >> selName; cout << "\n\n";
                   showRange(selName);//Display range before and after the name initials.
                  }else cout << " There is no name in the file.\n\n";
                 break;
               };
             case 'd'://Delete a name.
               { showRange(selName);
                 cout << " Enter the Element# of the left to be deleted: ";
                 cin >> numDelete;
                 deleteName(numDelete);
                 break;
               };//End case 'd'
             case 'q':{ cout << " Are you sure you want to quit? ";
                        cin >> choice; cout << "\n\n";};
             default: cout << " Not a valid choice.\n";
           }//End switch
       } while(choice != tolower('q'));//End choice what to do

    return 0;
}//End main()

void addName(int& newName)
{ int size, selCase;
  DirV.push_back(Dir);//Push to next available element of DirV.
  size = DirV.size();// DirV[midPt].element = midPt; newName = midPt;
  int startPt = 0, endPt = size - 2, midPt = (endPt - startPt) / 2;
  if((size == 1)||((strcmp(DirV[endPt].lastName, Dir.lastName) <= 0) & (size >= 2)))
      selCase = 0;//Don't have to sort or anything, Dir is in last element already
//Case 0 for first entry when size = 1 OR when Dir.lastName is
// >= to last element of DirV(Dir.lastName >= DirV[endPt].lastName. 
  else
   {if((strcmp(Dir.lastName, DirV[startPt].lastName) <= 0) && (size > 1))
      selCase = 1;//If Dir smaller than DirV[0] AND (size >1)
    else
     { startPt = 0, endPt = size - 2; midPt = (endPt - startPt) / 2;
       do {  if (strcmp(Dir.lastName, DirV[midPt].lastName) <= 0)
                { endPt = midPt; midPt = (startPt + endPt) / 2; }
             else {startPt = midPt; midPt = (startPt + endPt) / 2; }
          }while (startPt != midPt);
       selCase = 2;
     }//else selCase = 2
   }//End if((strcmp(Dir.lastName, DirV[startPt].lastName) <= 0) && (size > 1))
  switch(selCase)
   //(size = 1)  AND  Dir.lastName => DirV[endPt].lastName
   {case 0: { DirV[size - 1].element = size - 1; newName = size - 1; break;}
    case 1://Dir.lastName <= DirV[0].lastName
        { int i;
          for(i = 1; i <= (size - 1); i++)
           { DirV[size - i] = DirV[size - i - 1];
             DirV[size - i].element = size - i;
             DirV[size - i - 1].element = size - i - 1;
           }//End for
          DirV[size - i] = Dir; newName = size - i;
          DirV[size - i].element = size - i;
          break;
        }//End case 1
    case 2:
        { int j;
          for(j = 1; j <= (size - endPt - 1); j++)
           { DirV[size - j] = DirV[size - j - 1];
             DirV[size - j].element = size - j;
             DirV[size - j - 1].element = size - j - 1;
           }
          DirV[size - j] = Dir; newName = size - j;
          DirV[size - j].element = size - j;
          break;
        }//end case 2
    }//End switch
}

void sort_firstName(int& newName)//DirV[newName] is the newly added name.
{   int beginLname = newName, endLname = newName;//start out all equal
    int bubbleDown, bubbleUp;
    Directory Temp;//Temporary structure variable to store structure Directory
    Temp = DirV[newName];
    bool doneUp = false, doneDown = false, moveUp = false;
    bubbleUp = newName; bubbleDown = newName;
    while ((bubbleUp > 0) & !doneUp)//Prevent bubbleUp going negative
       {if((strcmp(DirV[newName].lastName, DirV[newName - 1].lastName) == 0)
            & (strcmp(DirV[newName].firstName, DirV[newName - 1].firstName) < 0))
          {DirV[newName] = DirV[newName - 1]; DirV[newName].element = newName;
           DirV[newName - 1] = Temp; DirV[newName - 1].element = newName - 1;        
           newName--;bubbleUp--; moveUp = true;}     
        else (doneUp = true);
       }//END while((bubbleUp > 0)& !doneUp)
    if (moveUp == false)
      {while ((bubbleDown < (DirV.size()-1)) & !doneDown)
         { if((strcmp(DirV[newName].lastName, DirV[newName + 1].lastName) == 0)
             &(strcmp(DirV[newName].firstName, DirV[newName + 1].firstName) > 0))
            { DirV[newName] = DirV[newName + 1]; DirV[newName].element = newName;
              DirV[newName + 1] = Temp; DirV[newName + 1].element = newName + 1;
              newName++; bubbleDown++; } 
           else doneDown = true;
         }//END while (decrement < bubbleUp)
      }
}
void showRange(char selName[25])
{
    int size = DirV.size(), stpt = 0, edpt = size - 1;
    int mdpt = (stpt + edpt) / 2, index, comp;
    do //search to within range using 2 characters in selName
     {  comp = strncmp(selName, DirV[mdpt].lastName, 2);
        if (comp != 0) {if(comp > 0){stpt = mdpt; mdpt = (stpt + edpt)/2;}
        else {edpt = mdpt; mdpt = (stpt + edpt) / 2;}}
     } while ((comp != 0) && (stpt + 2 <= edpt));//Matching DirV[mdpt]
    for(index = -2; index <=3; index++)
      {if(((mdpt + index) >= 0) && ((mdpt + index) <= (size - 1)))
        { cout << "   Element #" << DirV[mdpt + index].element <<
        "]  is:   Last name: " << left << setw(10) << DirV[mdpt + index].lastName <<
        " first name: " << left << setw(10) << DirV[mdpt + index].firstName << "\n\n";}
      }//End for loop to display range of names if it is valid.
}//End showRange
void deleteName(int numDelete)
{   char sure;
    int edpt = DirV.size() - 1;
    cout << " Is this what you chose?\n";
    cout << "   Element #" << DirV[numDelete].element <<
          "]  is:   Last name: " << left << setw(10) << DirV[numDelete].lastName <<
          " first name: " << left << setw(10) << DirV[numDelete].firstName << "\n\n";
    cout << " Are you sure you want to delete this:\n\n"; cin >> sure;
    if (tolower(sure) == 'y')
    {
        for(int i = 0; i < (edpt - numDelete); i++)
        { DirV[numDelete + i] = DirV[numDelete + i + 1];
          DirV[numDelete + i].element = numDelete + i;}
        DirV.pop_back();
    }

}

It is getting very long. the next step on top of saving in file, I am going to break the program up using Class declaration and put a lot of these in the Specification and implementation file. I am even thinking about using two Specification files, one doing file management, the second one just add sort delete.

Thanks for all the help. It's educational. Working through the programs in the book is NOTHING like writing one of this program, one really find out what they actually learned. I had to kept going back to my notes, the book and online to find the correct ways to write the program.

Thanks
 
Last edited:

Similar threads

  • Programming and Computer Science
3
Replies
75
Views
4K
  • Programming and Computer Science
Replies
30
Views
2K
  • Programming and Computer Science
Replies
32
Views
2K
  • Programming and Computer Science
2
Replies
66
Views
4K
  • Programming and Computer Science
Replies
5
Views
885
Replies
10
Views
960
  • Engineering and Comp Sci Homework Help
Replies
3
Views
2K
  • Programming and Computer Science
Replies
3
Views
2K
  • Engineering and Comp Sci Homework Help
Replies
1
Views
6K
  • Engineering and Comp Sci Homework Help
Replies
4
Views
3K
Back
Top