将整数拆分为两个单独的整数

时间:2015-08-14 18:45:36

标签: c integer reverse

假设我有

int n=123456;
int x,y=0;

如何将整数“n”分成两半。

注意:n中的总位数将始终是2的倍数,例如 1234,4567,234567,35621等...都有2,4,6, 8位数。 我想将它们分成两半。

我正在尝试使用以下代码,但它不起作用,y变量以某种方式保持反转的第二部分。

int x, y=0, len, digit;
int n=123456;

len=floor(log10(abs(n))) + 1;
x=n;
while((floor(log10(abs(x))) + 1)>len/2)
{
    digit=x%10;
    x=x/10;
    y=(y*10)+digit;
}
printf("First Half = %d",x);
printf("\nSecond Half = %d",y);

当输入为:

  

N = 123456;

我得到的输出:

  

上半场= 123
  下半场= 654

我想要的输出:

  

上半场:123

     

下半场:456

6 个答案:

答案 0 :(得分:11)

这是一个示范程序。它不使用除printf之外的任何函数。:)因此它是最简单的解决方案。

#include <stdio.h>

int main( void )
{
    unsigned int a[] = { 12, 1234, 123456, 12345678, 1234567890 };
    const unsigned int Base = 10;

    for ( size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++ )
    {   
        unsigned int divisor = Base;
        while ( a[i] / divisor > divisor ) divisor *= Base;

        printf( "%u\t%u\n", a[i] / divisor, a[i] % divisor );
    }        
}

程序输出

1       2
12      34
123     456
1234    5678
12345   67890

如果您要使用有符号整数类型和负数,那么程序可以采用以下方式

#include <stdio.h>

int main( void )
{
    int a[] = { -12, 1234, -123456, 12345678, -1234567890 };
    const int Base = 10;

    for ( size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++ )
    {   
        int divisor = Base;
        while ( a[i] / ( a[i] < 0 ? -divisor : divisor ) > divisor ) divisor *= Base;

        printf( "%d\t%d\n", a[i] / divisor, a[i] % divisor );
    }        
}

它的输出是

-1      -2
12      34
-123    -456
1234    5678
-12345  -67890

答案 1 :(得分:4)

这实际上是我要做的事情

#include <stdio.h>
#include <math.h>

