问题
Suppose I have
int n=123456;
int x,y=0;
How do I split the integer "n" in two half.
Note : The Total Number of digits in n
will always be multiple of 2, e.g. 1234, 4567, 234567, 345621 etc... all have 2,4,6,8 digits.
I want to divide them in half.
I am trying with following Code but it's not working, the y
variable is holding reversed second part somehow.
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);
When Input is :
n=123456;
Output I am getting :
First Half = 123
Second Half = 654
Output I want :
First Half : 123
Second Half : 456
回答1:
Here is a demonstrative program. It does not use any function except printf.:) Thus it is the simplest solution.
#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 );
}
}
The program output is
1 2
12 34
123 456
1234 5678
12345 67890
If you are going to use a signed integer type and negative numbers then the program can look the following way
#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 );
}
}
Its output is
-1 -2
12 34
-123 -456
1234 5678
-12345 -67890
回答2:
Here is actually what I would do
#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);
}
回答3:
This can be done by division an modulus operators with the divider, that is 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;
}
回答4:
Another possibility:
// 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;
}
which produces the output of
iVal iTop iBot
00123456 00000123 00000456
00012345 00000012 00000345
00000012 00000001 00000002
00000000 00000000 00000000
1234567890 00012345 00067890
-1234567890 -00012345 -00067890
回答5:
Since this seems to be a problem about numbers, more specifically integers, you shouldn't use either strings or floating-point operations.
int n = 123456;
int digits = 0;
int m = n;
while (m) {
digits++;
m /= 10;
}
digits /= 2;
int tmp = 0, lower_half = 0;
while (digits--) {
tmp *= 10;
tmp += n % 10;
n /= 10;
}
while (tmp) {
lower_half *= 10;
lower_half += tmp % 10;
tmp /= 10;
}
Here, n
contains the upper half of the digits, lower_half
the lower ones.
回答6:
The easiest way to do this is with the sprintf function. This takes a value and formats it according to the provided specifier. Once you have your integer represented as a string, you simply take each half of your string. Using sscanf, you reverse the process back to integer.
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
}
回答7:
Another variation on using strings to do the split:
#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 );
}
Some sample runs:
[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
You didn't mention whether values had to be positive or not, or whether leading zeros count against the number of digits (since it's read as an integer value and not a string, there are no leading zeros after the conversion).
To me, this code has the virtue of simplicity. We're essentially treating the number as a string of digits to split down the middle, so (in my mind at least), using string operations seemed the most straightforward. Performance-wise, this shouldn't be any slower than using log
to get the digits and looping through them.
来源:https://stackoverflow.com/questions/32016815/split-integer-into-two-separate-integers