2

I have C program that needs to find the position of a number. It goes like this:

From standard input we enter unknown number of number that are positive. The numbers have maximum of 5 digits, we read new numbers till the user enters a value that is not a number. I need to find the positions of the max digit of a number from right to left. Use the right-most position if there are more than one instance of the max digit.

The program needs to output the position and the number of times the max digit of a number was found at that position.

For example:
input:

97654 48654 12345 12343 1263 12443 12643  12777 #

output:

0: 2
1: 3
2: 1
3: 1
4: 1

because

Position: 4      3        0    1    1     1    2        0
          v      v        v    v    v     v    v        v
          97654 48654 12345 12343 1263 12443 12643  12777 #

THE PROGRAM WORKS FOR THIS SPECIFIC TEST CASE

More test cases under the code.

Here is my code:

#include <stdio.h>

int main(){
    int n;
    int max;
    int num,digit,pos,br0=0,br1=0,br2=0,br3=0,br4=0;
    while (scanf("%d",&n)) {
        max =0;
        num = n;
        pos=0;
        while (num>0) {

            digit = num%10;
            if(digit > max){
                max=digit;
                pos++;
            }
            num/=10;

        }
                    printf("%d\n",pos);
        switch (pos) {
            case 1: br0++; break;
            case 2: br1++; break;
            case 3: br2++; break;
            case 4: br3++; break;
            case 5: br4++; break;
        }
    }
    printf("0: %d\n1: %d\n2: %d\n3: %d\n4: %d\n",br0,br1,br2,br3,br4);
    return 0;
}

This program work for some test cases, such as

97654 48654 12345 12343 1263 12443 12643 12777 #
123 456 789 987 654 321 #

But not for:

542 8965 7452 1111 12 8 6532 98745 15926 #
75386 86142 94285 15926 35724 #
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
itmemilan
  • 331
  • 4
  • 17
  • If needed i can provide you with more test cases :) – itmemilan Nov 18 '21 at 14:53
  • Your desired output is not entirely clear. In the example you give, does the line "0: 2" indicate that 2 of the number in the input have the maximum value in the rightmost digit? – William Pursell Nov 18 '21 at 14:57
  • @WilliamPursell 0 is the position and 2 is the number of max digits that are on that position... – itmemilan Nov 18 '21 at 14:58
  • for input:542 8965 7452 1111 12 8 6532 98745 15926 #
    theprogram need to output: 0:3 1: 0 2: 3 3: 2 4: 1
    – itmemilan Nov 18 '21 at 14:59
  • Incrementing `pos` when `digit > max` is not the correct logic. – William Pursell Nov 18 '21 at 15:00
  • @WilliamPursell do you have any idea how to find the position of a max digit in a number ? – itmemilan Nov 18 '21 at 15:01
  • 3
    You need to increment `pos` every time you shift the number, and recall the value of `pos` when the max is attained. – William Pursell Nov 18 '21 at 15:01
  • Are you looking for the _largest_ integer in a set, or looking for the set that has the highest count of integers? – ryyker Nov 18 '21 at 15:02
  • @WilliamPursell if its not a problem can you explain that more and you can put in in answers so i can give you credit for helping me.. – itmemilan Nov 18 '21 at 15:03
  • @itmemilan It is unclear what this output 0: 2 means. – Vlad from Moscow Nov 18 '21 at 15:05
  • @ryyker i enter numbers and for every number i find the max digit and the position of that digit, i remember the positions and increment them by one because i only enter numbers that are not more that 5 digits long i can do that with 5 variables in the end i output the number of positions that are found of every number.. i don't know how to explain it, not 2 good English :D – itmemilan Nov 18 '21 at 15:07
  • @VladfromMoscow i remember you, you have answered one question a year ago :D, the 0 means that on position 0 the count of max digits of a number is 2 – itmemilan Nov 18 '21 at 15:08
  • @VladfromMoscow for example 123 we get 0 : 1 – itmemilan Nov 18 '21 at 15:09
  • @VladfromMoscow hmm i think its ok starting from case 1: because every number have a digit that is max . Or i am wrong can you explain more ? – itmemilan Nov 18 '21 at 15:12
  • I found simple example where my program does not work for example if the input is 98745 the outputs is 3 : 1,but it should be 4 : 1, and the position is 4 where it should be 5. – itmemilan Nov 18 '21 at 15:14
  • it works for 98754 – itmemilan Nov 18 '21 at 15:14
  • 3
    Tip: It would make more sense to use an array of five elements rather than 5 vars. Var named `foo#` are red flags. – ikegami Nov 18 '21 at 15:24
  • The output will always be wrong for numbers where you find descending numbers before you get to the maximum. `98765`: OK, `98756`: NOK because you won't increment `pos` when you check the `5`. – Gerhardh Nov 18 '21 at 15:30

3 Answers3

2

The problem with your program is that within this loop

    while (num>0) {

        digit = num%10;
        if(digit > max){
            max=digit;
            pos++;
        }
        num/=10;

    }