int main(void)
{
  int x, y=0, len, digit;
  int n=123456;

  len=floor(log10(abs(n))) + 1;
  x = n / pow(10, len / 2);
  y = n - x * pow(10, len / 2;
  printf("First Half = %d",x);
  printf("\nSecond Half = %d",y);
}

答案 2 :(得分:3)

这可以通过将模数运算符除以除法器来完成,即10 (NumberOfDigits / 2)

#include <stdio.h>

int getNumberOfDigits(int n)
{
    int counter = 0;
    for (; n > 0; n /= 10)
        counter++;
    return counter;
}

int main(void)
{
    int n = 123456;

    int divider = 1;
    for (int i = 0; i < getNumberOfDigits(n) / 2; i++) {
        divider *= 10;
    }
    printf("%d, %d\n", n / divider, n % divider);

    return 0;
}

答案 3 :(得分:1)

另一种可能性:

// split an int value into two pieces with the same number of decimal
// digits in each piece.  a couple of examples to demonstrate the output
//     iVal          iTop           iBot
//     1234            12             34
//   123456           123            456
void split_int (int iVal, int *iTop, int *iBot)
{
    int iTopx = iVal;   // save a copy of the value to be split later

    // start with assuming two decimal digits. if value is zero will still work.
    // we will then keep shifting the value right by two decimal digits as
    // we increment our divisor by one decimal digit so that we can create
    // a divisor we can then use to split the value using integer division
    // to get the top half and remainder of integer division for the bottom half.

    int iTen = 10;   // divisor value to split two decimal digits
    iVal /= 100;     // shift value right by two decimal digits
    while (iVal) {   // check to see if we are done, if not continue counting
        iTen *= 10;  // increase the divisor value we will use to split digits
        iVal /= 100; // shift value right by two decimal digits
    }

    *iTop = iTopx / iTen;  // split off top part by dividing by divisor
    *iBot = iTopx % iTen;  // split off bottom part by taking remainder
}

// test harness for the function above to try out several input data variations
// and print the results.  This is a Visual Studio Windows Console Application
// so the entry point is _tmain().
int _tmain(int argc, _TCHAR* argv[])
{
    int iTop, iBot, iVal;

    printf ("    iVal       iTop        iBot\n");    // output heading

    split_int ((iVal = 123456), &iTop, &iBot);
    printf ("   %8.8d   %8.8d    %8.8d\n", iVal, iTop, iBot);

    split_int ((iVal = 12345), &iTop, &iBot);
    printf ("   %8.8d   %8.8d    %8.8d\n", iVal, iTop, iBot);

    split_int ((iVal = 12), &iTop, &iBot);
    printf ("   %8.8d   %8.8d    %8.8d\n", iVal, iTop, iBot);

    split_int ((iVal = 0), &iTop, &iBot);
    printf ("   %8.8d   %8.8d    %8.8d\n", iVal, iTop, iBot);

    split_int ((iVal = 1234567890), &iTop, &iBot);
    printf ("   %8.8d   %8.8d    %8.8d\n", iVal, iTop, iBot);

    split_int ((iVal = -1234567890), &iTop, &iBot);
    printf ("   %8.8d   %8.8d    %8.8d\n", iVal, iTop, iBot);

    return 0;
}

产生

的输出
    iVal       iTop        iBot
   00123456   00000123    00000456
   00012345   00000012    00000345
   00000012   00000001    00000002
   00000000   00000000    00000000
   1234567890   00012345    00067890
   -1234567890   -00012345    -00067890

答案 4 :(得分:0)

最简单的方法是使用sprintf功能。这将获取一个值并根据提供的说明符对其进行格式化。将整数表示为字符串后,只需取出字符串的每一半即可。使用sscanf,将进程反转回整数。

void print_both_halves(int x) {
    char str[80]; // magic number lengths
    char tmp[80];
    int len;
    int a, b;

    len = sprintf(str, "%d", x); // returns the number of chars written

    strncpy(tmp, str, len/2);
    tmp[len/2] = '\0';
    sscanf(tmp, "%d", &a); // gets the first half

    strncpy(tmp, &(str[len/2]), len/2); // copies from the middle of str
    tmp[len/2] = '\0';
    sscanf(tmp, "%d", &b); // gets the second half
}

答案 5 :(得分:0)

使用字符串进行拆分的另一种变体:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int split( int val, int *top, int *bot )
{
  char  tmp[23]; // should be large enough to hold a 64-bit decimal integer
                 // plus sign plus 0 terminator
  char  low[12] = {0};
  char high[12] = {0};

  if ( val < 0 )
    val = -val;

  sprintf( tmp, "%d", val );
  if ( strlen( tmp ) % 2 )
    return 0;

  strncpy( low, tmp, strlen( tmp ) / 2 );
  strncpy( high, tmp + strlen( tmp ) / 2, strlen( tmp ) / 2 );

  *top = (int) strtol( low, NULL, 10 );
  *bot = (int) strtol( high, NULL, 10 );

  return val;
}

int main( int argc, char **argv )
{
  if ( argc < 2 )
  {
    fprintf( stderr, "USAGE: %s integer_value_with_even_number_of_digits\n", argv[0] );
    exit( 0 );
  }

  int val = (int) strtol( argv[1], NULL, 10 );
  int lo, hi;

  if ( split( val, &lo, &hi ) )
    printf( "val: %d, lo: %d, hi: %d\n", val, lo, hi );
  else
    fprintf( stderr, "USAGE: %s integer_value_with_even_number_of_digits\n", argv[0] );

  exit( 0 );
}

一些示例运行:

[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter 1
USAGE: ./splitter integer_value_with_even_number_of_digits
[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter 12
val: 12, lo: 1, hi: 2
[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter -12
val: -12, lo: 1, hi: 2
[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter -123
USAGE: ./splitter integer_value_with_even_number_of_digits
[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter -1234
val: -1234, lo: 12, hi: 34
[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter 12345678
val: 12345678, lo: 1234, hi: 5678
[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter -1234567890
val: -1234567890, lo: 12345, hi: 67890
[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter 012
val: 12, lo: 1, hi: 2
[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter 00123456
val: 123456, lo: 123, hi: 456
[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter 001234567
USAGE: ./splitter integer_value_with_even_number_of_digits

你没有提到值是否必须是正数,或者前导零是否与数字位数相比(因为它被读作整数值而不是字符串,没有前导转换后的零)。

对我来说,这段代码具有简单的优点。我们基本上把数字当作一串数字来分解中间,所以(至少在我看来),使用字符串操作似乎是最直接的。在性能方面,这不应该比使用log获取数字并循环遍历它们要慢。