-2

So, given this input:

43890758927436598726435872648957245892643
834589723465892743658972346587243568274599

I should assign each of these two to a linked list.

I actually have no clue. I know in C++ I can use the getline method. Is there something similar in C?

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • 2
    `fgets` will be a good start but that the smallest part of your problem. – Support Ukraine Mar 08 '23 at 19:21
  • 1
    If you are going to build a linked list, why not read one digit at a time and build the list as you go? – M Oehm Mar 08 '23 at 19:25
  • 1
    If you need to create a linked list of digits, you might as well use `int digit = getchar()` to read one character at a time. You can use the `isdigit()` function from `` to check the character. It will return false when you read the space at the end of the first number, and the newline at the end of the second number. Use `digit -= '0';` to convert the character code for the digit into the corresponding digit value. – user3386109 Mar 08 '23 at 19:27
  • @MOehm that was my plan, but i didn't know how to deal with the space at the end of the first number – Paul Roman Mar 08 '23 at 19:33
  • @ Barmar I don't think that's a valid edit, because it makes it look like the numbers are separated by a newline, which is not what the title says. – user3386109 Mar 08 '23 at 19:33
  • @user3386109 The newline was in the original post. The lines were merged because he didn't put it in a code block. – Barmar Mar 08 '23 at 19:36
  • Well, the comment below mine tells you how to go about it. (Perhaps that comment should be an answer.) – M Oehm Mar 08 '23 at 19:36
  • @Barmar Ok, I'll let OP fix it if he wants to. – user3386109 Mar 08 '23 at 19:42
  • Is there a need to store them in some kind of number format or can you just store them as strings? – Jeff Mar 08 '23 at 19:47
  • As you did not show any code, I think you expect us to write it for you. It will not happen – 0___________ Mar 08 '23 at 20:35
  • Thanks for the info guys! basically i got to do the sum of the two numbers but it is mandatory to store them in a linked list. @0___________ i didn t know how to start the reading that's why i asked the question, I don't want someone to write the code for me as I want to understand how the algorithm works :) – Paul Roman Mar 08 '23 at 22:07
  • @Barmar thanks for the help, i don't actually know how stack overflow works as this is my first post. – Paul Roman Mar 08 '23 at 22:10
  • Just clarify -- are the numbers in the file on the same line or different lines? – Barmar Mar 08 '23 at 22:12
  • You're expected to learn the language basics, this isn't a tutoring service. So you need to read a tutorial to learn how to read from files. – Barmar Mar 08 '23 at 22:13

2 Answers2

1

Simple linked list exercise.

  1. Each link in the list is a bignum digit. In our case our “bigit” is just a value in 0–9.
  2. A number has sign, plus the singly-linked list of digits from least- to most-significant.
  3. Don’t forget to clean up (free()) anything you allocate (with malloc()).
  4. Reading from file is just:
    • skipping whitespace
    • checking for an optional sign
    • reading digits until a non-digit is encountered
  5. Notice how we are careful to put back characters that don’t match what we are looking for?
  6. For printing the digits we just use a recursive function. If you expect your bignums to be really big, don’t do this. There are all kinds of ways to overcome this limitation if it matters. For a homework it probably doesn’t.
  7. Always pass a number by pointer. More on this below.
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>

//-----------------------------------------------------------------------------
// Bignum digit type is an integer value in 0..9

struct digit
{
  int            digit;
  struct digit * next;
};


// Prepend a digit to a list of digits
struct digit * make_digit( int _digit, struct digit * _next )
{
  struct digit * d = malloc( sizeof(struct digit) );
  if (d)
  {
    d->digit = _digit;
    d->next  = _next;
  }
  return d;
}


void free_digits( struct digit * digit )
{
  while (digit)
  {
    struct digit * next = digit->next;
    free( digit );
    digit = next;
  }
}


//-----------------------------------------------------------------------------
// A bignum is:
//  • a sign: -1 or 1
//  • a list of digits starting with the least-significant

struct number
{
  int            sign;
  struct digit * digits;
};
typedef struct number number;


void free_number( number * n )
{
  free_digits( n->digits );
}


//-----------------------------------------------------------------------------
// Read a bignum from FILE *

void skip_whitespace( FILE * f )
{
  int c;
  while (isspace( (unsigned char)(c = fgetc( f )) )) { }
  if (c != EOF) ungetc( c, f );
}

number read_number( FILE * f )
{
  number n = { 1, NULL };
  skip_whitespace( f );
  int c = fgetc( f );
  switch (c)
  {
    case '-': n.sign = -1; c = fgetc( f ); break;
    case '+': n.sign =  1; c = fgetc( f ); break;
  }
  while (isdigit( (unsigned char)c ))
  {
    n.digits = make_digit( c-'0', n.digits );
    c = fgetc( f );
  }
  if (c != EOF) ungetc( c, f );
  return n;
}


//-----------------------------------------------------------------------------
// Print a bignum to FILE * 

void print_digits( FILE * f, struct digit * d )
{
  if (!d) return;
  print_digits( f, d->next );
  fprintf( f, "%c", d->digit+'0' );
}

void print_number( FILE * f, number * n, const char * s )
{
  if (!n->digits) return;
  if (n->sign < 0) fprintf( f, "-" );
  print_digits( f, n->digits );
  fprintf( f, "%s", s );
}


//-----------------------------------------------------------------------------

int main(void)
{
  number n1 = read_number( stdin );
  number n2 = read_number( stdin );
  
  print_number( stdout, &n1, "\n" );
  print_number( stdout, &n2, "\n" );
  
  free_number( &n1 );
  free_number( &n2 );
  return 0;
}

As already noted, and exampled, a number should be passed by pointer to functions that will modify the number. Since it doesn’t make any sense to manage const-ness with a number, you might as well make all functions that take numbers take a pointer so to be as un-confusing as possible.

For example, a function that sums two numbers and returns a new number might look like:

number add( number * a, number * b );  // result = a + b

A function that increments a number might look like:

void inc( number * n, number * by );  // n += by

Just remember: every time you get a new number, you must free it before terminating the current scope, just as the example in main().

Dúthomhas
  • 8,200
  • 2
  • 17
  • 39
  • You should remove the cast in `isspace( (unsigned char)(c = fgetc( f ))` as `isdigit()` has defined behavior for all values returned by `fgetc()`, including `EOF`, whereas `isspace((unsigned char)EOF)` might be true for some contorted architecture (I make a note to add this special case in my DS9K project :) – chqrlie Mar 09 '23 at 08:46
  • The test in `if (c != EOF) ungetc( c, f );` is redundant as `ungetc(EOF, f)` is specified as having no effect since at least C90. Yet I would probably keep this test for clarity. – chqrlie Mar 09 '23 at 08:54
0

If you're working with numbers that won't fit into 64 bits, then you need to simply store those numbers as a string. As a quick (BUT INSECURE) way to do this, you can simply do:

char *num1 = NULL;
char *num2 = NULL;
int ret = scanf("%m[0-9] %m[0-9]", &num1, &num2);
if (ret == 2) {
  //...
}

scanf will dynamically allocate num, so you can use num in your program, as long as you remember to free it later (if you're worried about memory consumption). Checking the return value also ensures you do in fact read in 2 numbers.

squidwardsface
  • 389
  • 1
  • 7