Funzione di conversione da alfanumerici a numerici - esempi in C
Tutti i linguaggi di programmazione hanno funzioni per convertire alfanumerici che rappresentano interi in interi.
Quando digitate sulla testiera la sequenza di caratteri '1' '2' e '3' questi vengono convertiti nella rispettiva codifica binaria in base alla tabella ad esempio ASCII. Quindi il carattere '1' verrà codificato in un byte con il valore binario di 49 decimale, il carattere '2' in un byte con il valore binario di 50 decimale e 3 in un byte con il valore binario di 51 decimale.
Quindi:
La sequenza 123 viene codificata in 3 byte
uno per ogni carattere, in base alla codifica ASCII:
| 49| 50| 51|
in binario:
|00110001|00110010|00110011|
E' necessario per eseguire i calcoli è necessario convertire questa sequenza di caratteri nell'intero corrispondente. Tutti i linguaggi di programmazione hanno delle funzioni che permettono questa conversione, ad esempio in C la funzione atoi:
int atoi (const char * str);
Converte una sequenza di caratteri in un intero.
Un esempio di utilizzo:
/* atoi example */
#include <stdio.h> /* printf, fgets */
#include <stdlib.h> /* atoi */
int main ()
{
int i;
char buffer[256];
printf ("Enter a number: ");
fgets (buffer, 256, stdin);
i = atoi (buffer);
printf ("The value entered is %d. Its double is %d.\n", i, i*2);
return 0;
}
L'output:
Enter a number: 73
The value entered is 73. Its double is 146.
Può essere utile fare una nostra implementazione semplice della funzione atoi per capire come convertire una sequenza di caratteri che rappresentano un intero in una variabile di tipo intero.
Sotto una semplice implementazione:
// Program to implement atoi() in C
#include <stdio.h>
// A simple atoi() function
int myAtoi(char str[])
{
// Initialize result
int res = 0;
// Iterate through all characters
// of input string and update result
// take ASCII character of corosponding digit and
// subtract the code from '0' to get numerical
// value and multiply res by 10 to shuffle
// digits left to update running total
for (int i = 0; str[i] != '\0'; ++i)
res = res * 10 + str[i] - '0';
// return result.
return res;
}
// Driver Code
int main()
{
char str[] = "89789";
// Function call
int val = myAtoi(str);
printf("%d ", val);
return 0;
}
Una implementazione un più controlli sull'input e che gestisca i negativi. Se il primo carattere è '-' allora setta il segno a negativo e converte il testo della sequenza di caratteri (stringa) come numero utilizzando l'approccio precedente e poi moltiplicando il risultato per il segno:
// A C program for
// implementation of atoi
#include <stdio.h>
// A simple atoi() function
int myAtoi(char str[])
{
// Initialize result
int res = 0;
// Initialize sign as positive
int sign = 1;
// Initialize index of first digit
int i = 0;
// If number is negative,
// then update sign
if (str[0] == '-') {
sign = -1;
// Also update index of first digit
i++;
}
// Iterate through all digits
// and update the result
for (; str[i] != '\0'; ++i)
res = res * 10 + str[i] - '0';
// Return result with sign
return sign * res;
}
// Driver code
int main()
{
char str[] = "-123";
// Function call
int val = myAtoi(str);
printf("%d ", val);
return 0;
}
Questa implementazione gestisce vari tipi di errore. Se str è NULL o str non contiene caratteri numerici allora ritorna 0 come numero non valido.
// A simple C++ program for
// implementation of atoi
#include <stdio.h>
// A utility function to check
// whether x is numeric
bool isNumericChar(char x)
{
return (x >= '0' && x <= '9') ? true : false;
}
// A simple atoi() function.
// If the given string contains
// any invalid character, then
// this function returns 0
int myAtoi(char str[])
{
if (str[0] == '\0')
return 0;
// Initialize result
int res = 0;
// Initialize sign as positive
int sign = 1;
// Initialize index of first digit
int i = 0;
// If number is negative,
// then update sign
if (str[0] == '-')
{
sign = -1;
// Also update index of first digit
i++;
}
// Iterate through all digits of
// input string and update result
for (; str[i] != '\0'; ++i)
{
// You may add some lines
// to write error message
if (isNumericChar(str[i]) == false)
return 0;
// to error stream
res = res * 10 + str[i] - '0';
}
// Return result with sign
return sign * res;
}
// Driver program to test above function
int main()
{
char str[] = "-134";
int val = myAtoi(str);
printf("%d ", val);
return 0;
}
L'output:
-134
Un'ultima implementazione, che gestisce i quattro casi limite:
Simulazione del comportamento con un dato di input:
L'implementazione:
// A simple C program for
// implementation of atoi
#include <stdio.h>
#include <limits.h>
int myAtoi(const char str[])
{
int sign = 1, base = 0, i = 0;
// if whitespaces then ignore.
while (str[i] == ' ')
{
i++;
}
// sign of number
if (str[i] == '-' || str[i] == '+')
{
sign = 1 - 2 * (str[i++] == '-');
}
// checking for valid input
while (str[i] >= '0' && str[i] <= '9')
{
// handling overflow test case
if (base > INT_MAX / 10
|| (base == INT_MAX / 10
&& str[i] - '0' > 7))
{
if (sign == 1)
return INT_MAX;
else
return INT_MIN;
}
base = 10 * base + (str[i++] - '0');
}
return base * sign;
}
// Driver Code
int main()
{
char str[] = " -123";
// Functional Code
int val = myAtoi(str);
printf("%d ", val);
return 0;
}
// This code is contributed by Yogesh shukla.
L'output:
-123
Complexity Analysis for all the above Approaches:
Time Complexity: O(n).
Only one traversal of string is needed.
Space Complexity: O(1).
As no extra space is required.
Convertire da intero a sequenza di caratteri
Nel linguaggio C, la funzione itoa, esegue la funzionalità inversa, cioè converte un intero nella corrispondente sequenza di caratteri ASCII.
char * itoa ( int value, char * str, int base );
Esempio di utilizzo della funzione:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int a=54325;
char buffer[20];
itoa(a,buffer,2); // here 2 means binary
printf("Binary value = %s\n", buffer);
itoa(a,buffer,10); // here 10 means decimal
printf("Decimal value = %s\n", buffer);
itoa(a,buffer,16); // here 16 means Hexadecimal
printf("Hexadecimal value = %s\n", buffer);
return 0;
}
L'output:
Binary value = 1101010000110101
Decimal value = 54325
Hexadecimal value = D435
Siccome in C itoa non è una funzione dello standard C non è presente in molti compilatori (contrariamente ad atoi che fa parte dello standard C).
Il primo deve essere una variabile di tipo char *, che significa che tu puoi utilizzare un array di char, ma bisogna che sia abbastanza grande da contenere il numero convertito.
Il secondo argomento è la stringa contenente la specifica del formato, dipendendo sul formato del numero che si vuole convertire.
Il terzo argomento è il numero che si vuole convertire a stringa.
sprintf ritorna il numero di caratteri della stringa (senza però il carattere null).
Questo esempio converte alcuni numeri in formato stringa, a stampa in output il risultato:
#include <stdio.h>
int main() {
char str[10]; /* MUST be big enough to hold all
the characters of your number!! */
int i;
i = sprintf(str, "%o", 15);
printf("15 in octal is %s\n", str);
printf("sprintf returns: %d\n\n", i);
i = sprintf(str, "%d", 15);
printf("15 in decimal is %s\n", str);
printf("sprintf returns: %d\n\n", i);
i = sprintf(str, "%x", 15);
printf("15 in hex is %s\n", str);
printf("sprintf returns: %d\n\n", i);
i = sprintf(str, "%f", 15.05);
printf("15.05 as a string is %s\n", str);
printf("sprintf returns: %d\n\n", i);
return 0;
}
L'output:
15 in octal is 17
sprintf returns: 2
15 in decimal is 15
sprintf returns: 2
15 in hex is f
sprintf returns: 1
15.05 as a string is 15.050000
sprintf returns: 9
Una nostra implementazione di itoa potrebbe essere:
#include <stdio.h>
void my_reverse(char str[], int len);
char* my_itoa(int num, char* str, int base);
int main() {
int i, b;
char charArray[128];
printf("Enter a number and base\n");
scanf("%d %d", &i, &b);
printf("String : %s", my_itoa(i, charArray, b));
return 0;
}
/*
* function to reverse a string
*/
void my_reverse(char str[], int len)
{
int start, end;
char temp;
for(start=0, end=len-1; start < end; start++, end--) {
temp = *(str+start);
*(str+start) = *(str+end);
*(str+end) = temp;
}
}
char* my_itoa(int num, char* str, int base)
{
int i = 0;
bool isNegative = false;
/* A zero is same "0" string in all base */
if (num == 0) {
str[i] = '0';
str[i + 1] = '\0';
return str;
}
/* negative numbers are only handled if base is 10
otherwise considered unsigned number */
if (num < 0 && base == 10) {
isNegative = true;
num = -num;
}
while (num != 0) {
int rem = num % base;
str[i++] = (rem > 9)? (rem-10) + 'A' : rem + '0';
num = num/base;
}
/* Append negative sign for negative numbers */
if (isNegative){
str[i++] = '-';
}
str[i] = '\0';
my_reverse(str, i);
return str;
}