2015-10-03 58 views
0

我有一個文本文件有15個數字和最後一個號碼15。並且,我想閱讀它,我做了以下步驟:轉換字符動態數組atoi到int

  • 首先,我試圖計算txt文件中有多少個數字。
  • 因此,創建了動態大小數組。
  • 試圖將數字保存到與其索引對應的動態數組中。現在

我的問題是,因爲,我從txt文件中的字符串形式中讀取數字。因此,我怎麼能將char轉換爲int動態數組。而且,我使用的算法在終端上生成垃圾值,同時轉換爲int。無法弄清楚它有什麼問題。

我的代碼:

#include <iostream> 
#include <fstream> 

using namespace std; 

int main(int argc, char* argv[]) 
{ 
    char *nPtr = argv[1]; 
    char *buffer = new char[5]; 
    int index = 0; 

    ifstream fin(nPtr); //open the file 

    if (argc > 1) 
    { 
     // allocate the memory 
     if (!fin) 
     { 
      cout << "can't read the file!!" << endl; 
      return -1; 
     } 

     if (fin) 
     { 
      cout << "Open sucessues!! " << endl; 
     } 

     while (!fin.eof()) 
     { 
      fin >> buffer; 
      index++; //counting here!!! 
     } 

     cout << "index: " << index << endl; //print out the counting results! 
     cout << "buffer: " << buffer << endl; // checking the last number! should "15" 

     delete[] buffer; // 
     buffer = NULL; 

     int *number = new int[index]; 
     char *temp = new char[index]; 
     int *home = number; //home 

     while (!fin.eof()) 
     { 
      fin >> temp; 
      *number = atoi(temp); //im confessing right here!!! 
      number++; 
      temp++; 
     } 

     number = home; 

     for (int i = 0; i < index; ++i) 
     { 
      cout << *number << endl; //*number print out garbage, i don't know why! 
      number++; 
     } 
     fin.close(); 
    } 
    return 0; 
} 

垃圾輸出:

Open sucessues!! 
index: 15 
buffer: 15 
0 
1073741824 
0 
1073741824 
2136670223 
32767 
-1680479188 
32767 
0 
0 
0 
0 
0 
0 
0 
+0

您有內存泄漏。你分配一個新的'buffer'數組,但可以在'delete'之前'返回'。 –

+0

@JoelCornett好吧,我只是把緩衝區和分配在while循環一起 – 7llllll

+0

@JoelCornett那麼現在呢? – 7llllll

回答

0

你錯過了 '\ 0' 在你緩衝區。製作你的緩衝區size + 1並在其末尾添加\0,然後垃圾必須消失。

+0

你能告訴我具體嗎?因爲我刪除並指向null。你的意思是我的臨時號碼和號碼必須全部是'\ 0'嗎?因爲我想出15個不同的數字。 – 7llllll

+0

正如我可以看到你的緩衝區大小是5,使其6緩衝區[5] ='\ 0';' –

+0

是的,但你打印垃圾然後你刪除... –

0
while (!fin.eof()) 

Is one of the common sins of C++。它不會做你想做的事。簡單化是你不知道你是否已經達到了文件的結尾,除非你試圖讀過它。這意味着如果您沒有測試成功讀取的結果,您會得到額外的讀取失敗和未定義的結果。

測試成功的閱讀非常簡單,幾乎涵蓋了您可能在學校任務中​​遇到的各種失敗案例,包括EOF。

while (fin >> buffer) 
{ 
    // do stuff 
} 

這意味着大部分的讀邏輯的壓縮下來:

if (!fin) 
{ 
    cout << "can't read the file!!" << endl; 
    return -1; 
} 
while (fin >> buffer) 
{ 
    // do stuff 
} 

我們走了什麼分配要求之前,正確的方法做你想要做的事情是

