簡體   English   中英

我的C ++代碼中的Letter計數器無法正常工作

[英]The Letter counter within my C++ code is not working properly

因此我的程序運行正常,除了一件事,函數計數的字母不正確。 例如,如果輸入“為什么在那里”! 作為字符串,顯示的字母數是3,而不是13。我不確定我做錯了什么,將不勝感激。 謝謝!

這是我的代碼:

#include <iostream>
#include <cstring>
#include <iomanip>

using namespace std;

void Count_All(char*, int&, int&, double&, int&); // Function prototype.
double Calc_Average (char*, int, int, double); // Function prototype.

int main()
{
    const int size = 500;
    char userString[size];
    int Word = 0;
    int Pun = 0;
    int Letters = 0;
    double Total_Characters = 0;
    double Average = 0.0;

    cout << "Please enter a string of 500 or less characters: ";
    cin.getline(userString, size);

    int len = strlen(userString);
    char *Dyn_Array = new char[len+1];
    strcpy(Dyn_Array, userString);

    cout << "\n";

    Count_All (Dyn_Array, Letters, Word, Total_Characters, Pun);

    cout << "Number of letters in the string: " << Letters << "\n";
    cout << "\n";
    cout << "Number of words in the string: " << Word << "\n";
    cout << "\n";

    Average = Calc_Average (Dyn_Array, Word, Pun, Total_Characters);
    cout <<"Average number of letters per word: "<< fixed <<
    showpoint << setprecision(2) << Average << "\n" << endl;


    cin.ignore(1);
    delete [] Dyn_Array;
    return 0;
}

void Count_All (char*strptr, int &Letters, int &Word, double &Total_Characters, int &Pun) // Counts all characters and types.
{
    while (*strptr != '\0')
    {
        if ((isspace(*strptr)) || (ispunct(*strptr)))
        {
            while ((isspace(*strptr)) || (ispunct(*strptr)))
            {
                strptr++;
            }
        }

        for(int x = 0; x < strlen(*strptr); x++)
        {
            if(!isspace(strptr[x]) && !Ispunct(strptr[x]))
            {
                Letters++;
            }
        }

        //if (((*strptr >= 'a') && (*strptr <= 'z')) || ((*strptr >= 'A') && (*strptr <= 'Z')))
            //Letters++;

        if ((isalnum(*strptr)) || (ispunct(*strptr)))
        {
            Word++;
            while ((isalnum(*strptr))||(ispunct(*strptr)))
            {
                strptr++;
                Total_Characters++; // Counting the total printable characters (including digits and punctuation).

                if((ispunct(*strptr)))
                {
                    Pun++; // Counting punctuation.
                }

            }
        }
        strptr++;
    }
}

double Calc_Average(char*strptr, int Word, int Pun, double Total_Characters)  // Calculates the average number of characters per words.
{
    double Average = 0.0;
    Total_Characters = Total_Characters - Pun; // Subtracting punctuation from all of the characters in the string (not including spaces).
    Average = (Total_Characters / Word);
    return Average;
}
for(int x = 0; x < strlen(*strptr); x++)

鑒於strptrchar * ,您的編譯器很可能會大聲地對您大喊大叫,因為您是將char傳遞給strlen()而不是char * 即使編譯器仍生成可執行文件,也不能忽略來自編譯器的大聲尖叫。

即使按以下方式解決此問題,仍然會產生完全錯誤的結果:

    for(int x = 0; x < strlen(strptr); x++)
    {
        if(!isspace(strptr[x]) && !Ispunct(strptr[x]))
        {
            Letters++;
        }
    }

這是第二個內部循環。 外循環在每個字符上迭代strptr ,執行一堆東西,包括這個內循環。

因此,如果所討論的字符串是“ hello”:

  1. 在外循環的第一次迭代中, strptr指向“ h ”,並且該內循環將5加到Letters

  2. 在外循環的第二次迭代中, strptr指向“ e ”,並且該內循環將4加到Letters

  3. 在外部循環的第三次迭代中, strptr指向第一個“ l ”,並且此內部循環將3加到Letters

  4. 在外循環的第四次迭代中, strptr指向第二個“ l ”,並且該內循環將2加到Letters

  5. 在外循環的第五次迭代中, strptr指向' o ',並且該內循環將1加到Letters

