Find the position of a max on a number - c

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 #

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

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;
}

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;
}

Related

Stop getting user inputs when enter is pressed (C language)

I am super new to programming and I am having a problem with one of the questions where i am supposed to write a C program to let the user enter some numbers and sort the entered elements and find the median of it. And it should stop getting inputs once the user presses enter.
this is my code and idk where it went wrong(btw sorry for asking such a simple question)
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
int i = 0;
int j,k,m,num;
int arr[20];
while(i<20 )
{
printf("Enter a number: ");
scanf("%d",&num);
if(num == '\n') break;
arr[i] = num;
i++;
}
n = sizeof(arr)/sizeof(arr[0]);
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(arr[i] < arr[j])
{
k = arr[i];
arr[i] = arr[j];
arr[j] = k;
}
}
}
if(n%2 != 0)
{
printf("The median is %d", arr[n/2] ) ;
}
else printf("The median is %.2f", arr[(n-1)/2] + arr[n/2]/2.0);
return 0;
}
If you want to stop on empty line, you cannot use scanf. The reason is that scanf("%d", ...) skips all whitespace characters from user input while waiting for the use to enter a number. Here "whitespace" includes the new-line character '\n'. So the user cannot make scanf return by pressing Enter - only an end-of-file (Ctrl+D on linux) or bogus input (non-number) will make scanf return.
So you have to replace scanf by the combination fgets+sscanf. Consider the following code:
while (i < 20)
{
int num;
char str[15];
printf("Enter a number: ");
if (!fgets(str, sizeof str, stdin))
break;
if (sscanf(str, "%d", &num) != 1)
break;
arr[i] = num;
i++;
}
It uses fgets to input a line of input, and sscanf to parse that line. If there is nothing in the line, sscanf will fail (it returns 1 for success; any other value for failure).
Notes:
If input is too long, it will be split into two lines, which will be surprising for the user
If the user inputs more than one number on the line, extra numbers will be silently ignored
The condition of fgets's return value terminates user input also on end-of-file; this is good if you supply input to your program by redirecting it from a file
Input could be processed character by character until either twenty integers are stored or a newline is found.
As digits are read, accumulate them into a value, checking for overflow.
Upon reading whitespace or another character, store the values in the array.
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
int main ( void) {
int ch = 0;
int value = 0;
int sign = 1;
int digits = 0;
int arr[20] = { 0};
int n = 0;
int i = 0;
int j = 0;
int k = 0;
while ( n < 20) {
while ( EOF != ( ch = fgetc ( stdin))) {//read a character
if ( isdigit ( ( unsigned char)ch)) {
ch -= '0';//character to int as '1' to 1
digits = 1;
if ( 1 == sign) {
if ( value < ( INT_MAX / 10) - ch) {
value *= 10;
value += ch;
}
else {
printf ( "overflow! reset to + and zero\n");
value = 0;
sign = 1;
digits = 0;
}
}
if ( -1 == sign) {
if ( value > ( INT_MIN / 10) + ch) {
value *= 10;
value -= ch;
}
else {
printf ( "overflow! reset to + and zero\n");
value = 0;
sign = 1;
digits = 0;
}
}
}
else if ( '-' == ch || '+' == ch) {
if ( digits) {
printf ( "invalid sign! reset to + and zero\n");
value = 0;
sign = 1;
digits = 0;
}
else {
sign = ( '-' == ch) ? -1 : 1;
}
}
else if ( digits) {
arr[n] = value;
value = 0;//reset to zero
sign = 1;//reset to +
++n;
digits = 0;
}
if ( '\n' == ch) {
break;
}
}
if ( '\n' == ch || EOF == ch) {
break;
}
}
for ( i = 0; i < n; i++) {
for ( j = i + 1; j < n; j++) {
if ( arr[i] < arr[j]) {
k = arr[i];
arr[i] = arr[j];
arr[j] = k;
}
}
}
for ( i = 0; i < n; i++) {
printf ( "arr[%d] = %d\n", i, arr[i]);
}
if ( n % 2 != 0) {
printf ( "The median is %d\n", arr[n/2]);
}
else {
printf ( "The median is %.2f\n", ( arr[( n - 1) / 2] + arr[n / 2] ) /2.0);
}
return 0;
}
Input and output:
9 1 82 0 3
arr[0] = 82
arr[1] = 9
arr[2] = 3
arr[3] = 1
arr[4] = 0
The median is 3

