web-dev-qa-db-fra.com

Comment concaténer deux entiers en C

Stack Overflow a répondu à cette question dans de nombreuses autres langues, mais pas C. J'ai donc pensé poser la question, car j'ai le même problème.

Comment concatène-t-on deux entiers en C?

Exemple:

x = 11;
y = 11;

Je voudrais z comme suit:

z = 1111;

D'autres exemples tentent de le faire avec des chaînes. Quelle est la façon de le faire sans chaînes?

Je cherche un moyen efficace de le faire en C car dans mon utilisation particulière, cela entre dans une partie critique du code.

Merci d'avance!

17
010110110101
unsigned concatenate(unsigned x, unsigned y) {
    unsigned pow = 10;
    while(y >= pow)
        pow *= 10;
    return x * pow + y;        
}

Preuve de compilation/exactitude/vitesse

J'évite le log10 et pow, car je suis quasiment sûr qu'elles utilisent des virgules flottantes et sont lentes, donc cela pourrait être plus rapide sur votre machine. Peut être. Profil.

37
Mooing Duck
z = x * pow(10, log10(y)+1) + y;

Explication:

Vous obtenez d'abord le nombre de chiffres de la variable qui devrait venir en second:

int digits = log10(y)+1;  // will be 2 in your example

Ensuite, vous "décaler" l'autre variable en la multipliant par 10 ^ chiffres.

int shifted = x * pow(10, digits);   // will be 1100 in your example

Enfin, vous ajoutez la deuxième variable:

z = shifted + y;   // 1111

Ou en une seule ligne:

z = x * pow(10, (int)log10(y)+1) + y;
9
DrummerB

Ce n'est peut-être pas une solution optimale ou rapide, mais personne ne l'a mentionné et c'est une solution simple et pourrait être utile.

Vous pouvez utiliser sprintf() et strtol().

char str[100];
int i=32, j=45;
sprintf(str, "%d%d", i, j);
int result=strtol(str, NULL, 10);

Vous écrivez d'abord dans une chaîne les nombres l'un suivi de l'autre avec sprintf() (tout comme vous imprimeriez sur la sortie standard avec printf()), puis convertissez la chaîne résultante en nombre avec strtol().

strtol() renvoie un long qui peut être une valeur supérieure à ce qui peut être stocké dans un int, vous pouvez donc vérifier d'abord la valeur résultante.

int result;
long rv=strtol(str, NULL, 10);
if(rv>INT_MAX || rv<INT_MIN || errno==ERANGE)
{
    perror("Something went wrong.");
}
else
{
    result=rv;
}

Si la valeur renvoyée par strtol() ne se trouve pas dans la plage d'un int (c'est-à-dire pas entre (y compris) INT_MIN Et INT_MAX), Une erreur s'est produite . INT_MIN Et INT_MAX Proviennent de limits.h.

Si la valeur de dans la chaîne est trop grande pour être représentée dans un long, errno sera défini sur ERANGE (de errno.h) En raison de la débordement.

Lisez à propos de strtol()ici .

Éditer:

Comme l'a souligné le commentaire éclairant de chqrlie , les nombres négatifs causeraient des problèmes avec cette approche.

Vous pouvez utiliser ceci ou une modification de ceci pour contourner cela

char str[100], temp[50];
int i=-32, j=45, result;
sprintf(temp, "%+d", j);
sprintf(str, "%d%s", i, temp+1);
long rv=strtol(str, NULL, 10);

Imprimez d'abord le deuxième nombre dans un tableau de caractères temp avec son signe.

Le + Dans %+d Provoquera l'impression du signe du numéro.

Imprimez maintenant le premier nombre et le deuxième nombre dans str mais sans la partie signe du deuxième numéro. Nous sautons la partie signe du deuxième nombre en ignorant le premier caractère dans temp.

Enfin, la strtol() est terminée.

2
J...S
int myPow(int x, int p)
{
     if (p == 0) return 1;
     if (p == 1) return x;

     int tmp = myPow(x, p/2);
     if (p%2 == 0) return tmp * tmp;
     else return x * tmp * tmp;
}
int power = log10(y);
z = x*myPow(10,power+1)+y;

Ici, j'ai copié sans vergogne myPow de https://stackoverflow.com/a/1505791/119487

2
Tae-Sung Shin

voici une autre façon de le faire:

int concat(int x, int y) {
    int temp = y;
    while (y != 0) {
        x *= 10;
        y /= 10;
    }
    return x + temp;
}

qui sait quelles performances vous obtiendrez. essayez juste de voir ..

1
none

Vous pouvez également utiliser la macro pour concaténer des chaînes (méthode simple)

#include<stdio.h>
#define change(a,b) a##b
int main()
 {
    int y;
    y=change(12,34);
    printf("%d",y);
    return 0;
 }

Il a un inconvénient. Nous ne pouvons pas passer d'arguments dans cette méthode

1
Jot Singh

Voici une variante de la réponse de @Mooing Duck qui utilise une table de recherche pour des multiples de 10 (pour les plates-formes avec une multiplication lente des nombres entiers). Elle retourne également unsigned long long pour permettre des valeurs plus grandes et utilise unsigned long long dans la table de recherche pour tenir compte de @ Commentaire de chqrlie sur les boucles infinies. S'il est garanti que les entrées combinées ne dépassent pas le nombre non signé, elles peuvent être modifiées.

static const unsigned long long pow10s[] = {
   10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,10000000000
};
unsigned long long concat(unsigned x, unsigned y) {
    const unsigned long long *p = pow10s;
    while (y >= *p) ++p;
    return *p * x +y;        
}
0
technosaurus

Peut-être que cela fonctionnera:

int x=11,y=11,temp=0;
int z=x;
while(y>0)
{
    // take reciprocal of y into temp
    temp=(temp*10)+(y%10);       
    y=y/10;
}
while(temp>0)
{
    // take each number from last of temp and add to last of z
    z=(z*10)+(temp%10);      
    temp=temp/10;
}

le code est long, mais simple. corrigez-moi s'il y a des erreurs.

0
Shabeer V P K