Program help with TUDs (total unique digit counter)

Hello, my code is so close to working but this pesky bug is proving hard for me to solve. It's to the point where I am being unproductive. Note that I had to use the below conventions, ie. only cin and cout.

Here is an example of erroneous output:

What is the size of the array?: 3
Value #1: 124
Value #2: 54444
Value #3: -432
The working array has 3 values of
Value 1: 124
Value 2: 54444
Value 3: -432

Calling getSIWSmallestTUDCWilliamG() with argument of
(1) The array { 124 , 54444 , -432 }; and
(2) The array size of 3

For individual values -
124 has 3 unqiue digit(s).
54444 has 2 unqiue digit(s).
-432 has 3 unqiue digit(s).

After the function call was completed and a value was returned

(1) The smallest TUD is 1 and;
(2) 0 is the smallest integer with a smallest TUD of 1

The TUD (total unique digit count) won't count right after the second loop! (first loop works)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <iostream>
using namespace std;

//Function Prototypes
void getSIWSmallestTUDCWilliamG(int smallestIntWG, int smallestTudWG);
int getIntUDCWilliamG(int integerWG);
void displayClassInfoWilliamG(void);
void runHW2(void);

//Application Driver
int main() {
    runHW2();
    return 0;
}

//Function Definition
void runHW2() {
    int inputWG = 0;
    int sizeWG = 0;
    int* arrayWG = { nullptr };
    int tempTudWG = 10;
    int tempWG = 0;
    int tudWG = 0;
    int smallestIntWG = 0;
    int smallestTudWG = 10;
    int tinyTudWG = 10;

    displayClassInfoWilliamG();

    do {
        cout << "\n*******************************************\n"
            "*              MENU - HW #2               *\n"
            "*  (1) Calling getSIWSmallestTUDCWilliamG *\n"
            "*  (2) Quit                               *\n"
            "*******************************************\n";
        cin >> inputWG;

        switch (inputWG) {
        case 1:
        {
            cout << "Calling getSIWSmallestTUDCWilliamG\n" << endl
                << "What is the size of the array?: ";
            cin >> sizeWG;

            while (sizeWG < 1) {
                cout << "\nInvalid input, SizeWG => 1 please. Type again here: ";
                cin >> sizeWG;
                cout << "\n";
            }

            arrayWG = new int[sizeWG];

            for (int i = 0; i < sizeWG; i++) {
                cout << "   Value #" << i + 1 << ": ";
                cin >> arrayWG[i];
            }

            cout << "The working array has " << sizeWG << " values of\n";

            for (int i = 0; i < sizeWG; i++) {
                cout << "   Value " << i + 1 << ": " << arrayWG[i] << "\n";
            }
            cout << endl;

            cout << "Calling getSIWSmallestTUDCWilliamG() with argument of\n"
                "  (1) The array { ";

            for (int i = 0; i < (sizeWG - 1); i++) {
                cout << arrayWG[i] << " , ";
            }
            cout << arrayWG[sizeWG - 1] << " }; and\n  (2) The array size of " << sizeWG << "\n";

            cout << "\n  For individual values -\n";
            for (int i = 0; i < sizeWG; i++) {
                arrayWG[i] > 0 ? tempWG = arrayWG[i] : tempWG = -arrayWG[i];
                tudWG = getIntUDCWilliamG(tempWG);

                cout << "    " << arrayWG[i] << " has " << tudWG << " unqiue digit(s).\n";

                tempTudWG = tudWG;
                if (tempTudWG < smallestTudWG) {
                    smallestTudWG = tempTudWG;
                    smallestIntWG = arrayWG[i];
                }
                else if (tempTudWG == smallestTudWG && smallestIntWG < tempWG) {
                    smallestIntWG = arrayWG[i];
                }
            }

            cout << "\nAfter the function call was completed and a value was returned\n\n";
            getSIWSmallestTUDCWilliamG(smallestIntWG, smallestTudWG);
            cout << "\n";

            smallestIntWG = 0;
            delete[] arrayWG;
            arrayWG = { nullptr };
            break;
        }
        case 2:
            cout << "Ok, goodbye!";
            break;
        default:
            cout << "Wrong option, try again\n";
            break;
        }
    } while (inputWG != 2);
}

//Function Definition
int getIntUDCWilliamG(int integerWG) {
    int tudWG = 0;
    int tempArray[10]{ 0 };

    while (integerWG > 0) {
        tempArray[integerWG % 10]++;
        integerWG /= 10;
    }

    for (int i = 0; i < 10; i++) {
        if (tempArray[i] != 0) {
            tudWG++;
        }
    }
    return tudWG;
}

