2013-10-24 49 views
1
#include <iostream> 
#include <cstdlib> 
#include <cctype> 
#include <cmath> 
#include <string> 
#include <iomanip> 
#include <fstream> 
#include <stdio.h> 
using namespace std; 

int main() 
{ 
    ifstream file; 
    string filename; 
    char character; 
    int letters[153] = {}; 

    cout << "Enter text file name: "; 
    cin >> filename;  
    file.open(filename.c_str()); 
    if (! file.is_open()) 
    { 
     cout << "Error opening file. Check file name. Exiting program." << endl; 
     exit(0); 
    } 

    while (file.peek() != EOF) 
    { 
     file >> character; 
     if(!file.fail()) 
     { 
      letters[static_cast<int>(character)]++; 
     } 
    } 

    for (int i = 0; i <= 153; i++) 
    { 
     if (letters[i] > 0) 
     { 
      cout << static_cast<char>(i) << " " << letters[i] << endl; 
     } 
    } 

    exit(0); 
} 

#endif 

大家好,我現在的代碼統計文本文件中每個字母的頻率。但是,它不計算空格的數量。有沒有簡單的方法來打印.txt文件中的空格的數量?在C++中打印出一個文本文件中的空格

另外,當我試圖訪問一個矢量項目時,我怎麼會遇到seg錯誤? 例如,如果我使用:

COUT < < 「」 +字母[I] < < ENDL ;,它顯示一個段錯誤。有任何想法嗎?

非常感謝。

+2

請注意,您的矢量的有效位置是'字母[0]'到'字母[152]'。 –

+0

@WhozCraig:除了你只是使用一個數組,因爲使用'unordered_map'將小整數值映射到整數是過量的。 –

+0

在for循環中,你說「我<= 153」,而你可能想要「我<153」。 for-loops的標準是在條件中使用「<」。 –

回答

2

默認情況下,iostream格式化的輸入提取操作(使用>>的那些操作)將跳過所有空白字符以獲取第一個非空白字符。也許令人驚訝的是,這包括char的提取操作符。爲了考慮空白字符的字符照常進行處理,你應該改變使用noskipws manipulator前處理:

file << std::noskipws; 

不要忘了以後才能再回到上:

file << std::skipws; 

如果什麼你是那些想要創造一種功能的人中的一員,它在離開之前保留了流狀態這個方面(或甚至在所有方面),因爲它是?當然,C++提供了一個令人沮喪的醜陋的方式來實現這一點:

std::ios_base::fmtflags old_fmt = file.flags(); 
file << std::noskipws; 

... // Do your thang 

file.flags(old_fmt); 
+0

如果你這樣做,你會使用'std :: istreambuf_iterator <>'並保存所有的格式設置嗎? – WhozCraig

+0

@WhozCraig:我只是在循環中調用'istream :: get(char&)'。每次我都會嘗試到iostreams的底部,但每次我發現它是一個令人沮喪的混亂,我從來沒有足夠的'streambuf'及其流行與他們打擾的足夠舒適。 –

+0

只是好奇。它確實是爲此而做出的,只是沒有格式化的吸引力而已。如果你有空餘的時間閱讀它,它絕對值得你花時間。 – WhozCraig

1

我只是發佈這個作爲做你明顯嘗試的替代方式。這使用您在代碼中使用的相同查找表方法,但使用istreambuf_iterator直接從流緩衝區中sl出未格式化(和未過濾)的原始字符。

#include <iostream> 
#include <fstream> 
#include <iterator> 
#include <climits> 

int main(int argc, char *argv[]) 
{ 
    if (argc < 2) 
     return EXIT_FAILURE; 

    std::ifstream inf(argv[1]); 
    std::istreambuf_iterator<char> it_inf(inf), it_eof; 

    unsigned int arr[1 << CHAR_BIT] = {}; 
    std::for_each(it_inf, it_eof, 
     [&arr](char c){ ++arr[static_cast<unsigned int>(c)];}); 

    for (int i=0;i<sizeof(arr)/sizeof(arr[0]);++i) 
    { 
     if (std::isprint(i) && arr[i]) 
      std::cout << static_cast<char>(i) << ':' << arr[i] << std::endl; 
    } 

    return 0; 
} 

上非常的源代碼文件本身執行此,(即上面的代碼)生成以下內容:

:124 
#:4 
&:3 
':2 
(:13 
):13 
*:1 
+:4 
,:4 
/:1 
0:3 
1:2 
2:1 
::13 
;:10 
<:19 
=:2 
>:7 
A:2 
B:1 
C:1 
E:2 
F:1 
H:1 
I:3 
L:1 
R:2 
T:2 
U:1 
X:1 
[:8 
]:8 
_:10 
a:27 
b:1 
c:19 
d:13 
e:20 
f:15 
g:6 
h:5 
i:42 
l:6 
m:6 
n:22 
o:10 
p:1 
r:37 
s:20 
t:34 
u:10 
v:2 
z:2 
{:4 
}:4 

只是用不同的方式來做到這一點,但希望它是明確的,通常的C++標準庫提供了優雅的方式來做你想做的事情,如果你深入挖掘,找到那裏有什麼。祝你好運。