2015-10-24 33 views
3

我有一個鏈接列表,它需要幾個輸入文件,然後將它們放入鏈接列表中以便稍後打印它們。打印鏈接列表 - 訪問衝突C++

我實現了一個打印功能,但它不能正常工作,並導致訪問衝突錯誤。我試圖調試,不幸的是我找不到問題的根源。

錯誤行的功能:

cout << ptr2->command + " "; 

運行時錯誤:0000005:訪問衝突讀取位置0xCDCDCDE1中的file.exe在0x00DAC616

第一次機會異常。

下面是代碼:

#include <iostream> 
#include <fstream> 
#include <string> 
#include "strutils.h" 
using namespace std; 

struct Commands; 

struct Functions 
{ 
    string fname; 
    Functions *right; 
    Commands *down; 
}; 
struct Commands 
{ 
    string command; 
    Commands *next; 
}; 

Functions *head; 
Functions *temp; 
Commands *temp2; 

void StreamToLinkedList(ifstream &inputfile) 
{ 
    string s; 
    getline(inputfile, s); 
    temp = new Functions(); 
    temp->fname = s.substr(0, s.length()); 
    temp2 = temp->down; 
    while (!inputfile.eof()) 
    { 
     getline(inputfile, s); 
     temp2 = new Commands(); 
     temp2->command = s.substr(0, s.length()-1) + ","; 
     temp2 = temp2->next; 
    } 
    inputfile.clear(); 
    inputfile.seekg(0); 
} 
void printLinkedList() 
{ 
    Functions *ptr = head; 
    Commands *ptr2; 
    while (ptr != nullptr) 
    { 
     cout << ptr->fname << endl; 
     ptr2 = ptr->down; 
     while (ptr2 != nullptr) 
     { 
      cout << ptr2->command + " "; 
      ptr2 = ptr2->next; 
     } 
     cout << endl; 
     ptr = ptr->right; 
    } 
} 
int main() 
{ 
    string file, key, s; 
    ifstream input; 
    cout <<"If you want to open a service (function) defining the file," << endl 
     <<"then press (Y/y) for 'yes', otherwise press any single key" << endl; 
    cin >> key; 
    ToLower(key); 
    if (key == "y") 
    { 
     cout << "Enter file the input file name: "; 
     cin >> file; 
     input.open(file.c_str()); 
     if (input.fail()) 
     { 
      cout << "Cannot open the file." << endl 
       << "Program terminated." << endl; 
      cin.get(); 
      cin.ignore(); 
      return 0; 
     } 
     else 
     { 
      StreamToLinkedList(input); 
      head = temp; 
      temp = temp->right; 
     } 
    } 
    else 
    { 
     cout << "Cannot found any input file to process" <<endl 
      << "Program terminated."<< endl; 
     cin.get(); 
     cin.ignore(); 
     return 0; 
    } 
    do 
    { 
     cout<< "Do you want to open another service defining file?"<<endl 
      << "Press (Y/y) for 'yes', otherwise press any key" <<endl; 
     cin >> key; 
     ToLower(key); 
     if (key == "y") 
     { 
      cout << "Enter file the input file name: "; 
      cin >> file; 
      input.open(file.c_str()); 
      if (input.fail()) 
      { 
       cout << "Cannot open the file." << endl 
        << "Program terminated." << endl; 
       cin.get(); 
       cin.ignore(); 
       return 0; 
      } 
      else 
      { 
       StreamToLinkedList(input); 
       temp = temp->right; 
      } 
     } 
    } while (key == "y"); 
    cout << "-------------------------------------------------------------------" << endl 
     << "PRINTING AVAILABLE SERVICES (FUNCTIONS) TO BE CHOSEN FROM THE USERS" << endl 
     << "-------------------------------------------------------------------" << endl << endl; 
    printLinkedList(); 
    cin.get(); 
    cin.ignore(); 
    return 0; 
} 

可能是什麼錯誤的代碼?

+0

