【问题标题】:How to concatenate two integers in C如何在C中连接两个整数
【发布时间】:2012-09-23 21:49:03
【问题描述】:

Stack Overflow 用许多其他语言回答了这个问题,但不是 C。所以我想我会问,因为我有同样的问题。

如何在 C 中连接两个整数?

例子:

x = 11;
y = 11;

我想要z如下:

z = 1111;

其他示例尝试使用字符串执行此操作。没有字符串的方法是什么?

我正在寻找一种在 C 中执行此操作的有效方法,因为在我的特定用法中,这将进入代码的时间关键部分。

提前致谢!

【问题讨论】:

  • 喜欢100 * x + y?
  • 您想要 C 还是 C++?答案将非常彼此不同。我会从标题中假设 C。
  • 需要 C 谢谢。
  • 100 * x + y 在 y == 0 时失败。

标签: c math optimization mathematical-optimization


【解决方案1】:
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;

这里我无耻地复制了https://stackoverflow.com/a/1505791/1194873的myPow

【讨论】:

    【解决方案2】:
    unsigned concatenate(unsigned x, unsigned y) {
        unsigned pow = 10;
        while(y >= pow)
            pow *= 10;
        return x * pow + y;        
    }
    

    compilation/correctness/speed的证明

    我避免使用 log10pow 函数,因为我很确定它们使用浮点并且速度较慢,所以这可能在您的机器上更快。可能是。个人资料。

    【讨论】:

    • 我认为没有什么能比得上你的回答了。
    • 一定是y >= pow,我觉得concatenate(1,10)不应该是20。
    • 您说得对,先生,因为我的某些数字不准确。固定。
    • 另外,我完全没有说这比大卫的回答快 17 倍,更不用说比鼓手的快 23 倍。
    • 存在潜在的无限循环:例如在 32 位系统上尝试 concatenate(1, 1000000000)。您可以在 while 循环中使用 if (pow > UINT_MAX / 10) return y; 来避免它。
    【解决方案3】:
    z = x * pow(10, log10(y)+1) + y;
    

    说明:

    首先你得到第二个变量的位数:

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

    然后你通过将另一个变量乘以 10^digits 来“移动”另一个变量。

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

    最后添加第二个变量:

    z = shifted + y;   // 1111
    

    或者在一行中:

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

    【讨论】:

    • 我赞成你的回答,因为你确实解释了一些东西。
    • 最好避免整数问题的浮点数学运算。
    【解决方案4】:

    也许这会奏效:

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

    代码很长,但很简单。 如果有任何错误,请纠正我。

    【讨论】:

    • ideone.com/hbWgE "断言 `func(0, 10) == 10' 失败"。可能还有其他极端情况。
    【解决方案5】:

    这是另一种方法:

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

    谁知道你会得到什么性能。试试看吧..

    【讨论】:

    • concat(123, 0) 返回 123 而不是 1230。建议使用do ... while 循环。
    • 这确实是最好的答案,一旦边缘情况修复。我也会使用unsigned,但 OP 对此很模糊。
    【解决方案6】:
    #include<iostream>
    using namespace std;
    
    int main()
    {
        int a=0,b=0,count=0,c=0,t=0;
        cout<<"enter 2 no"<<endl;
        cin>>a>>b;
        t=b;
    
        while(b!=0)
        {
            b=b/10;
            count++;
        }
    
        while(count!=0)
        {
            a=a*10;
            count--;
            c=a+t;
        }
    
        cout<<"concate no is:"<<c;
    }
    

    【讨论】:

    • OP 在 C 中寻找解决方案。您在 C++ 中提供了解决方案,因为您使用的是 cincout。此外,您回答了一个已经有几个广为接受的答案的老问题。为什么您的解决方案更好,值得发布?
    【解决方案7】:

    这可能不是一个最佳或快速的解决方案,但没有人提到它,它是一个简单的解决方案,可能很有用。

    您可以使用sprintf()strtol()

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

    您首先使用sprintf() 将数字写入一个字符串,然后将另一个数字写入另一个字符串(就像您使用printf() 打印到标准输出一样),然后使用strtol() 将生成的字符串转换为数字。

    strtol() 返回一个long,它的值可能大于int 中可以存储的值,因此您可能需要先检查结果值。

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

    如果strtol() 返回的值不在int 的范围内(即不在(包括)INT_MININT_MAX 之间),则发生错误。 INT_MININT_MAX 来自 limits.h

    如果字符串中的值太大而无法在long 中表示,由于溢出,errno 将被设置为ERANGE(来自errno.h)。

    了解strtol() here

    编辑:

    正如chqrlie 的启发性评论所指出的,负数会导致这种方法出现问题。

    你可以使用这个或修改这个来解决这个问题

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

    首先将第二个数字连同其符号一起打印到字符数组temp

    %+d 中的+ 将导致打印数字的符号。

    现在将第一个数字和第二个数字打印到str,但没有第二个数字的符号部分。我们通过忽略temp 中的第一个字符来跳过第二个数字的符号部分。

    strtol() 终于完成了。

    【讨论】:

    • 这是处理潜在溢出的好方法。添加相应的代码,设置和测试errno 并将结果与​​INT_MININT_MAX 进行比较会很有帮助。 ij 的负值也会导致问题。
    • @chqrlie 感谢您抽出宝贵时间告诉我们。我没有想到负数的问题。或者有需要的看INT_MIN
    • if(rv&gt;INT_MAX || rv&lt;INT_MIN || errno==ERANGE) 应该是 if(rv&gt;LONG_MAX || rv&lt;LONG_MIN || errno==ERANGE)。通常,这无法检测到 strtol("!!!", ...) 中的错误,因为 errno 未确定设置。
    【解决方案8】:

    这是@Mooing Duck 答案的一个变体,它使用查找表来查找 10 的倍数(对于具有慢整数乘法的平台)它还返回 unsigned long long 以允许更大的值,并在查找表中使用 unsigned long long考虑@chqrlie 关于无限循环的评论。如果可以保证组合输入不超过无符号数,则可以更改。

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

    【讨论】:

      【解决方案9】:

      你也可以使用宏来连接字符串(简单的方法)

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

      它有一个缺点。我们不能在这个方法中传递参数

      【讨论】:

        【解决方案10】:

        改进了@Mooing Duck@none 答案的变化。

        根据需要简单地移动x

        unsigned concatenate2(unsigned x, unsigned y) {
          unsigned y_temp = y;
          do {  // do loop to insure at least one shift
            x *= 10;
            y_temp /= 10;
          } while (y_temp > 0);
          return x + y;  
        }
        

        可以使用更广泛的数学来减少溢出可能性。 @technosaurus

        #include <inttypes.h>
        
        uintmax_t concatenate2(unsigned x, unsigned y) {
          uintmax_t x_temp = x;
          unsigned y_temp = y;
          do {  // do loop to insure at least one shift
            x_temp *= 10;
            y_temp /= 10;
          } while (y_temp > 0);
          return x_temp + y;  
        }
        

        【讨论】:

          猜你喜欢
          • 2020-08-29
          • 1970-01-01
          • 2010-12-14
          • 2016-09-07
          • 2023-02-09
          • 1970-01-01
          • 1970-01-01
          • 2015-04-23
          相关资源
          最近更新 更多