can anyone simplify this code for me in c?

The sum of all odd digits of n.(eg. n is 32677, the sum would be 3+7+7=17)
Here is the code.
For this question, any of loop or function is acceptable, but not longer than this answer.
#include <stdio.h>
int main()
{
char n[20];
int m=0,i;
printf("Enter integers for the variable n: ");
for (i=0;i<20;i++)
{
scanf("%c",&n[i]);
if(n[i]=='\n')
{
break;
}
}
for (i=0;i<20;i++)// this is the part I would like to simplified
{
if (n[i]%2!=0)
{
if(n[i]==49)
m++;
if(n[i]==51)
m+=3;
if(n[i]==53)
m+=5;
if(n[i]==55)
m+=7;
else if(n[i]==57)
m+=9;
}
}
printf("The sum of odd digits of n is %d.",m);
}
Here are some tools/ideas you can use:
In ctype.h is a function isdigit() which tells you whether or not a character represents a digit.
Assuming the characters for the digits 0..9 are in sequence, the value represented by a character digit c is c-'0'
Here you are
#include <stdio.h>
int main( void )
{
enum { N = 20 };
char value[N];
printf( "Enter an unsigned integer: " );
size_t n = 0;
for ( char digit; n < N && scanf( "%c", &digit ) == 1 && digit != '\n'; ++n )
{
value[n] = digit;
}
unsigned int sum = 0;
for ( size_t i = 0; i < n; i++ )
{
if ( value[i] % 2 != 0 ) sum += value[i] - '0';
}
printf( "The sum of odd digits of the value is %u.\n", sum );
}
The program output might look like
Enter an unsigned integer: 0123456789
The sum of odd digits of the value is 25
Or you can add a check that an entered character is a digit. For example
#include <stdio.h>
#include <ctype.h>
int main( void )
{
enum { N = 20 };
char value[N];
printf( "Enter an unsigned integer: " );
size_t n = 0;
for ( char digit;
n < N && scanf( "%c", &digit ) == 1 && isdigit( ( unsigned char )digit );
++n )
{
value[n] = digit;
}
unsigned int sum = 0;
for ( size_t i = 0; i < n; i++ )
{
if ( value[i] % 2 != 0 ) sum += value[i] - '0';
}
printf( "The sum of odd digits of the value is %u\n", sum );
}
As for your code then in this loop
for (i=0;i<20;i++)
{
scanf("%c",&n[i]);
if(n[i]=='\n')
{
break;
}
}
you have to count how many digits were entered. And the new line character shall not be stored in the array. Otherwise this loop
for (i=0;i<20;i++)
can result in undefined behavior.
And you should not use magic numbers like for example 49.

Count frequency of digits in string

