0

I am trying to push numbers from a text file into a linked list which might have multiple digit numbers in multiple lines. My output is a mess, only printing -47 multiple times. My main doubts are how to read a 2 digit number from the file, although my current code is not even reading any number.

My code:

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

typedef struct linklist
{
     int data;
     struct linklist *addr;
}ll;

void push(ll **h,int val);
void display(ll **h);


void main()
{
    FILE *fp;
    fp=fopen("re.txt","r");
    char c;
    ll *head=NULL;

    while(c=fgetc(fp)!=EOF)
    {
        if(c==' ' || c=='\n')
        {
            continue;
        } 
        else
        {
            int temp=c-'0';
            printf("Temp = %d",temp);
            push(&head,temp);
        }
    }
    printf("check");
    display(&head);
    fclose(fp);
}

void push(ll **h,int val)
{

    if(*h==NULL)
    {
        ll *temp=(ll*)malloc(sizeof(ll));
        temp->data=val;
        temp->addr=NULL;
        *h=temp;
    }
    else
    {
        ll *current = *h;
        while(current->addr!=NULL)
            current=current->addr;
        current->addr=(ll*)malloc(sizeof(ll));
        current->addr->data=val;
        current->addr->addr=NULL;      
    }
}

void display(ll **h)
{
    ll *current=*h;
    while(current->addr!=NULL)
    {
        printf("%d\t",current->data);
        current=current->addr;
    }
}

Edit:

The re.txt file looks like this:

4
2 1 8 19
6 11 50 89
21 22 47
25 35
13
  • Don't use fgets which only read characters but use fscanf. Also edit and show the first 3-4 lines of re.txt. Commented Oct 7, 2020 at 16:34
  • So your list should contain the numbers 4,2,1,8,19,6, etc. ? Please confirm. Commented Oct 7, 2020 at 16:39
  • 2
    Side note: best avoid a name such a l or ll. My first thought was "what are those elevens doing". Worse for an r-value. You shouldn't have to peer at code or mistake a variable for a number. Commented Oct 7, 2020 at 16:40
  • 2
    Note that while(c=fgetc(fp)!=EOF) is missing a critical set of parentheses. It should be while( (c=fgetc(fp)) != EOF) Commented Oct 7, 2020 at 16:46
  • 1
    OT: regarding: fp=fopen("re.txt","r"); a function call (like fopen()) can fail. Always check (!=NULL) the returned value to assure the operation was successful. If not successful (==NULL) then call perror( "fopen failed" ) to output both your error message and the text reason the system thinks the error occurred to stderr so the user is informed of the problem. Generally, this is a unrecoverable error, so clean up then call exit( EXIT_FAILURE ); Commented Oct 7, 2020 at 17:01

2 Answers 2

2

For starters the condition in the while loop

while(c=fgetc(fp)!=EOF)

is incorrect. It is equivalent to the following condition

while( c = ( fgetc(fp) != EOF ) )

So if fgetc( fp ) is not equal to EOF then the expression fgetc( fp ) != EOF evaluates to 1 and the variable c will get this value 1.

The while loop shall look at least like

while( ( c =  fgetc(fp) ) != EOF  )

And the variable c should have the type int.

int c;

Otherwise the loop can be infinite because the type char can behave as the type unsigned char (depending on an option of the compiler) and the variable c will be never equal to the signed value of EOF.

However in any case this loop is incorrect because the function fgetc also reads white space characters while you need to read whole numbers.

So change the loop like

int temp;

while ( fscanf( fp, "%d", &temp ) == 1 )
{
    push( &head, temp );
}

Also the function push can look simpler. And it can signal to the caller whether the memory for the new node was allocated successfully Otherwise the function can invoke undefined behavior in the case when the memory allocation fails. For example

int push( ll **h, int val )
{
    ll *temp = malloc( sizeof( ll ) );
    int success = temp != NULL;

    if ( success )
    {
        temp->data = val;
        temp->addr = NULL;

        while ( *h != NULL ) h = &( *h )->addr;

        *h = temp;
    }

    return success;
}

The function display can invoke undefined behavior when the passed pointer to the head node is equal to NULL. And the function will output nothing if the list contains only one node.

The function can be declared the following way

void display( ll **h )
{
    for ( ll *current = *h; current != NULL; current = current->addr )
    {
        printf("%d\t",current->data);
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

Use fscanf which does the work for you.

You want this:

int main()
{
  FILE* fp;
  fp = fopen("re.txt", "r");
  if (fp == NULL)
  {
     printf("Can't open file\n");
     return 1;
  }
  char c;
  ll* head = NULL;
  int temp;

  while (fscanf(fp, "%d", &temp) != EOF)
  {
    printf("Temp = %d\n", temp);
    push(&head, temp);
  }
  printf("check");
  display(&head);
  fclose(fp);
}

There is still room for improvement though.

1 Comment

scanf(fp, "%d", &temp) == 1 is a better idiomatic test.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.