//Function Definition
void getSIWSmallestTUDCWilliamG(int smallestIntWG, int smallestTudWG) {
    cout << "  (1) The smallest TUD is " << smallestTudWG << " and;\n"
    "  (2) " << smallestIntWG << " is the smallest integer with a smallest TUD of " << smallestTudWG;
}

//Function Definition
int getSIWSmallestTUDCWilliamG(int* arrayWG, int sizeWG) {
    int smallestIntTUDWG = arrayWG[0];
    int tudWG = 0;
    int smallestTUDWG = 10;
    int tempWG = 0;


    //Find smallest TUDC
    for (int i = 0; i < sizeWG; i++) {
        tempWG = arrayWG[i];
        if (arrayWG[i] != 0) {
            tempWG % 10;
            ++tudWG;
            tempWG /= 10;
        }
        if (tudWG < smallestTUDWG) {
            smallestIntTUDWG = smallestTUDWG;
            tudWG = smallestTUDWG;
        }
    }
   
    return smallestIntTUDWG;
}
Last edited on
Hello WillliamTries2Prog,

You should first compile your program and try to fix the errors that you can. The errors that you do not understand post the full compiler error message and not what you think it means.

Your first problem is line 28. You are trying to define a function inside a function and that is not allowed in C++. Either remove the function definition or move it outside of "main". For the way it starts I would call it "MainMenu". As a menu function you can use a do while loop until you have a valid choice to return. This gives you the ability to enter something and check it until it is right.

Consider something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
int MainMenu()
{
    constexpr int MAXCHOICE{ 2 };  // <--- Change as needed.

    int choice{};

    cout <<
        "\n"
        "*******************************************\n"
        "*              MENU - HW #2               *\n"
        "*  (1) Calling getSIWSmallestTUDC         *\n"
        "*  (2) Quit                               *\n"
        "*******************************************\n"
        "\n"
        " Enter choice: ";

    do
    {
        cin >> choice;

        if (!std::cin || (choice < 1 || choice > MAXCHOICE))  // <--- Change 2 as needed.
        {
            if (!std::cin)
            {
                std::cout << "\n     Invalid entry! Must be a number.\n";

                std::cin.clear();
                std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
            }
            else if (choice < 1 || choice > MAXCHOICE)
            {
                std::cout << "\n     Invalid choice! Try again.\n";
            }
        }
    } while (choice < 1 || choice > MAXCHOICE);
 
    return choice;
}

Some of the other code that contains errors I just commented out for now.

On line 74 you wrote: tudWG = getIntUDCWilliamG(tempWG);, but the closest function appears to be:
tudWG = getIntUDC(tempWG);.

Andy
Hello WillliamTries2Prog,

When I made a few changes and got the program to run I get this output:


*******************************************
*              MENU - HW #2               *
*  (1) Calling getSIWSmallestTUDC         *
*  (2) Quit                               *
*******************************************

 Enter choice: 1

Calling getSIWSmallestTUDC

What is the size of the array?: 3
   Value #1: 124
   Value #2: 54444
   Value #3: -432
The working array has 3 values of
   Value 1: 124
   Value 2: 54444
   Value 3: -432

Calling getSIWSmallestTUDC() with argument of
  (1) The array { 124 , 54444 , -432 }; and
  (2) The array size of 3

  For individual values -
    124 has 3 unique digit(s).  // <--- Corrected spelling of "unqiue"
    54444 has 2 unique digit(s).
    -432 has 3 unique digit(s).

After the function call was completed and a value was returned

  (1) The smallest TUD is 2 and;
  (2) 54444 is the smallest integer with a smallest TUD of 2


Is this what you need or maybe the last may need to say something different?

Andy
Hi HandyAndy, my apologies. I was so out of mind that I failed to see that the paste somehow came out wrong. I now see what I pasted would not even compile. My issue is a little different than what was above, see:

*******************************************
*              MENU - HW #2               *
*  (1) Calling getSIWSmallestTUDCWilliamG *
*  (2) Quit                               *
*******************************************
1
Calling getSIWSmallestTUDCWilliamG

What is the size of the array?: 3
   Value #1: 1245
   Value #2: 214
   Value #3: 222
The working array has 3 values of
   Value 1: 1245
   Value 2: 214
   Value 3: 222