該代碼最終計數字符串“ hello”中的5 + 4 + 3 + 2 + 1或15個字母。 顯然不是正確的結果。

完全不需要此內部循環。 擺脫它。

您還應該在計算機上找到一個非常有用的工具,稱為“調試器”。 使用此工具,您將能夠一步一步地執行代碼,檢查所有變量,並自行確定此問題。 學習如何使用調試器是每個C ++開發人員的必備技能。

編輯:字母計數可能應該合並在您的單詞檢測器中,因為它也可以提高strptr 它不僅搞亂了單獨的字母計數邏輯,而且還因其自身的優點而被打破,因為它可能會將strptr推進到終止\\0字符,而最終的strptr++將再次推進它,導致不確定的行為,並且可能會崩潰。 總體邏輯有太多問題。 應該從頭開始重寫它。

效率很棒。 一次完成所有操作可能會很棒,但是它很少優雅,並且經常是真正的[刪除專有內容]進行調試。 結果,在軟件工程中建議您做一件事並做好。

Count_All計算字母,單詞和標點符號,並通過幾種不同的方式將其弄錯。 很難弄清楚哪一部分功能被破壞了,因為錯誤傾向於相互滋養並相互隱藏。

另一方面,具有三個函數Count_Punctuation ; Count_LettersCount_Words各自Count_Words一件事。 每個都可以分別編寫,分別測試和調試。 編寫一個函數。 證明它有效。 繼續寫作並證明下一個功能。 沖洗,重復。

產生的結果並不像高度優化的多合一解決方案那樣快,但是您可以更快地進行編碼和調試。 這在學習時非常重要。 這意味着您可以花費更多時間進行學習。

例如:

int Count_Punctuation(char * strptr)
{
    int punc = 0;
    while (*strptr != '\0')
    {
        if (ispunct(*strptr))
        {
            punc ++;
        }
        strptr++;
    }
    return punc;
}

每個字符一個循環。 如果字符是標點符號,則增加計數器。 當字符不足時返回計數器。

Count_Letter幾乎相同,但計數字母。 Count_Word有點棘手。

正如Sam所說,您需要成為strlen函數的指針。 然后,您需要將字母計數器移到while循環之外,並且應該可以。 像這樣:

for(int x = 0; x < strlen(strptr); x++)
{
   if(!isspace(strptr[x]) && !Ispunct(strptr[x]))
   {
   Letters++;
   }
}

while (*strptr != '\0')
{
    if ((isspace(*strptr)) || (ispunct(*strptr)))
    {
        while ((isspace(*strptr)) || (ispunct(*strptr)))
        {
            strptr++;
        }
    }

    if ((isalnum(*strptr)) || (ispunct(*strptr)))
    {
        Word++;
        while ((isalnum(*strptr))||(ispunct(*strptr)))
        {
            strptr++;
            Total_Characters++; // Counting the total printable characters (including digits and punctuation).

            if((ispunct(*strptr)))
            {
                Pun++; // Counting punctuation.
            }

        }
    }
    strptr++;
}

我已更新以解決評論中的問題,據我測試,現在更好了...

#include <iostream>
#include <cstring>
#include <iomanip>

using namespace std;

void Count_All(char*, int&, int&, double&, int&); // Function prototype.
double Calc_Average (char*, int, int, double); // Function prototype.

int main()
{
    const int size = 500;
    char userString[size];
    int Word = 0;
    int Pun = 0;
    int Letters = 0;
    double Total_Characters = 0;
    double Average = 0.0;

    cout << "Please enter a string of 500 or less characters: ";
    cin.getline(userString, size);

    int len = strlen(userString);
    char *Dyn_Array = new char[len+1];
    strcpy(Dyn_Array, userString);

    cout << "\n";

    Count_All (Dyn_Array, Letters, Word, Total_Characters, Pun);

    cout << "Number of letters in the string: " << Letters << "\n";
    cout << "\n";
    cout << "Number of words in the string: " << Word << "\n";
    cout << "\n";

    Average = Calc_Average (Dyn_Array, Word, Pun, Total_Characters);
    cout <<"Average number of letters per word: "<< fixed <<
    showpoint << setprecision(2) << Average << "\n" << endl;


    cin.ignore(1);
    delete [] Dyn_Array;
    return 0;
}

