- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
所以我实现了一个标准的链表,它在 clang 中编译和运行完美。但是,g++ 抛出了很多错误,并且在消除了常见的内存泄漏之后,出现了一个没有任何书籍/文档/教程可以帮助解决的错误-
struct token{
string data;
string id = "n";
void print(){
cerr<<"| "<<data<<" | ";
}
};
struct node{
token data;
node *next = nullptr;
void print(){
cerr<<" ||| "<<this<<" | "<<data.data<<" | "<<next<<" ||| ";
}
};
class list{
friend class queue;
friend class stack;
public:
node *head = nullptr;
node *tail = nullptr;
void insert(token incoming_data){
if (head == nullptr){
node *new_node = new node;
new_node->data = incoming_data;
new_node->next = nullptr;
head = new_node;
tail = new_node;
new_node = nullptr;
}
else{
node *new_node = new node;
new_node->data = incoming_data;
tail->next = new_node;
new_node->next = nullptr;
tail = new_node;
new_node = nullptr;
}
}
void del(){
cerr<<"List before deletion is ";
print();
cerr<<"\n";
cerr<<"Head is at "<<head;
cerr<<"\n";
if (head == nullptr){
cerr<<"List is empty\n";
return;
}
else if (head->next == nullptr){
tail = nullptr;
cerr<<endl<<"Deleting object at "<<head<<endl;
delete head;
head = nullptr; //keep an eye on this
}
else{
node *temp = head;
head = temp->next;
cerr<<endl<<"Deleting object at "<<temp<<endl;
delete temp;
temp = nullptr;
}
cerr<<"List after deletion is ";
print();
cerr<<"\n";
}
~list(){
cerr<<"Destructor calling delete"<<endl;
while (not(head == nullptr)){
del();
}
}
void insert_front(token incoming_data){
if (head == nullptr){
node *new_node = new node;
new_node->data = incoming_data;
new_node->next = nullptr;
head = new_node;
tail = new_node;
new_node = nullptr;
}
else{
node *new_node = new node;
new_node->data = incoming_data;
new_node->next = head;
head = new_node;
new_node = nullptr;
}
}
};
现在,它可以独立运行。使用它实现的堆栈和队列工作得很好。但是,在析构函数试图调用它时的某个时刻,会发生这种情况-
Destructor calling delete
List before deletion is
||| 0x100409bc0 | 55 | 0x100431890 ||| --> ||| 0x100431890 | 5 | 0x100504830 ||| --> ||| 0x100504830 | + | 0x0 ||| --> NULL
Head is at 0x100409bc0
Deleting object at 0x100409bc0
test shunting yard (76600,0x10039e380) malloc: *** error for object 0x100409bc0: pointer being freed was not allocated
节点以|||格式打印本节点地址 |资料 |下一个节点的地址||
是的,每个节点都是使用“new”动态创建的。此外,同一个析构函数和 del 函数在同一个程序中可以完美运行多次,但对于一个特定的实例,会失败。
在其他具有相同错误的堆栈溢出问题中,指针没有指向任何东西,但是这里显然有一个对象可以在有问题的指针处删除。
编辑:它是使用 Shunting-Yard 实现的 RPN 解析,这是完整的代码-
#include <iostream>
#include <string.h>
#include<cmath>
using namespace std;
struct token{
string data;
string id = "n";
void print(){
cerr<<"| "<<data<<" | ";
}
};
struct node{
token data;
node *next = nullptr;
void print(){
cerr<<" ||| "<<this<<" | "<<data.data<<" | "<<next<<" ||| ";
}
};
class list{
friend class queue;
friend class stack;
public:
node *head = nullptr;
node *tail = nullptr;
void insert(token incoming_data){
if (head == nullptr){
node *new_node = new node;
new_node->data = incoming_data;
new_node->next = nullptr;
head = new_node;
tail = new_node;
new_node = nullptr;
}
else{
node *new_node = new node;
new_node->data = incoming_data;
tail->next = new_node;
new_node->next = nullptr;
tail = new_node;
new_node = nullptr;
}
}
void print(){
cerr<<endl;
if (head == nullptr){
cerr<<"List is empty";
}
else{
node *active_ptr = head;
while(active_ptr!=nullptr){
active_ptr->print();
cerr<<" --> ";
active_ptr = (*active_ptr).next;
}
cerr<<"NULL\n";
}
}
void del(){
cerr<<"List before deletion is ";
print();
cerr<<"\n";
cerr<<"Head is at "<<head;
cerr<<"\n";
if (head == nullptr){
cerr<<"List is empty\n";
return;
}
else if (head->next == nullptr){
tail = nullptr;
cerr<<endl<<"Deleting object at "<<head<<endl;
delete head;
head = nullptr; //keep an eye on this
}
else{
node *temp = head;
head = temp->next;
cerr<<endl<<"Deleting object at "<<temp<<endl;
delete temp;
temp = nullptr;
}
cerr<<"List after deletion is ";
print();
cerr<<"\n";
}
bool is_empty(){
if (head == nullptr){
return true;
}
else return false;
}
token first_elem(){
return head->data;
}
~list(){
cerr<<"Destructor calling delete"<<endl;
while (not(head == nullptr)){
del();
}
}
void insert_front(token incoming_data){
if (head == nullptr){
node *new_node = new node;
new_node->data = incoming_data;
new_node->next = nullptr;
head = new_node;
tail = new_node;
new_node = nullptr;
}
else{
node *new_node = new node;
new_node->data = incoming_data;
new_node->next = head;
head = new_node;
new_node = nullptr;
}
}
};
class queue{
public:
list l_queue_list;
void push(token incoming_data){
l_queue_list.insert(incoming_data);
}
void pop(){
if(is_empty()){
return;
}
l_queue_list.del();
}
token peek(){
return (l_queue_list.first_elem());
}
void print(){
l_queue_list.print();
}
bool is_empty(){
if(l_queue_list.is_empty())
return true;
else return false;
}
};
class stack{
public:
list l_stack_list;
void push(token incoming_data){
l_stack_list.insert_front(incoming_data);
}
void pop(){
if(is_empty()){
return;
}
l_stack_list.del();
}
token peek(){
return l_stack_list.first_elem();
}
void print(){
l_stack_list.print();
}
bool is_empty(){
if(l_stack_list.is_empty())
return true;
else return false;
}
};
class Thermostat{
public:
bool heating, cooling, user_setting, valid_command = true; //command is valid until an exception is thrown
int current_temp, desired_temp;
Thermostat(string cmd){
try{
lexer(&cmd);
logic();
}
catch(...){
raise_error(7);
}
}
private:
void lexer(string *cmd) {
string command = *cmd;
int pos = 0, len = (int)command.length();
char *start = NULL, *end = NULL;
if (!(command.find_first_not_of("TtCcHh0123456789+-") == string::npos)){
raise_error(0);
return;
}
if (command[pos] != 'T' and command[pos] !='t' and !(isdigit(command[pos+1]))){
raise_error(1);
return;
}
else{
pos++;
if(!isdigit(command[pos])){
raise_error(2);
return;
}
start = &command[pos];
while(isdigit(command[pos]) and pos<len)
pos++;
end = &command[--pos];
current_temp = parse_digits(start, end);
pos++;
if (pos == len){
user_setting = false;
return;
}
else if(command[pos]!='H' and command[pos]!='h' and command[pos]!='C' and command[pos]!='c'){
raise_error(3);
return;
}
else{
user_setting = true;
if(command[pos] == 'H' or command[pos] == 'h')
heating = true;
if(command[pos] == 'C' or command[pos] == 'c')
cooling = true;
pos++;
if(!isdigit(command[pos])){
raise_error(4);
return;
}
desired_temp = parse_expression(pos, cmd);
}
}
}
int parse_digits(char *start, char *end){
int temperature = 0, place_value = 0;
for(; end>=start; end--){
temperature = temperature + (*end-'0') * pow(10,place_value);
place_value++;
}
return temperature;
}
queue generate_expression_queue(int pos, string *cmd){ //Generates the expression queue for Shunting-Yard to work on
string command = *cmd, literal ="";
queue exp_queue;
int flag = pos;
for(; pos<=command.length(); pos++){
if(command[pos] == '+' or command[pos]=='-'){
literal = command.substr(flag, (pos-flag)); //Literals are numbers precceded by operators
token tok1, tok2;
tok1.data = literal;
tok2.data =(string(1, command[pos])); //Converting the operator to string-type inline
tok2.id = "o";
exp_queue.push(tok1);
exp_queue.push(tok2);
flag = pos+1;
}
}
token tok3;
tok3.data = (command.substr(flag, (command.length()-flag))); //token 3 carries the last digits which aren't succeeded by an operator
exp_queue.push(tok3);
return exp_queue;
}
queue shunting_yard(queue exp_queue) { //Simplified execution of shunting-yard because expressions don't have parantheses or operator precedence
queue output;
stack ops;
token temp;
while(!exp_queue.is_empty()){
if(exp_queue.peek().id=="n"){
temp = exp_queue.peek();
output.push(temp);
exp_queue.pop();
}
else if(exp_queue.peek().id=="o"){
if(ops.is_empty()){
temp = exp_queue.peek();
ops.push(temp);
exp_queue.pop();
}
else {
temp = ops.peek();
output.push(temp);
ops.pop();
temp = exp_queue.peek();
ops.push(temp);
exp_queue.pop();
}
}
}
while(!ops.is_empty()){
temp = ops.peek();
output.push(temp);
ops.pop();
}
return output;
}
token eval(token op1, token op2, token operation){// Evaluate binary operation of + or -
int num1, num2, result;
token output;
try {
num1 = stoi(op1.data);
num2 = stoi(op2.data);
if(num1 == 0 or num2 == 0){ // Increment or Decrement by 0 not allowed
raise_error(6);
return output;
}
if(operation.data == "+"){
result = num1 + num2;
output.data = to_string(result);
return output;
}
else if (operation.data == "-"){
result = num1 - num2;
output.data = to_string(result);
return output;
}
else{
raise_error(5);
return output;
}
}
catch(...){
raise_error(5);
return output;
}
}
int reverse_polish_parse(queue exp_queue){ //RPN parsing algorithm
stack ops_stack;
token op1, op2, operation, temp;
while(!exp_queue.is_empty()){
if(exp_queue.peek().id == "n"){
temp = exp_queue.peek();
ops_stack.push(temp);
exp_queue.pop();
}
else if(exp_queue.peek().id == "o"){
op1 = ops_stack.peek();
ops_stack.pop();
op2 = ops_stack.peek();
ops_stack.pop();
operation = exp_queue.peek();
exp_queue.pop();
token x = eval(op2, op1, operation);
ops_stack.push(eval(op2,op1,operation));
}
}
try{
return (stoi(ops_stack.peek().data));
}
catch(...){
raise_error(5);
return -1000;
}
}
int parse_expression(int pos, string*cmd){//
queue exp_queue = generate_expression_queue(pos, cmd);
exp_queue = shunting_yard(exp_queue);
return reverse_polish_parse(exp_queue);
}
void raise_error(int id){
valid_command = false;
switch (id) {
case 0:
cerr<<"Ilegal characters\n";
break;
case 1:
cerr<<"First letter of command must be T or t\n";
break;
case 2:
cerr<<"T must be followed by current temperature\n";
break;
case 3:
cerr<<"Current temperature must be followed by setting\n";
break;
case 4:
cerr<<"Setting must be followed by a vaid expression\n";
break;
case 5:
cerr<<"Error parsing expression token. Please check\n";
break;
case 6:
cerr<<"Increment or Decrement should be more than 0\n";
break;
case 7:
cerr<<"Please don't walk into a bar and try to order -5 beers. Thanks :) \n";
break;
default:
break;
}
}
void logic(){
if (heating and current_temp >= desired_temp){
heating = false;
}
if (cooling and current_temp <= desired_temp){
cooling = false;
}
}
};
bool isWellFormedThermostatString(string commands){
Thermostat thermos(commands);
return thermos.valid_command;
}
int temperature(string commands){
Thermostat thermos(commands);
if (thermos.valid_command){
return thermos.current_temp;
}
else return -1;
}
int setting(string commands){
Thermostat thermos(commands);
if (thermos.valid_command and thermos.user_setting){
return thermos.desired_temp;
}
else if(thermos.valid_command){
return 0;
}
else return -1;
}
bool isHeating(string commands){
Thermostat thermos(commands);
if (thermos.valid_command) //Extra security doesn't hurt :)
return thermos.heating;
else return false;
}
bool isCooling(string commands){
Thermostat thermos(commands);
if (thermos.valid_command)
return thermos.cooling;
else return false;
}
int main(){
string str = "T205h55+5";
cerr<<"\nThe command is valid: "<<boolalpha<<isWellFormedThermostatString(str)<<endl<<endl;;
cerr<<"Current temperature is "<<temperature(str)<<endl<<endl;
cerr<<"User's desired temperature "<<setting(str)<<endl<<endl;
cerr<<"Heating: "<<boolalpha<<isHeating(str)<<endl<<endl;
cerr<<"Cooling: "<<boolalpha<<isCooling(str)<<endl<<endl;
}
最佳答案
您的列表用作queue
和stack
类的直接成员。 queue
类在您的代码中按值传递。自 Rule of Three被你的 list
类违反了,它会不可避免地导致典型的问题,比如双重删除、访问释放的内存等等。
list
的当前编译器提供的复制构造函数和复制赋值运算符执行 list
对象的浅复制,即相同 list< 的所有拷贝
将引用相同的节点链表。当一个这样的实例被破坏时,它会释放列表。之后,其他拷贝将指向已释放的内存。
如果您真的想按值传递这些类,您必须遵循三规则(或五规则)。您必须为您的 list
类正确实现复制构造函数和复制赋值运算符。
另一种解决方案是避免按值传递这些对象。如果您决定采用这种方式,请将复制构造函数和复制赋值运算符定义为“已删除”。这将确保您永远不会无意中对这些对象进行浅拷贝。
关于c++ - 'delete' 在 clang 中完美编译时在 g++ 中抛出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51395051/
我目前正在尝试让 g++ 工作,并查看 http://gcc.gnu.org/install/build.html ,我似乎找不到它在哪里说如何“执行编译器的 3 阶段 bootstrap ”。我在哪
James Powell 在他对即将举行的演示文稿的简短描述中说,他自豪地发明了最粗糙的 Python 单行代码之一: (None for g in g if (yield from g) and F
请告诉我我的证明是否正确 We have a connected graph, and specific vertex u in V(G). Suppose we compute the dfs tr
下面的test2和test3结果是不同的。 我对此感到困惑,因为它看起来像相同的逻辑,并且与linux bash ||逻辑不同。 $data = @( [PSCustomObject]@{St
我试图找到一个明确的 G 代码语法规范,而不是单个 G 代码的含义,我无处不在的规范,我的意思是详细的语法规范,目的是编写解析器。 我编写解析器没有问题,我只是在寻找语法规范,例如。我知道您不必总是为
我写了这个 mixin,但它循环了很多时间。你能帮我优化我的代码吗?或者你能建议一些其他的东西来获得想要的结果吗? dfgdfgsdfgsdf 最佳答案 希望这就是您要找的。 $spaces: (4,
默认情况下,g++ 似乎会省略未使用的类内定义方法的代码。示例 from my previous question : struct Foo { void bar() {} void baz(
是否可以将文件内容通过管道传送到 g++编译程序? 我想这样做是因为我想使用数据库中的文件而不是磁盘上的物理文件。可以通过我制作的 API 轻松检索文件内容。 例如,我想做这样的事情: g++ con
如何profile c++代码获取每行代码的调用次数和消耗时间,就像profile工具一样在 Matlab 中呢? 我尝试使用-fprofile-arcs之类的东西,但它只生成代码覆盖率报告,其中可以
如何在几行代码上禁用所有警告。可以使用 GCC 诊断功能禁用特定警告,但是否有针对所有警告的标志。我尝试了这个方法,但不起作用 #pragma GCC diagnostic push #pragma
我有一个链接到 opencv 2.2 的可执行文件。但是,我删除了 opencv 2.2 并安装了 opencv 2.3。 问题是,有没有办法在不重新编译整个源代码的情况下将这个可执行文件链接到新的共
在编译带有一些标志的以下文件时,是否可以让 g++ 显示错误? #include using namespace std; int main() { int arr[ 2 ]; cout
在学习 Haskell 时,我遇到了一个挑战,要找到两个函数 f 和 g,例如 f g 和 f 。 g 是等价的(并且是总计,因此像 f = undefined 或 f = (.) f 这样的东西不算
根据我的理解,Theta 位于 Big O 和 Omega 之间,但我看到了这个声明,但我无法理解为什么交集会出现在这里。我能否对 Θ(g(n)) = O(g(n)) ∩ Ω(g(n)) 获得数学和分
我需要为这个递归函数编写一个迭代函数。 int funcRec(int n){ if(n>1) { return 2*funcRec(n - 1) + 3*funcRec(n
我在 github repository 上有代码示例并在 travis-ci 上创建了一个构建便于复制。 最小的、完整的和可验证的例子 可能不是最小的,但我相信它足够小 它使用 boost.inte
编辑:我们将调用箭头 p纯如果存在这样的函数f即:p = arr f . 我试图更好地掌握 Haskell 中的 Arrows,我想弄清楚什么时候 f >>> (g &&& h) = (f >>> g
我有两个(或更多)函数定义为: val functionM: String => Option[Int] = s => Some(s.length) val functionM2: Int => Op
好像是的。任何直观或严肃的证据都值得赞赏。 最佳答案 没有。 我认为您的问题等同于:给定函数 f 和 g,f 是 O(g) 或 g 是 O(f) 是否总是正确的?这在 SE Computer Scie
如果我设法证明 f(n) = o(g(n))(小 o),那么这两个函数的总和 f( n) + g(n) 应该被“更大”的函数 g(n) 紧紧束缚。 然而,我在证明这一点时遇到了一些麻烦。 最佳答案 以
我是一名优秀的程序员,十分优秀!