繁体   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