Calling getSIWSmallestTUDCWilliamG() with argument of
  (1) The array { 1245 , 214 , 222 }; and
  (2) The array size of 3

  For individual values -
    1245 has 4 unqiue digit(s).
    214 has 3 unqiue digit(s).
    222 has 1 unqiue digit(s).

After the function call was completed and a value was returned

  (1) The smallest TUD is 1 and;
  (2) 222 is the smallest integer with a smallest TUD of 1

*******************************************
*              MENU - HW #2               *
*  (1) Calling getSIWSmallestTUDCWilliamG *
*  (2) Quit                               *
*******************************************
1
Calling getSIWSmallestTUDCWilliamG

What is the size of the array?: 3
   Value #1: 532
   Value #2: 1243
   Value #3: -12
The working array has 3 values of
   Value 1: 532
   Value 2: 1243
   Value 3: -12

Calling getSIWSmallestTUDCWilliamG() with argument of
  (1) The array { 532 , 1243 , -12 }; and
  (2) The array size of 3

  For individual values -
    532 has 3 unqiue digit(s).
    1243 has 4 unqiue digit(s).
    -12 has 2 unqiue digit(s).

After the function call was completed and a value was returned

  (1) The smallest TUD is 1 and;
  (2) 0 is the smallest integer with a smallest TUD of 1

*******************************************
*              MENU - HW #2               *
*  (1) Calling getSIWSmallestTUDCWilliamG *
*  (2) Quit                               *
*******************************************
1
Calling getSIWSmallestTUDCWilliamG

What is the size of the array?: 3
   Value #1: 534
   Value #2: 3523
   Value #3: 324
The working array has 3 values of
   Value 1: 534
   Value 2: 3523
   Value 3: 324

Calling getSIWSmallestTUDCWilliamG() with argument of
  (1) The array { 534 , 3523 , 324 }; and
  (2) The array size of 3

  For individual values -
    534 has 3 unqiue digit(s).
    3523 has 3 unqiue digit(s).
    324 has 3 unqiue digit(s).

After the function call was completed and a value was returned

  (1) The smallest TUD is 1 and;
  (2) 0 is the smallest integer with a smallest TUD of 1

*******************************************
*              MENU - HW #2               *
*  (1) Calling getSIWSmallestTUDCWilliamG *
*  (2) Quit                               *
*******************************************



I will edit my post with the correct code. I am sorry about that, my fault. I appreciate your help! Cheers.

Also- thank you for your advice, it's a great perspective. Sadly there are some library functions you use, my professor is very strict so I am quite limited. Will take note regardless! Also your reply is correct, that is ideally what the output should look like.

Additional note: this was not a definition, it is actually a function that I defined elsewhere that outputs redundant information about the homework that I did not want to waste space pasting. Technically, it has no functionality, other than to print out some information.
Last edited on
After some more testing, I see that negative numbers cause the whole program to do the shown issue. It works just fine with positives? When negative integers are inputted, the program will fail. Even future iterations of the menu with ONLY positives will still fail, until the program is restarted. This is both interesting since I have no idea why it is happening, yet frustrating for said reason.

My only logical assumption is that:
1
2
3
4
5
6
7
8
 tempTudWG = tudWG;
                if (tempTudWG < smallestTudWG) {
                    smallestTudWG = tempTudWG;
                    smallestIntWG = arrayWG[i];
                }
                else if (tempTudWG == smallestTudWG && smallestIntWG < tempWG) {
                    smallestIntWG = arrayWG[i];
                }


would be the cause of the issue? But I am not sure why.
Last edited on
Hello WillliamTries2Prog,

Since you are new do not change your original post especially the code. It makes it harder for others to understand what is wrong. Or when the replies refer to a line of code that has been changed.

Put any changes in a reply to keep the flow of replies making sense.

First thing in the morning I will look at your changes.

Andy
Thank you for taking your time to help, and sorry about that, will keep in mind for the future.
@WillliamTries2Prog

Some advice:

Come up with better variable and function names. Well named code should tell a story of what is happening. Putting your name in function identifiers just adds a whole lot of cruft. Acronyms like TUD are ok if you comment them to say what they mean, but don't overdo it. It turns the code into gibberish.

Use more functions, case 1 in the switch is way too much code. Functions should do 1 conceptual thing.

I would have expected the following functions:

Sort the chars in a string;
Remove duplicates;
count chars in string;
Store count variable in a container so there is an association with the original numbers;
Find the minimum.

What I just wrote above was most of the pseudo code for your assignment. Pseudo code is a very useful tool for young and old: it can help one design their code properly; identify what data structures to use; identify what should be in functions etc. The beauty of it is that one can start with very general ideas, then go back and add more detail. What I do: write the pseudo code as comments in a file; keep adding detail until ready to write actual code; leave comments in the code.

