The condition of the problem is as follows: Transfer a number from a number system with base b1 to a system with base b2 (b1 and b2 are greater than 2 but less than 16), and it can be real and can contain as few as 13 characters, including a period.

At first I tried to do a character-by-character read, without connecting additional memory, but gave up and introduced an array, which was initially filled with the numbers -2. The transform function should read all the entered characters and convert them to numbers in an array. The point is replaced by the number -1. This raises the first problem. Transform should work exactly as many times as the characters were entered and should not touch other cells of the array. But when entering large real numbers, the cells of the array at the end are for some reason overwritten by large numbers. There is also a decimal function; it translates numbers from any number system to decimal. But when the program is executed, it displays a multi-digit number that is not the answer. Help me understand what the problem is, I will be very grateful!

#include <stdio.h> #include <stdlib.h> #include <math.h> int counter = -1, i = -1, j = -1; void transform(int* array_F) { int x = getchar(); if (x == '\n') return ; j++; if( x != '.') { if ((x - 'A') >= 0) array_F[j] = x - 'A' + 10; else array_F[j] = x - '0'; } else array_F[j] = -1; transform(array_F); } void fractional(int first_ss, float* number_F, int* array_F) { for(j = i+1; array_F[j]!= -2; j++) *number_F += (float)((array_F[j]) * pow(first_ss, -1*j)); } void decimal(int first_ss, int* array_F, float* number_F) { i++; if (array_F[i] == -2) return; if (array_F[i] == -1) { fractional(first_ss, number_F, array_F); return; } decimal(first_ss, array_F, number_F); counter++; *number_F += (float)(array_F[i - counter] * pow(first_ss, counter)); } 
  • If you are talking about this: for (i = 0; i <j + 8; i ++) printf ("% d", array [i]); I forgot to delete this cycle. I have it in order to check the values ​​of the array. - Alex
  • And what should you do if the result is infinite? For example, when translating ternary 0.1 into the decimal system, the result is 0.333... infinite (periodic). Just cut back on length (same 13 characters)? Or search for a period and use () notation? - AnT
  • Please determine the constraints for the input dataset. For now, I guess these are numbers and capital Latin letters. So? In this case, I would recommend not to reinvent the wheel, but to use isalnum (), isupper () and isdigit (). - Alexander Amelkin

1 answer 1

You are trying to divide the functionality between functions in a very strange way. If the transform() function is to perform an intermediate conversion of characters into numbers, then there is no need to impose on it also a data entry function. With the input of string data, the scanf() function does an excellent job. Moreover, it also has the ability to allocate memory for the lines entered ( %a ). If you don’t want to do memory allocation at all (even with scanf() ), then for character processing, the getchar() function can be called from an external function, passing the result inside the transform() . Leave the transform() function only for its proper actions.

For some reason, instead of passing a pointer to the current position in the array being processed by the recursion parameter in decimal() , you pass the address of the beginning of the array, and the pointer (more precisely, the index) goes in your global variable. Yes, in fact, recursion is completely unnecessary in this case, but only consumes extra space on the stack.

Global variables are evil. Data coupling between the functions must be zero if there is no vital necessity. Implicit function input parameters are evil. All data transfer must be done through arguments. Otherwise, in the future (with a more serious code and a larger scale of the project), huge problems of the “hemorrhoid” class are inevitable.

Moreover, these problems are already present in your code right now, since The transform() function works on the assumption that j is -1 at the start, however, if someone calls transform() several times, especially after calling decimal() -> fractional() , then at the entrance to tranform() variable j will have garbage value.

At the same time, ANYWHERE is not controlled anywhere beyond the bounds of the Array_F array! This guarantees problems. Actually this is the previous one - probably the root of the problems you have. In addition, printed but non-valid characters (spaces, punctuation marks other than dots, etc.) are not processed in any way.

It’s not at all clear why the decimal() function is needed if it actually complements the transform() functionality. And it does not translate into decimal form at all, but simply transforms an array of individual digits of an arbitrary number system created by the transform() function into a regular float number. It is NOT decimal at all. Rather, the binary is in IEEE754 format. It would be logical to combine all these three functions into one.

In general, I would completely redo this code like this:

 #include <stdio.h> #include <ctype.h> #include <math.h> double transform_char(double in, char c, int base, int fractional_position) { int i; if(isalnum(c)) { if(isdigit(c)) { i = c - '0'; } else if(isalpha(c)) { if(isupper(c)) { i = c - 'A' + 10; } else { i = c - 'a' + 10; } } if(i > base - 1) { return -NAN; } if(!fractional_position) { in *= base; in += i; } else { double frac = in - (int)in; in -= frac; frac += (double)i / pow(base, (double)fractional_position); in += frac; } } return in; } 

This function processes the string character by character. For the integer part, the fractional_position parameter must be zero. After detecting a point symbol in the incoming stream, it is necessary to set the parameter to 1 and then increment after each next processed symbol:

 #include <stdbool.h> #include <stdlib.h> ... int input_base; double res = 0.0; char c = 0; bool fraction = false; int pos = 0; ... // Инициализация input_base где-то тут while((c = getchar()) != '\n') { int i; printf("%c: %g -> ", c, res); if(isalnum(c)) { res = transform_char(res, c, input_base, pos); if(isnan(res)) { fprintf(stderr, "Invalid digit %c for base %d\n", c, input_base); break; } if(pos) pos++; } else if('.' == c) { fraction = true; pos = 1; } else { fprintf(stderr, "Invalid character %c\n", c); return 1; } printf("%g\n", res); } 

At the same time I draw your attention to the fact that the inverse transformation is a more complicated task. Although your limit of 13 characters makes it much easier. Solutions are set forth, for example, here: https://stackoverflow.com/questions/7228438/convert-double-float-to-string

Please also note that my code (like yours) does not know how to handle negative numbers, but this is easy to fix.