Создайте список имен пользователей и балансировки с помощью C

#c #list #pointers

#c #Список #указатели

Вопрос:

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

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

//function declaration
int checkTimeStamp(int currentTS, int prevTS);
int checkBalance(float currentBal, float prevBal);

//Nodes for each List
struct node
{
    char userName[31];
    float balance;
    struct node *next;
};

int main()
{
    //Float and int variables
    float bal;
    int timeStamp;
    int listCount = 0; //Keep Track of the number of nodes
    int iEach = 0;
    int check = 0; //user for validating input string
    int prevTS = 0;
    int prevBal = 0;
    int checkBal;
    int checkTS;

    //String variables
    char userID[31];
    char input[130];


    //Node variables
    struct node root = { "", 0, NULL};// declare and initialize the first structure
    struct node* freeNode = NULL;// declare a pointer and initialize it null. use for freeing memory later
    struct node* pNode = amp;root;// declare a pointer and initialize it to point to the first structure

    while( fgets(input, 130, stdin) )
    {
        check = sscanf(input, "%d %s %f" , amp;timeStamp, userID, amp;bal); //checking if the user has entered the right values
        //printf("%dn", check);

        if( check == 0 ) //checking if timestamp was integer
        {
            printf("Invalid timen");
        }
        else if( check == 2 ) //checking if balance was float
        {
            printf("Illegal balancen");
            prevTS = timeStamp;
        }
        else //if check >= 3
        {
            //pNode->next = malloc ( sizeof( struct node));// allocate memory for the next structure
            checkBal = checkBalance(bal, prevBal);
            checkTS = checkTimeStamp(timeStamp, prevTS);
            if(checkTS == 1)
            {
                printf("Non-monotonic timestampsn");  
            }
            else if( checkBal == -1 )
            {
                printf("Debit!!!n");  
                prevTS = timeStamp;
                listCount  ;
                strcpy(pNode->userName,userID); // use the pointer to assign the userID
                pNode->balance = bal;
                pNode->next = malloc ( sizeof ( struct node));// allocate memory for the next structure

            }
            else if( checkBal == 1 )
            {
                printf("Suspiciously large balance changen");
                prevTS = timeStamp;
                prevBal = bal;
                listCount  ;
                strcpy(pNode->userName,userID); // use the pointer to assign the userID
                pNode->balance = bal;
                pNode->next = malloc ( sizeof ( struct node));// allocate memory for the next structure
            }
            else if( checkBal == 2 amp;amp; checkTS == 2)
            {
                printf("Okn");
                prevTS = timeStamp;
                prevBal = bal;
                listCount  ;
                strcpy(pNode->userName,userID); // use the pointer to assign the userID
                pNode->balance = bal;
                pNode->next = malloc ( sizeof ( struct node));// allocate memory for the next structure
            }

        }

    }
    pNode = amp;root; // set the pointer to the original structure root
    for ( iEach = 0; iEach < listCount; iEach  ) // loop through each structure. ilistCount holds the number of structures
    {
        printf("Location number %d is : (%s,%.2f)n", iEach   1, pNode->userName, pNode->balance);
        pNode = pNode->next; // set the pointer to the next structure

    }

    pNode = root.next; // set the pointer to the first allocated structure
    for ( iEach = 1; iEach < listCount; iEach  ) // loop through each structure
        //start with 1 as the first structure was not allocate and does not need to be freed. ilistCount holds the number of structures
    {
        freeNode = pNode->next; // set the free pointer to the next structure
        free ( pNode); // free the memory for the structure
        pNode = freeNode; // point to the free pointer
    }

}


//Functions
int checkTimeStamp(int currentTS, int prevTS)
{
    if( prevTS >= currentTS)
    {
        return 1;
    }
    else
    {
        return 2;  
    }  
}


int checkBalance(float currentBal, float prevBal)
{
    if( abs(currentBal - prevBal) >= 1000)
    {
        return 1;  
    }
    else if ( currentBal < 0)
    {
        return -1; 
    }
    else
    {
        return 2;  
    }
}
  

Когда ввод :

 Testing 234 234.153
1235 Mega0123test -x-0.5
3600 godzilla 300
36000 godzilla 299
36001 godzilla 2000
36002 godzilla 0
36003 godzilla -10
36004 godzilla1 10
36005 godzilla2 10
36006 godzilla3 10 
1000 innocent 69
^D
  

Вывод должен быть:

 Illegal balance
Ok
Ok
Suspiciously large balance change
Suspiciously large balance change
Debit!!!
Ok
Ok
Ok
Non-monotonic timestamps
Invalid time
Non-monotonic timestamps
godzilla 0
godzilla -10
godzilla1 10
godzilla2 10
godzilla3 10 
  

Но я получаю

 Illegal balance
Ok
Ok
Suspiciously large balance change
Suspiciously large balance change
Debit!!!
Ok
Ok
Ok
Non-monotonic timestamps
Invalid time
Non-monotonic timestamps
Location number 1 is : (godzilla3,10.00)
Location number 2 is : (,0.00)
Segmentation fault (core dumped)
  

Комментарии:

1. @user3121023 Хорошо, так что это решило проблему: D Не могли бы вы сделать это ответом 🙂

2. Кроме того, поскольку вы полагаетесь на связанный список struct node , вам было бы полезно создать одну или две функции, помогающие управлять списком. Один или два быстрых поиска дадут вам идеи для функций create_node и add_node. Также убедитесь, что используемая вами информация относится к одному некруглому связанному списку . Если размер вашего списка превышает 1 м или около того узлов, вы можете захотеть просмотреть циклический двойной связанный список с указателями node-> prev и node-> next, чтобы разрешить повторение fwd и назад, чтобы уменьшить итерации, необходимые для каждого поиска, и т.д..

Ответ №1:

Это не логическая ошибка (по крайней мере, не тот тип, который вы имеете в виду). Сообщение

 Segmentation fault (core dumped)
  

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

В Linux хорошим отладчиком является gdb, отладчик GNU. Средство проверки памяти, которое я в равной степени могу порекомендовать, — это valgrind (и друзья). Ни один из них не установлен по умолчанию, но доступен, например

 sudo apt-get install gdb valgrind
  

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

Комментарии:

1. Где я могу это сделать? Есть ли в Ubuntu какое-либо приложение по умолчанию, которое это делает? @Michael

Ответ №2:

В вашем первом while цикле вы никогда не меняете pNode , поэтому он всегда указывает на root .

Ни один из узлов malloc’d не инициализирован.

Последующие циклы повторяются в неинициализированной памяти.

@user3121023 дайте решение в комментарии к вопросу.