the variable pos is incremented only when a digit that is greater than previous digits is found. For example If you have a number like this

51234 

then the first largest digit is 4 and the variable pos is set to 1. After that when the next largest digit is found that is the digit 5 the variable pos is incremented and becomes equal to 2 while actually the largest digit 5 is at the position 5.

You need to introduce one more variable as for example

    max =0;
    num = n;
    pos=1;

    int i = 1;

    do
    {
        digit = num%10;
        if(digit > max){
            max=digit;
            pos = i;
        }
     } while ( ( num /=10 ) && ( i++ != 5 ) );

I would write the program the following way

#include <stdio.h>

int main(void) 
{
    enum { N = 5 };
    const unsigned int Base = 10;
    
    size_t total[N] = { 0 };
    
    unsigned int n;
    
    while ( scanf( "%u", &n ) == 1 )
    {
        unsigned int pos = 0;
        unsigned int max_digit = 0;
        unsigned int i = 0;
        
        do
        {
            unsigned int current_digit = n % Base;
            
            if ( max_digit < current_digit )
            {
                pos = i;
                max_digit = current_digit;
            }
        } while ( ( n /= Base ) && ( ++i != N ) );
        
        ++total[pos];
    }
    
    for ( unsigned int i = 0; i < N; i++ )
    {
        printf( "%u: %zu\n", i, total[i] );
    }
    
    return 0;
}

For the input

542 8965 7452 1111 12 8 6532 98745 15926 #

the program output is

0: 3
1: 0
2: 3
3: 2
4: 1
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

It may be fewer steps to do the work using fgets(), and keeping the input in string format. (verifying that it contains numeric characters.) Plus, an array of values will be easier to keep tract of value to index relationships.

Here is an alternate way of getting the information you describe:

int main(void) {
    char inBuf[20] = {0};
    int index = 0;
    int loops = 0;
    int maxPos = 0;
    int maxVal = 0;
    
    printf("Enter a number : ");
    while (fgets(inBuf, sizeof inBuf, stdin) && loops < 6) {
        
        inBuf[strcspn(inBuf, "\r\n")] = 0;//remove unwanted white space
         if(strstr(inBuf, "#")) return 0;//exit if "#"
        if(digits_only(inBuf))
        {
            index = 0;
            maxVal = inBuf[index];
            while(inBuf[index])
            {
                if(inBuf[index] >= maxVal)
                {
                   maxVal = inBuf[index];
                   maxPos = index;
                }
                index++;                    
            }
            printf("%d:%d \n", loops, maxPos);
            loops++;
            inBuf[0]=0;

        }
        else
        {
            printf("\n%s contains non-numeric characters, it cannot be converted.\n\nctrl-c to exit\n...Or enter a number : \n", inBuf);
        }
    };
    return 0;
}
ryyker
  • 22,849
  • 3
  • 43
  • 87
0

scanf is the wrong tool for this. (scanf is (almost) always the wrong tool). For this particular problem, you really want to treat the input as a string. As long as you don't want to accept inputs that look like "1e3" (which is a perfectly valid representation of an integer), you could just do something like:

#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <string.h>

int
main(void){
    int max = -1;
    int br[5] = {0};
    int maxpos = -1;
    int len = 0;
    int c;
    while( (c = getchar()) != EOF ){
        if( c && strchr("0123456789", c) ){
            if( ++len > 5 ){
                fputs("invalid input\n", stderr);
                return 1;
            }
            assert( len > 0 && len < 6 );
            if( c > max + '0' ){
                maxpos = len;
                max = c - '0';
            }
        } else if( isspace(c) ){
            if( max > -1 ){
                br[len - maxpos] += 1;
            }
            maxpos = -1;
            len = 0;
            max = '0' - 1;
        } else {
            fputs("invalid input\n", stderr);
            return 1;
        }
    }
    for( int i = 0; i < 5; i++ ){
        printf("%d: %d\n", i, br[i]);
    }
    return 0;
}
William Pursell
  • 204,365
  • 48
  • 270
  • 300
  • Why do you think `scanf()` is the wrong tool for this? It seems like a programming contest question, where the input is strictly defined and error handling and corner cases are out of scope. So `scanf()` would do its job perfectly fine. It would let the programmer focus on the algorithm part of the question, which is where the real flaw is in this case. – wovano Nov 18 '21 at 16:36
  • @wovano I think scanf is the wrong tool because you really want to treat the input as a string rather than using `scanf` to convert it to an integer. Once you realize that you want to treat the input as a string, it is simpler to just use `getchar` and never bother with the conversion. – William Pursell Nov 18 '21 at 16:39
  • Ah, okay, I can see the point of not doing integer magic but just using string comparisons. Although it seems you will need to do an equal (or larger?) amount of string stuff instead, so personally I would prefer the integer approach. But Your Mileage May Vary. – wovano Nov 18 '21 at 16:46