I need to implement a function that can count the number of digits in a string. So for numbers but also for somehting like: aD23b. If I could make it work...it should look like:
Input: 0912302
Output:
0: 2
1: 1
2: 2
3: 1
4: 0
5: 0
6: 0
7: 0
8: 0
9: 1
At this point I can't code anything that works unfortunately...My basic idea is: Use a loop to check every character from Input, if it's a digit, store it in a second array (let's say frequency). The problems I have are that I need to somehow convert every character into a integer or somehow be able to count how
often each digits appears... I was hoping this might work but it doesn't at all:
I forgot to mention I'm a beginner in programming so I would really appreciate if you could give me tips and explanations.
void calc_occurrences(int s[], int occurrences[])
{
int i = 0;
int j;
int count = 0;
while (s[i] != '\0') {
if (isdigit(s[i])) {
for (j = 0; occurrences[j] != '\0'; j++) {
occurrences[j] = s[i];
}
}
i++;
for (j = i + 1; s[j] != '\0'; j++) {
if (isdigit(s[i]) == isdigit(s[j])) {
count++;
occurrences[j] = 0;
}
}
if(occurrences[i] != 0) {
occurrences[i] = count;
}
}
}
Make an array to count the frequency of each relevant character.
Something like this:
#include <stdio.h>
void count_freq(char* str, int freq[10])
{
int i = 0;
while(str[i]) // Loop to end of string
{
if (str[i] >= '0' && str[i] <= '9') // Check that the character is in range
{
++freq[str[i]-'0']; // notice the -'0' to get in range 0..9
}
++i;
}
}
int main(void) {
int freq[10] = {0}; // Array to count occurence
char str[] = "0034364hh324h34"; // Input string
count_freq(str, freq); // Calculate frequency
for (int i=0; i < 10; ++i) // Print result
{
printf("%d: %d\n", i, freq[i]);
}
return 0;
}
Output:
0: 2
1: 0
2: 1
3: 4
4: 4
5: 0
6: 1
7: 0
8: 0
9: 0
You can have an integer array with size 10 with 0 stored in all indices. Then, when you spot a digit, you can increment the number in the respective index.
In example, when you see a "0", you can do arr[0]++;.
Also, you may check if a character is a digit with the isdigit() function.
PS : I know, I'm answering an old post, but I was doing some challenges on HackerRank, and I managed to solve this nearly exact problem, in case it might help someone since I've used dynamic allocation on my code.
/* Problem: hackkerrank.com/challenges/frequency-of-digits-1/problem */
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main(void)
{
char *s;
int *arr;
int i;
i = 0;
s = (char*)malloc(sizeof(char));
scanf("%s", s);
arr = (int*)malloc(10 * sizeof(int));
while(i < 10)
{
*(arr + i) = 0;
i++;
}
i = 0;
while (i < strlen(s))
{
if (*(s + i) >= '0' && *(s + i) <= '9')
{
(*(arr + (*(s + i) - '0'))) += 1;
}
i++;
}
i = 0;
while (i < 10)
{
printf("%d ", *(arr + i)); // As HackerRank problem wanted the output format.
// printf("%d: %d\n", i, *(arr + i)); As you wanted it
i++;
}
return (0);
}

checking for float in string

Hello I would like to check for a float number in string
#include<stdio.h>
#include <math.h>
#include <ctype.h>
#include <stdlib.h>
int main(void)
{
char qihjuq[] = "a s d a s d g g 1 2 3 1 2 3 5 5.4 d 10.4";
int num[256];
float digit[256];
char let[256] = {"0"};
int lcounter =0;
int ncounter =0;
int dcounter =0;
for(int i =0; i< sizeof qihjuq; i++)
{
if(isalpha(*(qihjuq+i))) {
let[lcounter] = *(qihjuq + i);
lcounter++;
}
else if(isdigit(*(qihjuq+i)) && *(qihjuq+i+1) != '.') {
num[ncounter] = *(qihjuq + i);
ncounter++;
}
else if(roundf(*(qihjuq+i)) != *(qihjuq+i)) {
digit[dcounter] = *(qihjuq + i);
dcounter++;
}
}
printf("The letters are: \n");
for(int i =0; i< lcounter; i++)
printf("%c ",let[i]);
printf("The whole numbers are: \n");
for(int i =0; i< ncounter; i++)
printf("%c ",num[i]);
}
The problem lies in the second and third if
else if(isdigit(*(qihjuq+i)) && *(qihjuq+i+1) != '.') {
num[ncounter] = *(qihjuq + i);
ncounter++;
}
else if(roundf(*(qihjuq+i)) != *(qihjuq+i)) {
digit[dcounter] = *(qihjuq + i);
dcounter++;
}
where the program has to detect whether the is float or integer. The problem is that the program is detecting 10.4 as individual characters which in turn puts 1 0 4 in the whole number to try to negate this I added a detection for . but still has logical errors since the condition does not include the numbers behind the .
like this:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void){
char qihjuq[] = "a s d a s d g g 1 2 3 1 2 3 5 5.4 d 10.4";
int num[256];
float digit[256];
char let[256];
int lcounter =0;
int ncounter =0;
int dcounter =0;
for(int i = 0; i < sizeof(qihjuq) -1; i++){
if(isspace(qihjuq[i]))
continue;//skip spaces
char work[256] = {0};
for(int j = 0; qihjuq[i] && !isspace(qihjuq[i]); ++j, ++i)
work[j] = qihjuq[i];//Extraction
--i;//for next loop
if(isalpha(*work) && !work[1]) {//one letter
let[lcounter++] = *work;
} else {
char *p = work;
int n = strtol(p, &p, 10);
if(!*p)//convert to int succeeded (Not strict)
num[ncounter++] = n;
else {
p = work;
float f = strtod(p, &p);
if(!*p)//convert to float succeeded (Not strict)
digit[dcounter++] = f;
}
}
}
printf("The letters are: \n");
for(int i = 0; i < lcounter; i++)
printf("%c ", let[i]);
printf("\nThe whole numbers are: \n");
for(int i = 0; i < ncounter; i++)
printf("%d ", num[i]);
puts("");
}
I do not understand your approach.
You have – let's call it – tokens in a string separated by spaces. You can neither detect the kind of a token nor the value of that token by simply looking on one character.
You have two options: (Logically they are the same, but the implementation is different.)
You iterate over the string extracting the tokens and then iterate over each token to detect its kind.
You iterate over the string and recursively iterate over a token.
Like so (typped in browser)
char *char_ptr = qihjuq;
do
{
if( char_ptr == ' ')
{
continue
}
// iterate overe the next token
int char_set = 0x0;
char * start_ptr = char_ptr; // The start of an item
do
{
if( isdigit( *char_ptr) )
{
char_set |= 0x01; // contains digit
}
else if( *char_ptr == '.' )
{
char_set |= 0x02; // contains period
}
else if( isalpha( *char_ptr ))
{
char_set |= 0x04;
}
break; // any other character breaks item
} while( *char_ptr++ );
// integers have 0x01, floats have 0x3. Other values are alphas or alphanumerics
// you can store the result into an array, do some processing with them or whatever you want. start_ptr points to the beginning of the item_char_ptr to one char after the end.
} while ( *char_ptr++ )
Likely there are some bugs, but this is the structure.
Just read a double with strtod().
If it works, the end pointer points to the position to read from; if it doesn't work advance by 1.
Keep at it until the end of the string
/* code untested */
double x;
char *end
char qihjuq[] = "a s d a s d g g 1 2 3 1 2 3 5 5.4 d 10.4";
char *p = qihjuq;
while (*p) {
errno = 0;
x = strtod(p, &end);
if (errno) {
p += 1;
} else {
printf("found %f\n", x);
p = end;
}
}

