Search code examples
cstringlinked-listdynamic-programminglong-integer

How do I cast a String to a Long-int in C?


How do i turn a String in C to a Long integer, without removing the leading zero?

I have used both sscanf() and strtol() functions but they both remove the leading zero as if its white-space. I have tried chatgpt and bard for a solution but none of theirs work at all.

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

   int main()
   {
       char *num = "09999999991";

       long n = strtol(num, NULL, 10);;

       printf("%ld\n", n); 
    
       /*
           Output: 9999999991 
           Expected: 09999999991
       */ 
   }

I'am origanally getting the numbers from two linked lists converting them to longs so that i can get the sum and make a new linked list out of the sum like bellow

    struct ListNode *addTwoNumbers(struct ListNode * l1, struct ListNode * l2)
    {
        // make two string to hold the nums
        char num1[500] = "";
        char num2[500] = "";

        long long n1, n2, sum, reverse1 = 0, reverse2 = 0, remainder;

        // get the first num
        struct ListNode *tmp = l1;
        while (tmp != NULL)
        {
            char c[600];
            sprintf(c, "%lld", tmp->val);
            strcat(num1, c);
            tmp = tmp->next;
        }

        // get the second num
        tmp = l2;
        while (tmp != NULL)
        {
            char c[600];
            sprintf(c, "%lld", tmp->val);
            strcat(num2, c);
            tmp = tmp->next;
        }
        printf("%s + %s\n", num1, num2);

        // cast to int
        n1 = strtol(num1, NULL, 10);
        n2 = strtol(num2, NULL, 10);
        printf("%lld + %lld\n", n1, n2);

        // reverse the numbers
        while (n1 != 0)
        {
            remainder = n1 % 10;
            reverse1 = reverse1 * 10 + remainder;
            n1 /= 10;
        }
        while (n2 != 0)
        {
            remainder = n2 % 10;
            reverse2 = reverse2 * 10 + remainder;
            n2 /= 10;
        }

        printf("%lld + %lld\n", reverse1, reverse2);

        // get the sum
        sum = reverse1 + reverse2;

        printf("%ld\n", sum);
        char value[500];
        sprintf(value, "%ld", sum);

        struct ListNode *head = NULL;
        for (int i = 0, len = strlen(value); i < len; i++)
        {
            struct ListNode *n = malloc(sizeof(struct ListNode));
            if (n == NULL)
            {
                exit(1);
            }

            n->val = value[i] - '0';
            n->next = NULL;

            n->next = head;
            head = n;
        }

        // free memory
        tmp = l1;
        while (tmp != NULL)
        {
            struct ListNode *next = tmp->next;
            free(tmp);
            tmp = next;
        }

        tmp = l2;
        while (tmp != NULL)
        {
            struct ListNode *next = tmp->next;
            free(tmp);
            tmp = next;
        }

        return head;
    }

Solution

  • ... getting the numbers from two linked lists converting them to longs so that i can get the sum ...

    Instead of converting to long, adding and converting back to a string, consider simply adding the string content.

    The below finds the string size potentially needed, allocates, then adds, just like we learned in our early school days, finds the sum one digit at a time. We start with the least significant digit.

    // Untested illustrative code
    
    #include <ctype.h>
    #include <stdlib.h>
    #include <string.h>
    
    // Return an allocated string of the sum of the strings.
    // Return NULL on problems: out-of-memory, non-numeric text.
    char* string_sum(const char *a, const char *b) {
      const char *s;
    
      // Test for digits only and find length
      for (s = a; *s; s++) {
        if (!isdigit(*(const unsigned char* )s)) {
          return NULL;
        }
      }
      size_t a_len = (size_t) (s - a);
    
      for (s = b; *s; s++) {
        if (!isdigit(*(const unsigned char* )s)) {
          return NULL;
        }
      }
      size_t b_len = (size_t) (s - b);
    
      // Allocate 
      size_t c_len = a_len > b_len ? a_len : b_len;
      c_len++; // +1 for potential carry.
      size_t c_size = c_len + 1 /* null character */;
      char *c = malloc(c_size);
      if (c == NULL) {
        return NULL;
      }
      c[c_len] = '\0';
    
      // Add digits, starting with least.
      int carry = 0;
      while (a_len > 0 || b_len > 0 || carry) {
        int sum = carry;
        if (a_len > 0) {
          sum += a[--a_len] - '0';
        }
        if (b_len > 0) {
          sum += b[--b_len] - '0';
        }
        c[--c_len] = (char) ('0' + sum % 10);
        carry = sum / 10;
      }
    
      // Adjust for carry and return.
      return memmove(c, c + c_len, c_size - c_len);
    }