Я пытаюсь создать балансировщик HTML-тегов, используя стек. Программа читает символ символа HTML по символу, и всякий раз, когда он встречает открытый тег, он добавляет его в стек. Если он встречает тег close, он пытается удалить его из стека. Однако код компилируется правильно, когда я выполняю его с valgrind, он производит другой и более правильный вывод, чем когда я запускаю его без valgrind. Например:Когда я запускаю этот код с valgrind, выполняется по-другому, когда я запускаю его без valgrind
<html>
<body>
<h1>My First Heading</h1>
<p>My first paragraph.</p>
<p>Hello
</body>
</html>
Когда я запускаю программу предыдущего файла без Valgrind он выходит давая это сообщение:
Error:
The stack is not empty at the end of the file
Stack:
Однако, когда я запускаю эту программу на тот же файл с Valgrind он выходит давая это разные и правильное сообщение:
Error:
Line Number:9
The close tag, body, doesn't match the most recent open tag, p
Вот источник:
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
//#define DEBUG
struct node
{
char* datum;
struct node* next;
};
typedef struct node Node;
struct stack
{
Node* top;
};
typedef struct stack Stack;
bool isEmpty(Stack* s);
char* pop(Stack* s);
void push(Stack* s, char* newItem);
char* peek(Stack* s);
void printStack(Node* s);
size_t size(Stack* s);
Node* makeNode(char* x);
void freeStack(Stack** s);
int lineNumber = 1;
int main(int argc, char** argv)
{
Stack * s = malloc(sizeof(Stack));
s -> top = NULL;
char* tag;
int size;
if(argv[1] == NULL)
{
printf("ERROR: Filename is NULL...Bailing");
exit(1);
}
FILE* htmlFile = fopen(argv[1], "r");
char ch;
//int lineNumber = 1;
while((ch = fgetc(htmlFile)) != EOF && ch != '\n')
{
}
if(ch == EOF)
{
printf("The file id not valid");
free(s);
free(tag);
fclose(htmlFile);
exit(3);
}
while((ch = fgetc(htmlFile)) != EOF)
{
//printf("Line Number: %d\n", lineNumber);
if(ch == '\n')
{
lineNumber++;
}
if(ch == '<')
{
tag = malloc(64*sizeof(char));
size = 0;
while((ch = fgetc(htmlFile)) != EOF && ch != ' ' &&
ch != '>' && ch != '/')
{
//printf("ch = %c\n", ch);
tag[size] = ch;
size++;
if(ch == '\n')
{
lineNumber++;
}
}
if(ch == ' ')
{
//Read through the rest of the tag and see if it is self-closing
while((ch = fgetc(htmlFile)) != EOF &&
ch != '>' && ch != '/')
{
//Don't care about the rest of the tag
}
if(ch == EOF)
{
//print ERROR
printf("Error:\nLine Number: %d\nFile ended during the middle of a tag\n", lineNumber);
free(s);
free(tag);
fclose(htmlFile);
exit(2);
}
else if(ch == '>')
{
//Add tag to stack
push(s, tag);
}
else if(ch == '/')
{
//Don't worry about it
}
}
else if(ch == '>')
{
//Add to stack
push(s, tag);
}
else if(ch == '/')
{
//If size == 0 read the rest of the tag and remove it
//Else dont worry about it
if(size == 0)
{
while((ch = fgetc(htmlFile)) != EOF && ch != ' ' &&
ch != '>')
{
//printf("ch = %c\n", ch);
tag[size] = ch;
size++;
if(ch == '\n')
{
lineNumber++;
}
}
tag[size] = '\0';
//printf("Tag: %s\n", tag);
if(ch == EOF)
{
//Print ERROR
printf("Error:\nLine Number: %d\nFile ended during the middle of a tag\n", lineNumber);
free(s);
free(tag);
fclose(htmlFile);
exit(1);
}
else if(ch == ' ' || ch == '>')
{
printf("Tag: %s, Top: %s\n", tag, peek(s));
//Remove tag from stack or ERROR
if(strncmp(peek(s), tag, size+1) == 0)
{
//Remove tag from stack
pop(s);
}
else
{
//Print ERROR
printf("Error:\nLine Number:%d\nThe close tag, %s, doesn't match the most recent open tag, %s\n", lineNumber, tag, peek(s));
freeStack(&s);
free(tag);
fclose(htmlFile);
exit(3);
}
}
}
}
else if(ch == EOF)
{
//Print ERROR
printf("Error:\nLine Number: %d\nFile ended during the middle of a tag\n", lineNumber);
free(s);
free(tag);
fclose(htmlFile);
exit(4);
}
//printf("Tag: %s\n", tag);
//printStack(s->top);
//printf("\n");
free(tag);
}
printStack(s->top);
printf("\n");
}
if(!isEmpty(s))
{
printf("Error:\nThe stack is not empty at the end of the file\nStack:");
printStack(s->top);
printf("\n");
free(s);
fclose(htmlFile);
exit(5);
}
else
{
printf("The file is valid and all tags are closed.\n");
}
free(s);
fclose(htmlFile);
//free(htmlFile);
//free(tag);
exit(0);
return 0;
}
Возможно, это не ваша главная проблема, но 'char ch' должно быть' int ch' для сравнения EOF, чтобы быть уверенным в правильной работе, –
Также вы не проверяете ошибку при вызове 'fopen'. –
при компиляции всегда включайте все предупреждения, затем исправьте эти предупреждения. (для 'gcc', при минимальном использовании:' -Wall -Wextra -pedantic' Я также использую: '-Wconversion -std = gnu99') – user3629249