int tempnumber; 
std::vector<int> numbers; 
while (fin >> tempnumber) // read directly into a number. No further parsing needed. 
{ 
    numbers.push_back(tempnumber); 
} 
if (fin.eof()) // now is when you check eof. 
       // If we didn't get to the end of the file, 
       // there is something wrong with the file 
{ 
    std::cout << "Before sort:" << std::endl; 
    for (int number: numbers) 
    { 
     std::cout << " " << number << std::endl; 
    } 

    // And because I know why you are doing this, you finish off with: 

    std::sort(numbers.begin(), numbers.end()); 
    std::cout << "After sort:" << std::endl; 
    for (int number: numbers) 
    { 
     std::cout << " " << number << std::endl; 
    } 
} 
else // stopped somewhere other than the end of the file. Bad file 
{ 
    std::cerr << "improperly formatted file" << std::endl; 
    return 0; 
} 

可悲的OP有一位教官認爲,學習射擊步槍你應該先學會製造步槍,所以OP無法利用C++的高級特性。我更多的是一門教學邏輯,然後教授低級語言基礎類的人,所以我當然認爲這種教學風格是次優的。

還要注意顯式命名空間的使用。在我看來,這超過了輸入一些額外字符的難度。

但如何做到這一點與動態大小的數組沒有高層次的構造? OP讀取文件兩次:一次大小,第二次獲取內容。相比於你在計算機上做的任何其他操作,文件IO速度都很慢,但工作起來很慢。爲了不讀兩次,一個簡單的單鏈表可以工作,但是OP已經聲明(in their previous question)他們最終需要一個數組來排序列表。

沒有那未盡的要求,該解決方案解決了下來不要使用數組,不轉換爲數字,並

while (fin >> buffer) 
{ 
    cout << buffer<< endl; 
} 

完成。還有其他有趣的技巧,將fin直接轉換成cout,但實質上,它是這樣做的。

這可以通過定義一個動態數組負擔很重的類來解決,但爲什麼? std :: vector填補了市場的空白,爲什麼搶OP的指導者可能是下一個任務?

所以讓我們通過手動調整數組大小來實現。我們要做的是蠻力和白癡。每當數組即將溢出時,我們將創建一個新數組,它是舊數組的兩倍,將舊數據複製到新數組中,釋放舊數據並指向新數組。

#include <iostream> 
#include <fstream> 
#include <cstdlib> 
#include <cstring> 

using namespace std; 

int main(int argc, char* argv[]) 
{ 
    if (argc > 1) 
    { 
     char buffer[100]; // no need for pointer. allocate a big buffer that is 
          // unlikely to overflow 
     int * numbers = new int[10]; // make a dynamic array. 10 seems like a 
            // good starting size 

int *被稱爲原始指針。它不受保護。它必須手動管理。如果出現任何問題,它往往會丟失,它指向的內容變得無法恢復。不要在真實世界中使用原始指針,如果沒有真正的理由,你可以誠實地向其他人解釋和解釋。如果其中一個人說:「但是你可以這樣做。」而且他們是對的,那就做吧。

在考慮使用std::unique_ptr和[std::shared_ptr][5]按照該順序的原始指針檢查之前。 There are a whole raft of better ways to do this,但賠率是指導者將拒絕允許他們。知道它們存在並在可能時使用它們。他們會爲你節省很多的痛苦。

 size_t capacity = 10; // number of items that can go into numbers 

當做索引變量時,贊成size_t。它是無符號的(沒有值< 0)並且保證能夠存儲可以構造的最大對象的字節大小。換句話說,如果它不夠大,你的程序就無法工作。

 size_t size = 0; // number of items currently in numbers 

     ifstream fin(argv[1]); //open the file 

     while (fin >> buffer) // will read up to next whitespace in file. 

這可以讀取超過緩衝區的末尾。被警告。這就是爲什麼我們把緩衝區做得很大

 { 
      int temp = atoi(buffer); 

atoi是原油和容易出現故障的從我這裏不是排渣ÇC的石器時代遺留下來的。一個理智的C程序員使用它時要注意同樣的事情,因爲它是一個非常古老而且非常愚蠢的函數。只能在抗議或極度受控的情況下使用它。

首選strtol及其家族轉換字符數組和std::stoi和家庭轉換std::string s,因爲他們可以爲您捕捉錯誤。優先將std::string用於char數組。

  if (capacity == size) // need to resize numbers 
      { // make a bigger array, copy into bigger array, replace smaller array 
       int * temp = new int[capacity * 2]; // make a bigger array 
       memcpy(temp, numbers, capacity * sizeof(numbers[0])); 

atoimemcpy是原油,但工程。如果向量不在這個賦值中,std :: copy也可能出來。 memcpy適用於簡單的值,如int和double,但贊成std::copy結構和類。memcpy無意識地複製對象或結構中的內容,他們經常在幕後發生其他事情,如指針,複製時需要特殊處理。

   delete numbers; // free the array currently used by numbers 
       numbers = temp; // point at new, bigger array 
       capacity *= 2; // update the capacity to the new size 
      } 
      numbers[size++] = temp; 
     } 
     std::cout << "Before sort:" << std::endl; 
     for (size_t index = 0; index < size; index++) 
     { 
      std::cout << " " << numbers[index] << std::endl; 
     } 
     fin.close(); 
     // call to sorting function goes here. 
    } 
    return 0; 
} 