Doing code design like that is much better than tearing into writing lots of code, then discovering one has made a giant mess. A big problem is that people spend hours writing code, then someone comes along and pours icy water over the whole thing. It takes some maturity to take constructive criticism on board, then start again with a fresh view of how to go about designing and writing code.

If I was marking assignments, this would be my regime: 1/4 marks if it works; 1/4 marks for design; 1/4 marks for coding style (ease of readability & comprehension) ; 1/4 marks for efficiency. I would also force the production of pseudo code before any real code.

To be blunt & rude: your tutor will see your code and think wtf is this? Apologies, but it may make you consider changing how you approach coding. Hopefully for the better :+) I think you will feel good if you know that you are doing your work with a good methodology - that is, happy you are doing it right :+)
Last edited on
Hello WillliamTries2Prog,

I agree with the TheIdeasMan you need much better variable names. I have changed a couple of names, but the rest are hard to follow.

I have looked back over your posts and did not find anywhere where you mentioned what IDE and compiler you are using. The IDE is more important. Please mention this.

While testing the program I found:
void getSIWSmallestTUDCWilliamG(int smallestIntWG, int smallestTudWG);, but looking after "main" I find:
1
2
3
4
5
void getSIWSmallestTUDCWilliamG(int smallestIntWG, int smallestTudWG)

//  And

int getSIWSmallestTUDCWilliamG(int* arrayWG, int sizeWG)

The return values here help make a difference, but it is the 1st parameter that makes them different and the compiler accepts this without any problem. You do need to forward declare the 2nd function and also call it with the proper parameters, which you are not doing.

Inside the function: int getSIWSmallestTUDCWilliamG(int* arrayWG, int sizeWG)
This line of code: tempWG % 10; does nothing. Did you mean tempWG %= 10;, but then when you get to: tempWG /= 10;, but since "tempWG", say having a value of 5, now has a single digit and dividing by 10 would leave you with "0.5". But this is integer division the ".5" is dropped and only the (0)zero is stored. This can be a problem.

I have yet to fully understand what the for loop and if statement is trying to do.

AS I gain more understand of your code the function getIntUDCWilliamG is called 1st, which makes me wonder if int getSIWSmallestTUDCWilliamG(int* arrayWG, int sizeWG) is even needed.

Still have some work to do, but these are some of the changes I made. Some may seem small, but they are very helpful:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

using namespace std;  // <--- Best not to use.

//Function Prototypes
void getSIWSmallestTUDCWilliamG(int smallestIntWG, int smallestTudWG);
int getSIWSmallestTUDCWilliamG(int* arrayWG, int sizeWG);  // <--- Added.
int getIntUDCWilliamG(int integerWG);
void displayClassInfoWilliamG(void);  // <--- 2nd "void" not required. This is old C.
void runHW2(void);  // <--- 2nd "void" not required. This is old C.

//Application Driver
int main()
{
    runHW2();

    return 0;  // <--- Not required, but makes a good break point for testing.
}