scan n numbers without spaces in C

Suppose n numbers are to be input in a single line without any spaces given the condition that these numbers are subject to the condition that they lie between 1 and 10.
Say n is 6 , then let the input be like "239435"
then if I have an array in which I am storing these numbers then I should get
array[0]=2
array[1]=3
array[2]=9
array[3]=4
array[4]=3
I can get the above result by using array[0]=(input/10^n) and then the next digit
but is there a simpler way to do it?
Just subtract the ASCII code of 0 for each digit and you get the value of it.
char *s = "239435"
int l = strlen(s);
int *array = malloc(sizeof(int)*l);
int i;
for(i = 0; i < l; i++)
array[i] = s[i]-'0';
update
Assuming that 0 is not a valid input and only numbers between 1-10 are allowed:
char *s = "239435"
int l = strlen(s);
int *array = malloc(sizeof(int)*l);
int i = 0;
while(*s != 0)
{
if(!isdigit(*s))
{
// error, the user entered something else
}
int v = array[i] = *s -'0';
// If the digit is '0' it should have been '10' and the previous number
// has to be adjusted, as it would be '1'. The '0' characater is skipped.
if(v == 0)
{
if(i == 0)
{
// Error, first digit was '0'
}
// Check if an input was something like '23407'
if(array[i-1] != 1)
{
// Error, invalid number
}
array[i-1] = 10;
}
else
array[i] = v;
s++;
}
E.g.
int a[6];
printf(">");
scanf("%1d%1d%1d%1d%1d%1d", a,a+1,a+2,a+3,a+4,a+5);
printf("%d,%d,%d,%d,%d,%d\n", a[0],a[1],a[2],a[3],a[4],a[5]);
result:
>239435
2,3,9,4,3,5
You can use a string to take the input and then check each position and extact them and store in an array. You need to check for the numeric value in each location explicitly, as you are accepting the input as a string. For integers taken input as string, there's no gurantee that the input is pure numeric and if it is not, things can go wild.
check this code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char ipstring[64];
int arr[64];
int count, len = 0;
printf("Enter the numbersi[not more than 64 numbers]\n");
scanf("%s", ipstring);
len = strlen(ipstring);
for (count = 0; count < len ; count++)
{
if (('0'<= ipstring[count]) && (ipstring[count] <= '9'))
{
arr[count] = ipstring[count] - '0';
}
else
{
printf("Invalid input detectde in position %d of %s\n", count+1, ipstring );
exit(-1);
}
}
//display
for (count = 0; count < len ; count++)
{
printf("arr[%d] = %d\n", count, arr[count]);
}
return 0;
}

Resources