而且在一個切面正pastable塊:

#include <iostream> 
#include <fstream> 
#include <cstdlib> 
#include <cstring> 

using namespace std; 

int main(int argc, char* argv[]) 
{ 
    if (argc > 1) 
    { 
     char buffer[100]; // no need for pointer. allocate a big buffer that is 
          // unlikely to overflow 
     int * numbers = new int[10]; // make a dynamic array. 10 seems like a 
            // good starting size 
     size_t capacity = 10; // number of items that can go into numbers 
     size_t size = 0; // number of items currently in numbers 

     ifstream fin(argv[1]); //open the file 

     while (fin >> buffer) // will read up to next whitespace in file. 
     { 
      int temp = atoi(buffer); 
      if (capacity == size) // need to resize numbers 
      { // make a bigger array, copy into bigger array, replace smaller array 
       int * temp = new int[capacity * 2]; // make a bigger array 
       memcpy(temp, numbers, capacity * sizeof(numbers[0])); 
       delete numbers; // free the array currently used by numbers 
       numbers = temp; // point at new, bigger array 
       capacity *= 2; // update the capacity to the new size 
      } 
      numbers[size++] = temp; 
     } 
     std::cout << "Before sort:" << std::endl; 
     for (size_t index = 0; index < size; index++) 
     { 
      std::cout << " " << numbers[index] << std::endl; 
     } 
     fin.close(); 
     // call to sorting function goes here. 
    } 
    return 0; 
} 

現在,我們有邏輯下,有改進整體轉換。首先是將main中的所有代碼以及它自己的read功能。這種方式主要是很好,很乾淨,有兩個定義好的子任務,每個子任務都有自己的功能:readsort

爲什麼?人類的頭腦比小的更容易理解小東西。如果一次只有一個問題,那麼保持人類關注也更容易。功能比一個大的readsort功能短。 readsort意味着兩件事情正在進行。當read干擾sort的運作時,大樂趣來自於此。你在調試哪個?兩個都。除非共同混合具有顯着的,可測量的和完全必要的收益,否則將分開的工作分開。

如果您將所有內容都轉換爲mainyou get one massive, confused mess。閱讀代碼變得更加困難。這意味着調試變得更加困難。做任務需要更長的時間。在更直接的方面,標記變得更難。等級變低。

在作爲程序員的現實生活中,由於同事的嘲笑,代碼評審失敗以及最終被從工作中釋放出來,因爲您的個人生產力吸收和清理代碼會拖累整個部門的績效。