Line 16 is to demonstrate how a blank line makes the code more readable and easier to follow.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void runHW2()
{
    constexpr int MAXSIZE{ 1 };

    int choice{};  // <--- ALWAYS initialize all your variables.
    int arrSize{};  // <--- Changed.
    int* arrayWG{ nullptr };
    int tempTudWG{ 10 };
    int tempWG = 0;
    int tudWG = 0;
    int smallestIntWG = 0;
    int smallestTudWG = 10;
    int tinyTudWG = 10;
    int loopTimes{}; // <--- Used for testing. Comment or remove when finished.

    /*displayClassInfoWilliamG();*/  // <--- This is a function call to a function that does not exist.

    do
    {
        cout << 
            "\n"
            "*******************************************\n"
            "*              MENU - HW #2               *\n"
            "*  (1) Calling getSIWSmallestTUDCWilliamG *\n"
            "*  (2) Quit                               *\n"
            "*******************************************\n"
            "  Enter choice: ";
        cin >> choice;  // <--- The "cin" ALWAYS needs a prompt. See above.

        switch (choice)

The concept of line 3 is very useful. You need to get use to this. AS you will see it makes changing your code very easy.

The "cout" statement may look like 7 different strings, but to the IDE and compiler it sees just 1 string of 237 characters +1 for the (\0) to mark the end of the string, or const char*, as the IDE considers it.

So you just 1 "cout" for 1 string and 1 (;) to mark the end of the line.

There are 2 advantages to this. First it looks more like what will be printed to the screen. Second it is much easier to change or edit.

Prefer to use the new line, (\n), over the function "endl" as much as possible.

The last advantage is when a "cout" is followed by a "cin" the "cin" will cause the buffer to be flushed of anything, output, that is left before it takes any input.

In your switch case 1 is way to big. Much of what is there can be put into small functions that can be called when needed. The switch should just direct the program flow not be the program.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
switch (choice)
{
    case 1:
    {
        cout << "\nCalling getSIWSmallestTUDCWilliamG\n\n";
        //    << "What is the size of the array?: ";
        //cin >> arrSize;

        while
            (std::cout << "What is the size of the array? (Must be >= " << MAXSIZE << "): " && !(std::cin >> arrSize) || arrSize < MAXSIZE)
        {
            if (!std::cin)
            {
                std::cout << "\n     Invalid entry! Must be a number.\n\n";

                std::cin.clear();
                //std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
                std::cin.ignore(1000, '\n');

            }
            else if (arrSize < MAXSIZE)
            {
                cout <<
                    "\n     Invalid input, SizeWG => " << MAXSIZE << " please try again.\n\n";
            }
        }

The while loop is something that you should get use to. I realize this may be ahead of what you have learned, but there is no time like the present to learn something new. I you need a better explanation let me know.

In line 24 "SizeWG" has no meaning as a variable name and even less meaning to a user. Consider changing "SizeWG" to "value" and see how it reads. Think about the perspective of a user who has no knowledge of C++ or any other language. Good advice when writing a prompt or error message.

This is a good example of how "MAXSIZE" can be used. Having only place to change its value you do not have to hunt through your program to find magic numbers to change. You will very likely miss 1 or 2.

After this I did this for testing:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
arrayWG = new int[arrSize];
                
if (!loopTimes) // <--- Used for testing. Comment or remove when finished. Also removing the (!) can change the order.
{   
    arrayWG[0] = 1245;
    arrayWG[1] = 214;
    arrayWG[2] = 222;

    loopTimes++;
}
else
{
    arrayWG[0] = 532;
    arrayWG[1] = 1243;
    arrayWG[2] = -12;

    loopTimes++;
}


//for (int i = 0; i < arrSize; i++)  // <--- Commented for testing. Because we know it works.
//{
//    cout << "   Value #" << i + 1 << ": ";
//    cin >> arrayWG[i];
//} 

You can change the "else" to "else if (loopTimes == 1)" and add more "else if" statements to create different scenarios. This speeds up testing not having to enter numbers each time you run the program. You can also initialize "arrSize" to 3 and comment the "cin" statement for this.

After this I need to determine if getIntUDCWilliamG is enough or if
getSIWSmallestTUDCWilliamG(arrayWG, arrSize); is needed and wow it needs to be changed.

Andy
Hello WillliamTries2Prog,

It took awhile, but I think it is a simple fix to the program. Sometines it is the simple things that get you.

You have:
1
2
3
4
smallestIntWG = 0;
delete[] arrayWG;
arrayWG = { nullptr };
break;

But you forgot about: smallestTudWG.

Your code should be:
1
2
3
4
5
smallestIntWG = 0;
smallestTudWG = 10;
delete[] arrayWG;
arrayWG = { nullptr };
break;

Once I added that line I believe it works properly. At least it looks that way for the first 2 I tested.

Andy
Hello WillliamTries2Prog,

After running 3 tests I get this output:


*******************************************
*              MENU - HW #2               *
*  (1) Calling getSIWSmallestTUDCWilliamG *
*  (2) Quit                               *
*******************************************
  Enter choice:
Calling getSIWSmallestTUDCWilliamG

The working array has 3 values of
   Value 1: 1245
   Value 2: 214
   Value 3: 222

Calling getSIWSmallestTUDCWilliamG() with argument of
  (1) The array { 1245 , 214 , 222 }; and
  (2) The array size of 3

  For individual values -
    1245 has 4 unqiue digit(s).
    214 has 3 unqiue digit(s).
    222 has 1 unqiue digit(s).

After the function call was completed and a value was returned

  (1) The smallest TUD is 1 and;
  (2) 222 is the smallest integer with a smallest TUD of 1

*******************************************
*              MENU - HW #2               *
*  (1) Calling getSIWSmallestTUDCWilliamG *
*  (2) Quit                               *
*******************************************
  Enter choice:
Calling getSIWSmallestTUDCWilliamG

The working array has 3 values of
   Value 1: 532
   Value 2: 1243
   Value 3: -12

Calling getSIWSmallestTUDCWilliamG() with argument of
  (1) The array { 532 , 1243 , -12 }; and
  (2) The array size of 3

  For individual values -
    532 has 3 unqiue digit(s).
    1243 has 4 unqiue digit(s).
    -12 has 2 unqiue digit(s).

After the function call was completed and a value was returned

  (1) The smallest TUD is 2 and;
  (2) -12 is the smallest integer with a smallest TUD of 2

*******************************************
*              MENU - HW #2               *
*  (1) Calling getSIWSmallestTUDCWilliamG *
*  (2) Quit                               *
*******************************************
  Enter choice:
Calling getSIWSmallestTUDCWilliamG

The working array has 3 values of
   Value 1: 534
   Value 2: 3523
   Value 3: 324

Calling getSIWSmallestTUDCWilliamG() with argument of
  (1) The array { 534 , 3523 , 324 }; and
  (2) The array size of 3

  For individual values -
    534 has 3 unqiue digit(s).
    3523 has 3 unqiue digit(s).
    324 has 3 unqiue digit(s).

After the function call was completed and a value was returned

  (1) The smallest TUD is 3 and;
  (2) 3523 is the smallest integer with a smallest TUD of 3


Notice the next to last line appears to be correce, but the lastline "3523" is not the smallest. "324" is.

Andy
Without all the intermediate output (easily added if really must), perhaps consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <string>
#include <iostream>
#include <limits>
#include <cmath>
#include <vector>

int getInt(const std::string& prm)
{
	int i {};

	while ((std::cout << prm) && (!(std::cin >> i) || std::cin.peek() != '\n')) {
		std::cout << "Not an integer\n";
		std::cin.clear();
		std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
	}

	std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
	return i;
}

size_t getTUD(int no)
{
	uint8_t nos[10] {no == 0};

	for (no = std::abs(no); no; no /= 10)
		++nos[no % 10];

	size_t cnt {};

	for (auto n : nos)
		cnt += n >= 1;

	return cnt;
}

struct Data {
	int no {};
	size_t cnt {};
};

void doTUD()
{
	int sze {};

	do {
		sze = getInt("What is the size of the array: ");
	} while (sze <= 0 && (std::cout << "Must be greater than 0\n"));

	std::vector<Data> array(sze);

	for (size_t elem {}; auto & [no, cnt] : array) {
		no = getInt("Value # " + std::to_string(++elem) + ": ");
		cnt = getTUD(no);
	}

	std::cout << '\n';

	size_t minTUD {};

	for (const auto& [no, cnt] : array) {
		std::cout << no << " has " << cnt << " unique digit(s)\n";

		if (minTUD == 0 || minTUD > cnt)
			minTUD = cnt;
	}

	std::cout << "\nThe smallest TUD is " << minTUD << "\nThese numbers are:\n";

	for (const auto& [no, cnt] : array)
		if (cnt == minTUD)
			std::cout << no << '\n';
}

int main()
{
	while (true) {
		std::cout << "\n"
			"*******************************************\n"
			"*              MENU - HW #2               *\n"
			"*  (1) Calculate TUD                      *\n"
			"*  (2) Quit                               *\n"
			"*******************************************\n\n";
		switch (getInt("Enter option: ")) {
			case 1:
				doTUD();
				break;

			case 2:
				std::cout << "Ok, goodbye!\n";
				return 0;

			default:
				std::cout << "Wrong option, try again\n";
				break;
		}
	}
}




*******************************************
*              MENU - HW #2               *
*  (1) Calculate TUD                      *
*  (2) Quit                               *
*******************************************

Enter option: 1
What is the size of the array: -9
Must be greater than 0
What is the size of the array: 3
Value # 1: 1234
Value # 2: 2222
Value # 3: -456

1234 has 4 unique digit(s)
2222 has 1 unique digit(s)
-456 has 3 unique digit(s)

The smallest TUD is 1
These numbers are:
2222

*******************************************
*              MENU - HW #2               *
*  (1) Calculate TUD                      *
*  (2) Quit                               *
*******************************************

Enter option: 2
Ok, goodbye!

Last edited on
Here is a version of your code that works. I left most variable names the same. See the comments starting with "DMH" for explanations:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include <iostream>
using namespace std;

//Function Prototypes
void getSIWSmallestTUDCWilliamG(int smallestIntWG, int smallestTudWG);
int getIntUDCWilliamG(int integerWG);
void displayClassInfoWilliamG(void);
void runHW2(void);

//Application Driver
int main() {
    // DMH: If main() contains just 1 function then why not put the function's code
    // inside main() instead?
    runHW2();
    return 0;
}

// DMH: I added a stub of this function that wasn't defined in your post.
void displayClassInfoWilliamG()
{
    cout << "DisplayClassInfoWilliamG() not implemented\n";
}

//Function Definition
void runHW2() {
    int inputWG = 0;
    int sizeWG = 0;
    int* arrayWG = { nullptr };
    // int tempTudWG = 10;  DMH: No longer used.
    // int tempWG = 0;      DMH: No longer used.
    int tudWG = 0;
    // int tinyTudWG = 10;  DMH: Not used

    displayClassInfoWilliamG();

    do {
        cout << "\n*******************************************\n"
            "*              MENU - HW #2               *\n"
            "*  (1) Calling getSIWSmallestTUDCWilliamG *\n"
            "*  (2) Quit                               *\n"
            "*******************************************\n";
        cin >> inputWG;

        switch (inputWG) {
        case 1:
        {
            cout << "Calling getSIWSmallestTUDCWilliamG\n" << endl
                << "What is the size of the array?: ";
            cin >> sizeWG;

            while (sizeWG < 1) {
                cout << "\nInvalid input, SizeWG => 1 please. Type again here: ";
                cin >> sizeWG;
                cout << "\n";
            }

            arrayWG = new int[sizeWG];

            for (int i = 0; i < sizeWG; i++) {
                cout << "   Value #" << i + 1 << ": ";
                cin >> arrayWG[i];
            }

	    // DMH: Nice job! It's always a good idea to print the input to verify that you
	    // read it right.
            cout << "The working array has " << sizeWG << " values of\n";

            for (int i = 0; i < sizeWG; i++) {
                cout << "   Value " << i + 1 << ": " << arrayWG[i] << "\n";
            }
            cout << endl;

            cout << "Calling getSIWSmallestTUDCWilliamG() with argument of\n"
                "  (1) The array { ";

	    // DMH ... but here you print it again, which isn't necessary.
            for (int i = 0; i < (sizeWG - 1); i++) {
                cout << arrayWG[i] << " , ";
            }
            cout << arrayWG[sizeWG - 1] << " }; and\n  (2) The array size of " << sizeWG << "\n";

            cout << "\n  For individual values -\n";
	    // DMH: Declare an initialize these close to where they're used. In this case
	    // It prevents the bug that Andy found where you didn't reinitialize smallestTudWG
	    int smallestIdx=0;	// DMH index of smallest number with smallest tud
	    int smallestTudWG = 10;
            for (int i = 0; i < sizeWG; i++) {
		// DMH. Change getIntUDCWilliamG() to accept negative numbers instead.
                // arrayWG[i] > 0 ? tempWG = arrayWG[i] : tempWG = -arrayWG[i];
                tudWG = getIntUDCWilliamG(arrayWG[i]);

                cout << "    " << arrayWG[i] << " has " << tudWG << " unqiue digit(s).\n";

		// DMH: Update smallestTud and smallestIdx
                if (tudWG < smallestTudWG) {
		    smallestTudWG = tudWG;
		    smallestIdx = i;
		} else if (tudWG == smallestTudWG && arrayWG[i] < arrayWG[smallestIdx]) {
		    smallestIdx = i;
		}
            }

            cout << "\nAfter the function call was completed and a value was returned\n\n";
            // DMH: No need to put the output in a function.
	    // Also, functions starting with "get" usually retrieve a value from somewhere.
	    // Yours prints stuff, so the name is very misleading
	    // getSIWSmallestTUDCWilliamG(smallestIntWG, smallestTudWG);
	    cout << "  (1) The smallest TUD is " << smallestTudWG << " and;\n"
		"  (2) " << arrayWG[smallestIdx] << " is the smallest integer with a smallest TUD of " << smallestTudWG;
            cout << "\n";

            // smallestIntWG = 0;  DMH: Not needed since we moved the declaration
            delete[] arrayWG;
            arrayWG = nullptr;
            break;
        }
        case 2:
            cout << "Ok, goodbye!";
            break;
        default:
            cout << "Wrong option, try again\n";
            break;
        }
    } while (inputWG != 2);
}

//Function Definition
int getIntUDCWilliamG(int integerWG) {
    int tudWG = 0;
    int tempArray[10]{ 0 };

    // DMH: change to let it work with negative numbers. That way you don't have to change
    // the input array
    if (integerWG < 0) {
	integerWG = -integerWG;
    }
    
    while (integerWG > 0) {
        tempArray[integerWG % 10]++;
        integerWG /= 10;
    }

    for (int i = 0; i < 10; i++) {
        if (tempArray[i] != 0) {
            tudWG++;
        }
    }
    return tudWG;
}

//Function Definition
void getSIWSmallestTUDCWilliamG(int smallestIntWG, int smallestTudWG) {
    cout << "  (1) The smallest TUD is " << smallestTudWG << " and;\n"
    "  (2) " << smallestIntWG << " is the smallest integer with a smallest TUD of " << smallestTudWG;
}

// DMH: This function wasn't used.
//Function Definition
// int getSIWSmallestTUDCWilliamG(int* arrayWG, int sizeWG); 
Hello everyone,

Thank you for all your wonderful words of advice. Also no worries, I definitely understand that I could have made my code more elegant, and am grateful to have that pointed out as a learning experience. A side note is that the weird variable names and making a run function was all part of my instructor's weird convention.

I have refactored the code to make it more efficient as suggested, but at the end of the day, the main issue was that my "tempTudWG" was declared to 10 instead of 0, which seemed to be cause of the issue. I also took @dhayden 's advice to change up some of those functions so that might have also helped fix the negative number issue. Also @handyandy made an issue fixed by recommending to reset the "smallestTudWG" to 10, I did not take into account to reset the TUD as well.

I still do not understand why this caused negative numbers to fail the program, or why an infinite loop would previously occur with big negatives. If anyone knows why, I'm just curious.

Other than that, hopefully this thread is over, but I will update if I run into any other small issues. Again, really appreciate this community!
Also @HandyAndy you ask above what my for loops is trying to do. The % must not be stored or else I would be dividing by a single digit rather than the whole integer. The purpose is to isolate each digit of an integer and then store it in the appropriate index of the tempArray size 10 (0-9). Then if it is not 0, I can increment TUD. It doesn't matter if the tempArray index is 1, 2, or even 5, because as long as it is not 0 in that array index, it is a unique digit (we don't care how many times it appears, we care if it does appear).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int tudWG = 0;
    int tempArray[10]{ 0 };

    while (integerWG > 0) {
        tempArray[integerWG % 10]++;
        integerWG /= 10;
    }

    for (int i = 0; i < 10; i++) {
        if (tempArray[i] != 0) {
            tudWG++;
        }
    }
    return tudWG;


And @seeplus, I appreciate your extremely small yet efficient solution, but my professor does not allow anything outside of cin and cout, so using anything such as a string class is prohibited. Regardless, I will keep your perspective in mind for future reference because with code it is good to see/solve problems in a variety of ways :-)
Last edited on
Hello WillliamTries2Prog,

In the future when you have an assignment you will given instructions or directions, whatever you call them, Please post the complete instructions along with anything that is allowed or not allowed. This will give those who may respond an idea of what to do or more importantly what code to suggest. This cuds down on code that you can not use.

If there is an input file post it or at least a good sample so everyone will have the same information to use and can see how the file is stored, helps with reading the file.

For a better understand of the tags you can look at http://www.cplusplus.com/articles/z13hAqkS/

For a quick reference the reference section here can help.

For a better reference https://en.cppreference.com/w/

For a good tutorial for reference https://www.learncpp.com/

Andy

Edit: typo
Last edited on
Minor suggestion: In runHW2(), arrayWG can be declared and initialized all on line 57, because you only ever use it within that scope. Likewise, the arrayWG = nullptr at the end is not necessary. You can also simply use a vector and not have to worry about memory leaks.
Last edited on
thank you Handy Andy, I will keep that in mind.

thank you as well Ganado, I didn't think of that. Cheers!
I think the algorithm is wrong as given;
How many unique digits does the number 0 have? Your program reports zero but I count one.

Consider using a loop like this instead:
1
2
3
4
int const radix = 10; 
int digit_counts[radix] = {};

do ++digit_counts[n % radix]; while (n /= radix);
Last edited on
my professor does not allow anything outside of cin and cout, so using anything such as a string class is prohibited


IMO you are not being well served by this professor. string, vector et al are as much part of C++ as for, if etc. You need to be familiar with these (and others) and comfortable with their usage. Part of learning C++ is to develop an understanding of knowing 'which parts' of C++ to use in a situation. Much of this comes with practice and experience - which if you're not allowed to use you won't acquire.
Topic archived. No new replies allowed.