void Count_All (char*strptr, int &Letters, int &Word, double &Total_Characters, int &Pun) // Counts all characters and types.
{
    // sorry this was a test: strptr[strlen(strptr)+1]='\0';
    while (strptr[0] != '\0')
    {
        while (isspace(strptr[0]))
        {
            strptr++;
        }

        if(!isspace(strptr[0]) && !ispunct(strptr[0]))
        {
            cout << strptr[0] << " ";
            Letters++;
            Total_Characters++; // Counting the total printable characters (including digits and punctuation).
            strptr++;
            if(strptr[0] == '\0' || isspace(strptr[0]) || ispunct(strptr[0]))
            {
                Word++;
            }
        }

        if ((isalnum(strptr[0])) || (ispunct(strptr[0])))
        {
            if((ispunct(strptr[0])))
            {
                Pun++; // Counting punctuation.
                Total_Characters++; // Counting the total printable characters (including digits and punctuation).
                strptr++;
            }
        }
    }
}

double Calc_Average(char*strptr, int Word, int Pun, double Total_Characters)  // Calculates the average number of characters per words.
{
    double Average = 0.0;
    Total_Characters = Total_Characters - Pun; // Subtracting punctuation from all of the characters in the string (not including spaces).
    Average = (Total_Characters / Word);
    return Average;
}

使用有限狀態機循環遍歷字符串中的每個字符,以跟蹤我們是否在一個單詞中,並計算單詞的數量。

#include <iostream>
#include <cstring>
#include <iomanip>

#include <string>

using namespace std;

const int STATE_WITHOUT = 1;
const int STATE_IN_WORD = 2;

class TestInput {
    public:
        string m_s_input;
        int m_i_expected_words;
        int m_i_expected_punctuation_marks;
        int m_i_expected_letters;
        int m_i_expected_total_printable_characters;

    TestInput(
        string s_input,
        int i_expected_words,
        int i_expected_punctuation_marks,
        int i_expected_letters,
        int i_expected_total_printable_characters
    ):  m_s_input(s_input),
        m_i_expected_words(i_expected_words),
        m_i_expected_punctuation_marks(i_expected_punctuation_marks),
        m_i_expected_letters(i_expected_letters),
        m_i_expected_total_printable_characters(i_expected_total_printable_characters)
    {}
}; /* class TestInput */

// Counts all characters and types. 
void Count_All (const string& str, int &Letters, int &Words, int &Total_Printable_Characters, int &Punctuation_Marks) {

    // Clear all these "out params" so the caller can call this
    // method multiple times without having to theirself
    // clear them...
    Letters = 0;
    Words = 0;
    Total_Printable_Characters = 0;
    Punctuation_Marks = 0;

    int i_state = STATE_WITHOUT;

    char c = '\0';

    for( size_t i = 0; i < str.length(); i++ ){

        c = str[i];

        if( isalpha(c) )
        {
            Letters++;
        }

        if( isalnum(c) || ispunct(c) )
        {
            Total_Printable_Characters++; // Counting the total printable characters (including digits and punctuation).
        }

        if( ispunct(c) ) 
        {
            Punctuation_Marks++;
        }

        /* Use finite-state machine to count words... */
        switch( i_state ){
            case STATE_WITHOUT:
                if( ispunct(c) || isalnum(c) )
                {
                    i_state = STATE_IN_WORD;
                    Words++;
                }
                break;

            case STATE_IN_WORD:
                if( isspace(c) )
                {
                    i_state = STATE_WITHOUT;
                }
                break;
        }/* switch( i_state ) */

    }/* for( size_t i = 0; i < str.length(); i++ ) */

}/* Count_All() */

// Calculates the average number of characters per words.
double Calc_Average(int Word, int Pun, int Total_Characters){
    double Average = 0.0;

    Total_Characters = Total_Characters - Pun; // Subtracting punctuation from all of the characters in the string (not including spaces).

    if( Word == 0 ){
        // Avoid divide by zero error...
        return 0.0;
    }

    Average = ((double)Total_Characters / (double)Word);

    return Average;
}/* Calc_Average() */

