Как вернуть конечные цифры long в C (особенно, когда они равны 0) - PullRequest
0 голосов
/ 06 декабря 2018

У меня была проблема с кредитной картой, и я не мог понять, как извлечь конечные цифры числа, например, выполняя 123% 10, чтобы получить 3, 123% 100, чтобы получить 23 и т. Д. И т. Д. Ноу меня проблема с числом типа 6310005, где от% 10 до 10000 все возвращают просто 5, тогда как я хотел бы, чтобы он возвращал 5,05,005 и т. д. Вот ссылка на вывод команды findDoubles (378282246310005,15,1)

long* findDoubles(long cardNum, int cardLength, int startIndex)
{
    long length = 0;
    // if starting at the second number, and counting there on
    if(startIndex == 1 )
    {
        length = floor(cardLength/2);
    }
    else
    {
        length = ceil(cardLength/2);
    }
    long *doublesArr = malloc(length);
    for (int i = startIndex; i < length; i++)
    {
        doublesArr[i] = cardNum % (long)pow(10,i);
        printf("\ndoublesArr[%i] = %lu",i, doublesArr[i]);
    }
    return doublesArr;
}

Любая помощь будет принята с благодарностью, спасибо

Ответы [ 3 ]

0 голосов
/ 06 декабря 2018

Обрабатывать частичный номер карты, начинающийся с startindex, немного проще, если делать это как жало.Учитывая, что для long может потребоваться не более 21-chars (включая знак и nul-terminating символ), все, что требуется, - это простой буфер с автоматической продолжительностью хранения.Вы можете передать буфер в качестве параметра и просто вернуть startindex в строке (созданной простым вызовом sprintf) в виде символьного указателя из finddoubles.

Простым примером будет:

#include <stdio.h>

#define MAXSTR 32   /* max chars for long is 21 */

char *finddoubles (long cardnum, int cardlength, int startindex, char *str)
{
    if (!str) {     /* check valid address for str */
        fputs ("error: str unallocated pointer.\n", stderr);
        return NULL;
    }

    /* validate conversion matches cardlength */
    if (sprintf (str, "%ld", cardnum) != cardlength) {
        fputs ("error: conversion not cardlength chars.\n", stderr);
        return NULL;
    }

    return &str[startindex];    /* return requesting substring at index */
}

int main (void) {

    long num = 6310005;   /* example credit card number */
    int len = 7;          /* length */
    char str[MAXSTR];     /* buffer for conversion - avoids allocation */

    for (int i = 0; i < len; i++)   /* output values for all startindexes */
        printf ("start index: %d  indexed card no.: %s\n",
                i, finddoubles (num, len, i, str));
}

( примечание: Вы можете просто назначить возвращение символьному указателю (например, char *p = finddoubles (num, len, i, str); для использования, а не для немедленной печати значения)

Пример использования / вывода

$ ./bin/cardnumidx
start index: 0  indexed card no.: 6310005
start index: 1  indexed card no.: 310005
start index: 2  indexed card no.: 10005
start index: 3  indexed card no.: 0005
start index: 4  indexed card no.: 005
start index: 5  indexed card no.: 05
start index: 6  indexed card no.: 5

Существует множество способов сделать это. Самое простое - использовать sprintf. Нет необходимости бросать ваше собственное преобразование, так как sprintf является частьюстандартной библиотеки. Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.

Редактировать для 16-символьного Cardnum

Если, как объяснено в комментариях, кредитномера карт всегда состоят из 16 символов, тогда простые отступы и ширина поля модификаторы для sprintf обеспечат индексацию всего номера карты со следующими модификациями, например

    ...
    if (sprintf (str, "%016ld", cardnum) != cardlength) {
    ...
    int len = 16;
    ...
    for (int i = 0; i < len; i++)
        printf ("start index: %2d  indexed card no.: %s\n",
        ...

Пример использования / вывода

$ ./bin/cardnumidx
start index:  0  indexed card no.: 0000000006310005
start index:  1  indexed card no.: 000000006310005
start index:  2  indexed card no.: 00000006310005
start index:  3  indexed card no.: 0000006310005
start index:  4  indexed card no.: 000006310005
start index:  5  indexed card no.: 00006310005
start index:  6  indexed card no.: 0006310005
start index:  7  indexed card no.: 006310005
start index:  8  indexed card no.: 06310005
start index:  9  indexed card no.: 6310005
start index: 10  indexed card no.: 310005
start index: 11  indexed card no.: 10005
start index: 12  indexed card no.: 0005
start index: 13  indexed card no.: 005
start index: 14  indexed card no.: 05
start index: 15  indexed card no.: 5

ПРИМЕЧАНИЕ long не может содержать 16 цифр во всех системах

Как ясно указано @ chqrlie в комментариях ниже, о устаревших системахнапример, X86, значение long является только 32-разрядным и может быть в ярости только от -2147483648 to 2147483647 и не может содержать 16 цифр.Чтобы исправить ситуацию, лучше использовать точный тип размера , определенный в stdint.h, например int64_t (для вашего long) или лучше uint64_t, так как использование числа со знаком здесь не имеет большого смысла.Соответствующие макросы печати для точных размеров указаны в inttypes.h.

0 голосов
/ 06 декабря 2018

для возврата конечных цифр long

Это просто "мод" long с некоторой степенью 10.

Чтобы сохранить начальные нули при печати, используйте ".*" или точность как часть printf() для прямого вывода или sprintf() для сохранения в строку .

Так как номер CC обычно превышает 10 цифр, лучше использовать более широкий тип, который, безусловно, может вместить, так как long может быть недостаточно.unsigned long long может обрабатывать все 19 цифр - по крайней мере.

#include <stdio.h>

unsigned long long pow10_ull(unsigned y) {
  unsigned long long z = 1;
  unsigned long long base = 10;
  while (y) {
    if (y % 2) {
      z *= base;
    }
    y /= 2;
    base *= base;
  }
  return z;
}

unsigned long long endDigits(unsigned long long cardNum, int endLength) {
  return cardNum % pow10_ull(endLength);
}

void printEndDigits(unsigned long long cardNum, int cardLength,
    int startIndex) {
  int endLength = cardLength - startIndex;
  printf("%.*llu\n", endLength, endDigits(cardNum, endLength));
}

int main() {
  printEndDigits(378282246310005, 15, 1);
  printEndDigits(378282246310005, 15, 11);
  return 0;
}

Вывод

78282246310005
0005
0 голосов
/ 06 декабря 2018

Прежде чем я скажу это, позвольте мне подчеркнуть, что вы не должны хранить номера кредитных карт в виде целых чисел.

Однако ... ключ в том, что послевы получаете остаток от вашей операции модуля, вам нужно вычесть это из вашего начального значения, а затем разделить начальное значение на вашу базу.

#include <stdio.h>

int main(void) {
  unsigned long long int CC = 1234123412341234; 
  unsigned long long int temp = CC;
  unsigned short int A[16] = { 0 };
  int i;

  for (i = 0; i < 16; i++) {
    A[15-i] = temp % 10;
    temp = temp - A[15-i];
    temp = temp / 10;
  }

  printf("As an unsigned long long int, the CC number is %llu\n", CC);
  printf("As individual digits in an array, the CC number is ");

  for (i = 0; i < 16; i++) {
    printf("%1d", A[i]);
  }

  printf("\n\n");

  return 0;
}
...