如何解决关于多项选择题程序的问题
我创建了一个程序来生成多项选择考试的结果。该程序应该显示错误总数,空白答案和错误回答的问题数量。对于以下输入:
6
1..223
(此处.
表示空白)
123124
输出应该是:
Your result:
Mistakes: 3
Blanks: 2
Your mistakes are following:
4 5 6
Your blanks are following:
2 3
但是代码显示了未定义的行为。它似乎经历了无限循环。期待很快解决我的问题。预先感谢。
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
char data;
struct node* next;
}node;
void printNode(node* head)
{
node* local = head;
int i = 0;
if(local -> data == 0)
{
printf("0");
return;
}
while(local != NULL)
{
if(i == 3)
{
i = 0;
printf("\n");
}
printf("%d\t",local -> data);
local = local -> next;
++i;
}
}
void freeNode(node** head)
{
node* temp = (*head);
while((*head) != NULL)
{
(*head) = (*head) -> next;
free(temp);
temp = (*head);
}
}
int main()
{
int n,i,flagB,flagM,blnk,mstk;
blnk = mstk = flagB = flagM = 0;
printf("Enter the number of questions: ");
scanf("%d",&n);
char ques[n],ans[n];
if(n == 0)
return 0;
node* headM = (node*)malloc(sizeof(node));
node* nodeM;
node* headB = (node*)malloc(sizeof(node));
node* nodeB;
printf("Enter your given answers: ");
fflush(stdin);
for(i = 0; i < n; ++i)
{
scanf("%c",&ques[i]);
}
fflush(stdin);
ques[n] = '\0';
printf("Enter the solution: ");
for(i = 0; i < n; ++i)
{
scanf("%c",&ans[i]);
}
ans[n] = '\0';
for(i = 0; i < n; ++i)
{
if(ques[i] == '.')
{
++blnk;
if(flagB == 0)
{
headB -> data = i + 1;
headB -> next = NULL;
nodeB = headB;
continue;
}
nodeB -> next = (node*)malloc(sizeof(node));
nodeB = nodeB -> next;
nodeB -> data = i + 1;
nodeB-> next = NULL;
flagB = 1;
}
else if(ques[i] != ans[i])
{
++mstk;
if(flagM == 0)
{
headM -> data = i + 1;
headM -> next = NULL;
nodeM = headM;
continue;
}
nodeM -> next = (node*)malloc(sizeof(node));
nodeM = nodeM -> next;
nodeM -> data = i;
nodeM-> next = NULL;
flagM = 1;
}
}
printf("Your result:\n\tMistakes: %d\n\tBlanks: %d\n",mstk,blnk);
printf("Your mistakes are follwing:\n");
printNode(headM);
printf("\nYour blanks are follwing:\n");
printNode(headB);
freeNode(&headM);
freeNode(&headM);
return 0;
}
解决方法
我对此代码做了一些更改,请检查一下。
#include <stdio.h>
#include <stdlib.h>
typedef struct Node node;
struct Node
{
int data;
struct Node * next;
};
void printNode(node *head)
{
node *local = head;
while (local != NULL)
{
printf("%d ",local->data);
local = local->next;
}
}
void freeNode(node **head)
{
node *temp = (*head);
while ((*head) != NULL)
{
(*head) = (*head)->next;
free(temp);
temp = (*head);
}
}
int main()
{
int n,i,flagB = 0,flagM = 0,blnk = 0,mstk = 0;
blnk = mstk = flagB = flagM = 0;
printf("Enter the number of questions: ");
scanf("%d",&n);
char ques[n],ans[n];
if (n == 0)
return 0;
node *headM = (node*) malloc(sizeof(node));
headM->data = 0;
node *nodeM = headM;
node *headB = (node*) malloc(sizeof(node));
headB->next = 0;
node *nodeB = headB;
printf("Enter your given answers: ");
for (i = 0; i < n; ++i)
{
scanf("%s",&ques[i]);
}
ques[n] = '\0';
fflush(stdin);
printf("Enter the solution: ");
for (i = 0; i < n; ++i)
{
scanf("%s",&ans[i]);
}
ans[n] = '\0';
fflush(stdin);
for (i = 0; i < n; ++i)
{
if (ques[i] == '.')
{ ++blnk;
if (flagB == 0)
{
nodeB->data = i + 1;
nodeB->next = NULL;
flagB = 1;
continue;
}
nodeB->next = (node*) malloc(sizeof(node));
nodeB = nodeB->next;
nodeB->data = i + 1;
nodeB->next = NULL;
}
else if (ques[i] != ans[i])
{ ++mstk;
if (flagM == 0)
{
nodeM->data = i + 1;
nodeM->next = NULL;
flagM = 1;
continue;
}
nodeM->next = (node*) malloc(sizeof(node));
nodeM = nodeM->next;
nodeM->data = i + 1;
nodeM->next = NULL;
//flagM = 1; //You made a mistake here
}
}
nodeM = headM;
nodeB = headB;
printf("Your result:\n\tMistakes: %d\n\tBlanks: %d\n",mstk,blnk);
printf("Your mistakes are following question numbers:\n");
if (mstk != 0)
printNode(headM);
else
printf("No Mistakes\n");
printf("\nYour blanks are following question numbers:\n");
if (blnk != 0)
printNode(headB);
else
printf("No Blanks\n");
freeNode(&headM);
freeNode(&headM);
return 0;
}
,
这里还有一些其他想法。是什么让您的代码非常复杂,难以调试且难以保持逻辑正确,是因为您在空白和错误的逻辑内混合了链表 Add 函数,并使用特殊条件来处理添加第一个节点和后续节点。这使测试和调试变得困难。如果需要将节点添加到链接列表,请编写一个add()
函数,在将其用于代码之前,可以对其进行彻底的测试和调试。
您的VLA ques
和ans
太短,无法容纳一串n
字符,至少它们必须长n + 1
个字符才能为 nul-termining 字符,用于标记字符串的结尾。理想情况下,您将使它们至少长2个字符,以同时容纳'\n'
,这将允许您使用fgets()
进行输入,而不是一次循环scanf()
一个字符-只是疯了。
您无需将指针的地址传递给freeNode()
,只需传递一个指针即可。当然freeNode()
将收到该指针的副本-但它将包含原始地址-并且由于您无需对该指针进行任何更改即可返回给调用者,因此无需传递指针的地址(完成后不会再担心任何其他列表了……)
因此,将这些部分放在一起,添加一个add()
函数以添加到您的链接列表中(请参阅Linus on Understanding Pointers,以了解为什么使用指针对指针进行迭代)。简单的empty_stdin()
函数可从'\n'
读取stdin
来清除n
剩余的scanf()
,然后再向{{1} }和fgets()
,您可以这样做:
ques
那里有很多东西,所以慢慢来。
使用/输出示例
ans
(注意:在#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* simple function to empty stdin to end-of-line */
void empty_stdin (void)
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
typedef struct node
{
int data;
struct node *next;
} node;
node *add(node **head,int v)
{
node **ppn = head,/* pointer to pointer to head */
*pn = *head,/* pointer to head */
*newn = malloc (sizeof *newn); /* allocate new node */
if (!newn) { /* validate allocation */
perror ("malloc-node");
return NULL;
}
newn->data = v; /* initialize members values */
newn->next = NULL;
while (pn) { /* iterate to end of list */
ppn = &pn->next;
pn = pn->next;
}
return *ppn = newn; /* add & return new node */
}
void printNode (node *head)
{
for (; head; head = head->next)
printf (" %d",head->data);
putchar ('\n');
}
void freeNode(node *head)
{
while (head != NULL)
{
node *victim = head;
head = head->next;
free(victim);
}
}
int main()
{
int n,blnk,mstk;
blnk = mstk = 0;
node *headM = NULL; /* declare pointers and initialize NULL */
node *headB = NULL;
printf ("Enter the number of questions: ");
/* you must VALIDATE every user-input */
if (scanf ("%d",&n) != 1) {
fputs ("error: invalid integer input.\n",stderr);
return 1;
}
empty_stdin(); /* remove '\n' (and any other chars from user) */
/* before calling fgets() below */
if (n == 0) /* check 0 BEFORE VLA declaration */
return 0;
char ques[2*n],ans[2*n]; /* declare question/answer VLAs,don't skimp */
printf("Enter your given answers: ");
if (!fgets(ques,sizeof ques,stdin)) /* read ques from stdin */
return 1;
ques[strcspn(ques,"\r\n")] = 0; /* trim '\n' from end of ques */
printf("Enter the solution: ");
if (!fgets(ans,sizeof ans,stdin)) /* read ans from stdin */
return 1;
ans[strcspn(ans,"\r\n")] = 0; /* ditto for ans */
for(i = 0; i < n; ++i) /* loop n times */
{
if(ques[i] == '.') /* if blank */
{
add (&headB,i + 1); /* add to list headB */
++blnk; /* increment counter */
}
else if(ques[i] != ans[i]) /* if mistake */
{
add (&headM,i + 1); /* add to list headM */
++mstk; /* increment counter */
}
}
printf ("Your result:\n\tMistakes: %d\n\tBlanks: %d\n"
"Your mistakes are following:\n",blnk);
printNode(headM);
printf("\nYour blanks are following:\n");
printNode(headB);
freeNode(headM); /* no need to pass the address of the pointer to free */
freeNode(headB); /* there won't be a list left when freeNode is done */
return 0;
}
和$ ./bin/llquestions
Enter the number of questions: 6
Enter your given answers: 1..223
Enter the solution: 123124
Your result:
Mistakes: 2
Blanks: 2
Your mistakes are following:
4 6
Your blanks are following:
2 3
中,1..223
并非错误,123124
在末尾的正确位置)
仔细检查一下,如果还有其他问题,请告诉我。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。