int main()
{
    int Words = 0;
    int Punctuation_Marks = 0;
    int Letters = 0;
    int Total_Printable_Characters = 0;

    double Average = 0.0;

    TestInput test_inputs[] = {
        // s_input, i_expected_words, i_expected_punctuation_marks, i_expected_letters, i_expected_total_printable_characters 
        TestInput("", 0, 0, 0, 0 ) 
        ,TestInput(" ", 0, 0, 0, 0 ) 
        ,TestInput("Why, hello there!", 3, 2, 13, 15 ) 
        ,TestInput("I am sam.", 3, 1, 6, 7 ) 
        ,TestInput("I'll take 1 bagel.", 4, 2, 12, 15 ) // Counting both contraction "I'll" and numerical "1" as one word each...as "wc" utility seems to do...
        ,TestInput("I'll be back, Bennett!", 4, 3, 16, 19) 
        ,TestInput("Let off some steam, Bennett!", 5, 2, 22, 24) 
        ,TestInput("Supercalifragilisticexpyalidocious", 1, 0, 34, 34 )
        ,TestInput("'ere, what'cha doin' 'ere, guv'nor?", 5, 8, 23, 31 )
        ,TestInput(" 'ere, what'cha doin' 'ere, guv'nor?", 5, 8, 23, 31 )
        ,TestInput("That's one small step for a man, one giant leap for mankind.", 12, 3, 46, 49 )
    };

    for( size_t i = 0; i < sizeof(test_inputs)/sizeof(TestInput); i++ ){
        cout << "i = " << i << ": Running Count_All( \"" << test_inputs[i].m_s_input << "\" )\n" 
               << "\t" << "(length of input = " << test_inputs[i].m_s_input.length() << ")..." << endl;

        Count_All( test_inputs[i].m_s_input, Letters, Words, Total_Printable_Characters, Punctuation_Marks );

        cout << "i = " << i << ": Letters = " << Letters << " (Expected " << test_inputs[i].m_i_expected_letters << ")..."
            << (( Letters == test_inputs[i].m_i_expected_letters ) ? "PASSED" : "FAILED" ) << "..." << endl;

        cout << "i = " << i << ": Words = " << Words << " (Expected " << test_inputs[i].m_i_expected_words << ")..."
            << (( Words == test_inputs[i].m_i_expected_words ) ? "PASSED" : "FAILED" ) << "..." << endl;

        cout << "i = " << i << ": Total_Printable_Characters = " << Total_Printable_Characters << " (Expected " << test_inputs[i].m_i_expected_total_printable_characters << ")..."
            << (( Total_Printable_Characters == test_inputs[i].m_i_expected_total_printable_characters) ? "PASSED" : "FAILED" ) << "..." << endl;

        cout << "i = " << i << ": Punctuation_Marks = " << Punctuation_Marks << " (Expected " << test_inputs[i].m_i_expected_punctuation_marks << ")..."
            << (( Punctuation_Marks == test_inputs[i].m_i_expected_punctuation_marks ) ? "PASSED" : "FAILED" ) << "..." << endl;

        Average = Calc_Average ( Words, Punctuation_Marks, Total_Printable_Characters);

        cout << "i = " << i << ": Average number of letters per word: " << fixed 
            << showpoint << setprecision(2) << Average << "\n" << endl;
    }

    return 0;

}/* main() */

OUTPUT:

i = 0: Running Count_All( "" )
    (length of input = 0)...
i = 0: Letters = 0 (Expected 0)...PASSED...
i = 0: Words = 0 (Expected 0)...PASSED...
i = 0: Total_Printable_Characters = 0 (Expected 0)...PASSED...
i = 0: Punctuation_Marks = 0 (Expected 0)...PASSED...
i = 0: Average number of letters per word: 0.00

i = 1: Running Count_All( " " )
    (length of input = 1)...