你忘了問一個問題。你嘗試調試什麼? – aslg

+2

你是否真的需要實現自己的鏈表? ** vs ** std :: list aslg

+0

對於第一個問題,我放棄了它,因爲我必須確保它確實工作;第二,我必須實現我自己的鏈表。 – Oguz

回答

1

來回答

你的打印功能就可以了。您創建和管理列表的方式有什麼不對,可能是由於您從不初始化您的Functions.rightFunctions.down字段,因此您的鏈接列表鏈接到無效內存。那麼,你實際上並沒有鏈接你的名單。

你的一些任務,如temp2 = temp->downtemp = temp->right的,因爲這些領域並沒有初始化並不意味着什麼因爲你要覆蓋這些變量(temptemp2)與後來的新對象。

此外,你有重複的代碼。您在兩個不同的地方以完全相同的方式從文件中讀取數據。問題是你的代碼是錯誤的,所以你有兩倍的錯誤來解決。這裏代碼複製的唯一明顯原因是,您希望在用戶第一次輸入輸入時和第n次顯示不同的消息。

我建議把這個代碼放在它自己的函數中。否則,找一個更有效的方式來使用條件/循環,所以你沒有太多重複的代碼。


注意

我有一個 「幾」 要注意的事情在你的代碼。 LinkedList在兩個類中實現,稱爲FunctionsCommands。我知道你想要有一個函數列表,並且每個函數都有一個命令列表,但是你必須學會​​將程序的域從其他功能中分離出來。

IE: A LinkedList是對象(任何類型)的容器。 A FunctionCommand是您爲程序製作的與鏈接列表本身無關的特定內容。從概念的角度來看一個Function包含Command S,但不一定通過LinkedListmap,或array

你的代碼需要的概念分離,看看它是多麼明顯的是

// Linked list of functions 
Functions list; 

// No need to comment this one 
LinkedList functions; 

(讓我們不要爭論缺乏一個模板類型)

而且,除非是有意義的使用複數命名類,你應該總是用單數(Functions VS Function) 。這是因爲當你實例化一個類時,你將有一個一個對象/實例,因此使用複數作爲類型可能會引起誤解。考慮下面的聲明,

Function someFunction; // This is a single function 
Functions someFunction; // Is this one function or multiple functions?? 

List<Function> functions; // This is a list of functions 
List<Functions> functions; // Is this a list of lists of functions??? 

你應該叫LinkedList的一個類(提示:如果你可以使用模板,使其更具重用性)。然後,如果你要的功能和命令執行從鏈表分開,你可以做類似的東西,

template <class T> 
struct LinkedList { 
    T* obj; 
    LinkedList<T>* next; 

    LinkedList() : obj(nullptr), next(nullptr) {} 
}; 

struct Command { 
    string cname; 
}; 

struct Function { 
    string fname; 
    LinkedList<Command> commands; 
}; 

現在你將宣佈你對這樣的功能列表,

LinkedList<Function> functions; 

由於每個Function擁有自己的Command列表,您擁有列表清單,您不必像當前實施中那樣獨立管理每個列表。當然,你的列表仍然需要一個接口(和內存管理),但這不在這個問題的範圍之內。

編輯:

初始化您的指針nullptr時,他們不會指向任何東西。

temp = new Functions; 
temp->right = nullptr; 
temp->down = nullptr; 

或者美國,一個默認的構造函數,

struct Functions { 
    ... 
    Functions() : right(nullptr), down(nullptr){} 
}; 

然後初始化一樣,

temp = new Functions(); 
+0

@Oguz你在SO。您可以全面搜索模板使用情況。編輯我的問題。 – aslg

+0

*編輯我的答案。 – aslg

1

您的訪問違規問題是,新的默認情況下不調零它分配的內存, 因此最後一個結構中的指針指向一個隨機值。

temp2 = new Commands; // this memory is not initilized to zero 
temp2 = new Commands(); // this memory is initialized to zero, (all elements is set to 0)