我正在为CS1做一个家庭作业,我几乎完成了它,但是我试图实现的一些功能的错误不断出现。赋值是使用链表的大整数的经典加法和减法。我的问题不在于程序的任何数学功能,而是在完成时使链接列表正确打印。我很确定大多数问题都存在于stripLeadingZeros()
之内;功能如下。
/*
* Function stripLeadingZeros
*
* @Parameter STRUCT** Integer
*
* Step through a linked list, recursively unlinking
* all leading zeros and making the first
* non-zero integer the head of the list.
*/
struct integer* stripLeadingZeros( struct integer *p )
{
// Are we at the end of the list?
if( p == NULL ) return NULL;
// Are we deleting the current node?
if( p->digit == 0 )
{
struct integer *pNext;
pNext = p->next;
// Deallocate the node
free( p );
// Return the pointer to the next node
return pNext;
}
// Recurse to make sure next node is not 0
p->next = stripLeadingZeros( p->next );
return p;
}
--- --- ///
/*
* Function print
*
* @Parameter STRUCT* Integer
*
* Given a linked list, will traverse through
* the nodes and print out, one at a time,
* the digits comprising the struct integer that the
* linked list represents.
*
* TODO: Print to file
*/
void print( struct integer *p )
{
struct integer *head = p;
reverse( &p );
p = stripLeadingZeros( p );
while( p )
{
fprintf(outFile, "%d", p->digit);
p = p->next;
}
reverse( &head );
}
--- --- ///
/*
* Function reverse
*
* @Parameter STRUCT** Integer
*
* Recursively reverses a linked list by
* finding the tail each time, and linking the
* tail to the node before it.
*/
void reverse (struct integer **p)
{
/*
* Example p: 1->2->3->4->NULL
*/
if( (*p)->next == NULL ) return;
struct integer *pCurr = *p, *i, *pTail;
// Make pCurr into the tail
while( pCurr->next )
{
i = pCurr;
pCurr = pCurr->next;
}
// Syntactic Sugar
pTail = pCurr;
pTail->next = i;
/*
* p now looks like:
* 1->2->3<->4
*/
i->next = NULL;
/*
* p now looks like:
* 1 -> 2 -> 3 <- 4
* |
* v
* NULL
*/
reverse( p ); // Recurse using p: 1 -> 2 -> 3;
*p = i;
}
我目前为整个计划获得的输出是:
888888888 + 222222222 = 11111111
000000000 - 999999999 = 000000001
000000000 - 999999999 = 000000001
而预期的输出是
8888888888 + 2222222222 = 11111111110
10000000000 – 9999999999 = 1
10000000000 – 9999999999 = 1
任何人都可以给予的任何帮助都会很棒;我一直在研究这个问题已经很长时间了,如果我有任何头发,我现在就把它拉出来。
编辑我的read_integer
功能如下:
/*
* Function read_integer
*
* @Parameter CHAR* stringInt
*
* Parameter contains a string representing a struct integer.
* Tokenizes the string by each character, converts each char
* into an integer, and constructs a backwards linked list out
* of the digits.
*
* @Return STRUCT* Integer
*/
struct integer* read_integer( char* stringInt )
{
int i, n;
struct integer *curr, *head;
int numDigits = strlen( stringInt ); // Find the length of the struct integer
head = NULL;
for( i = 0; i < numDigits; i++ )
{
n = stringInt[i] - '0'; // Convert char to an integer
curr = (struct integer *) malloc (sizeof( struct integer )); // Allocate memory for node
curr->digit = n; // Digit of current node is assigned to n
curr->next = head; // Move to the next node in the list.
head = curr; // Move head up to the front of the list.
}
return head; // Return a pointer to the first node in the list.
}
答案 0 :(得分:5)
在“0004”上模拟stripLeadingZeros()。
它不起作用。你也忽略了一个边缘情况:如果它只是“0”怎么办。在这种情况下,你不能剥掉唯一的0。
正确的代码:
struct integer* stripLeadingZeros( struct integer *p )
{
// Are we at the end of the list?
if( p == NULL ) return NULL;
// Are we deleting the current node? Also it should not strip last 0
if( p->digit == 0 && p->next != NULL)
{
struct integer *pNext;
pNext = p->next;
// Deallocate the node
free( p );
// Try to strip zeros on pointer to the next node and return that pointer
return stripLeadingZeros(pNext);
}
return p;
}
答案 1 :(得分:2)
考虑这个功能的控制流程:
struct integer* stripLeadingZeros( struct integer *p )
{
// Are we at the end of the list?
if( p == NULL ) return NULL;
// Are we deleting the current node?
if( p->digit == 0 )
{
struct integer *pNext;
pNext = p->next;
// Deallocate the node
free( p );
// Return the pointer to the next node
return pNext;
}
// Recurse to make sure next node is not 0
p->next = stripLeadingZeros( p->next );
return p;
}
当p
以零开头时会发生什么?它进入if
语句,删除一个前导零,然后返回。它不递归,因为您已经在if
语句中返回了。这意味着stripLeadingZeros
最多会删除一个零。
现在当p
以一个开头时会发生什么?它会跳过if
语句,但会递归。这也是错误的,因为一旦看到一个,你想停止删除零,因为它们不再领先。
所以这个函数实际上正在做的是删除它遇到的第一个零点,是否结束,然后停止。这不是你想要的。
删除零后,您想要递归,而在删除零之后只想 ,所以将递归调用移到if
语句中。换句话说,将return pNext;
替换为return stripLeadingZeros(pNext);
,并从循环外部删除递归。
答案 2 :(得分:1)
您可以通过将原始列表反转到另一个列表来改善您的反向功能:
void reverse(struct integer** p)
{
struct integer* old = *p;
struct integer* new = NULL;
while(old != NULL)
{
struct integer* oldNext = old->next;
old->next = new;
new = old;
old = oldNext;
}
*p = new;
}
答案 3 :(得分:1)
stripLeadingZeros( nodeptr s )
{
if(s!=NULL)
stripLeadingZeros(s->next);
if((s!=NULL)&&s->data==0&&on)
flg=1;
if((s!=NULL)&&(s->data!=0)&&flg)
on=0,flg=0,s->next=NULL;
if(flg)
s->next=NULL;
}
这是我的代码,用于去除前导零的初始值on和flg分别为1和0。
http://programmingconsole.blogspot.in/2013/10/all-basic-calculator-functions-on-large.html
答案 4 :(得分:0)
在当前版本的stripLeadingZeros
中,您可以使用while
语句替换if
循环,结果将是相同的。也许这就是问题所在。
while (1) {
/* ... */
return 0; /* this "infinite loop" only runs once */
}
与
比较if (1) {
/* ... */
return 0;
}