#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 дайте решение в комментарии к вопросу.