i = 1: Letters = 0 (Expected 0)...PASSED...
i = 1: Words = 0 (Expected 0)...PASSED...
i = 1: Total_Printable_Characters = 0 (Expected 0)...PASSED...
i = 1: Punctuation_Marks = 0 (Expected 0)...PASSED...
i = 1: Average number of letters per word: 0.00

i = 2: Running Count_All( "Why, hello there!" )
    (length of input = 17)...
i = 2: Letters = 13 (Expected 13)...PASSED...
i = 2: Words = 3 (Expected 3)...PASSED...
i = 2: Total_Printable_Characters = 15 (Expected 15)...PASSED...
i = 2: Punctuation_Marks = 2 (Expected 2)...PASSED...
i = 2: Average number of letters per word: 4.33

i = 3: Running Count_All( "I am sam." )
    (length of input = 9)...
i = 3: Letters = 6 (Expected 6)...PASSED...
i = 3: Words = 3 (Expected 3)...PASSED...
i = 3: Total_Printable_Characters = 7 (Expected 7)...PASSED...
i = 3: Punctuation_Marks = 1 (Expected 1)...PASSED...
i = 3: Average number of letters per word: 2.00

i = 4: Running Count_All( "I'll take 1 bagel." )
    (length of input = 18)...
i = 4: Letters = 12 (Expected 12)...PASSED...
i = 4: Words = 4 (Expected 4)...PASSED...
i = 4: Total_Printable_Characters = 15 (Expected 15)...PASSED...
i = 4: Punctuation_Marks = 2 (Expected 2)...PASSED...
i = 4: Average number of letters per word: 3.25

i = 5: Running Count_All( "I'll be back, Bennett!" )
    (length of input = 22)...
i = 5: Letters = 16 (Expected 16)...PASSED...
i = 5: Words = 4 (Expected 4)...PASSED...
i = 5: Total_Printable_Characters = 19 (Expected 19)...PASSED...
i = 5: Punctuation_Marks = 3 (Expected 3)...PASSED...
i = 5: Average number of letters per word: 4.00

i = 6: Running Count_All( "Let off some steam, Bennett!" )
    (length of input = 28)...
i = 6: Letters = 22 (Expected 22)...PASSED...
i = 6: Words = 5 (Expected 5)...PASSED...
i = 6: Total_Printable_Characters = 24 (Expected 24)...PASSED...
i = 6: Punctuation_Marks = 2 (Expected 2)...PASSED...
i = 6: Average number of letters per word: 4.40

i = 7: Running Count_All( "Supercalifragilisticexpyalidocious" )
    (length of input = 34)...
i = 7: Letters = 34 (Expected 34)...PASSED...
i = 7: Words = 1 (Expected 1)...PASSED...
i = 7: Total_Printable_Characters = 34 (Expected 34)...PASSED...
i = 7: Punctuation_Marks = 0 (Expected 0)...PASSED...
i = 7: Average number of letters per word: 34.00

i = 8: Running Count_All( "'ere, what'cha doin' 'ere, guv'nor?" )
    (length of input = 35)...
i = 8: Letters = 23 (Expected 23)...PASSED...
i = 8: Words = 5 (Expected 5)...PASSED...
i = 8: Total_Printable_Characters = 31 (Expected 31)...PASSED...
i = 8: Punctuation_Marks = 8 (Expected 8)...PASSED...
i = 8: Average number of letters per word: 4.60

i = 9: Running Count_All( " 'ere, what'cha doin' 'ere, guv'nor?" )
    (length of input = 36)...
i = 9: Letters = 23 (Expected 23)...PASSED...
i = 9: Words = 5 (Expected 5)...PASSED...
i = 9: Total_Printable_Characters = 31 (Expected 31)...PASSED...
i = 9: Punctuation_Marks = 8 (Expected 8)...PASSED...
i = 9: Average number of letters per word: 4.60

i = 10: Running Count_All( "That's one small step for a man, one giant leap for mankind." )
    (length of input = 60)...
i = 10: Letters = 46 (Expected 46)...PASSED...
i = 10: Words = 12 (Expected 12)...PASSED...
i = 10: Total_Printable_Characters = 49 (Expected 49)...PASSED...
i = 10: Punctuation_Marks = 3 (Expected 3)...PASSED...
i = 10: Average number of letters per word: 3.83

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM