C ProgrammingDiscussion
Look at my program?   11-17>|

StumblephonicAug 10, 2007 12:57pm
Hi guys and possibly gals,

I typed up a simple program that determines a paragraph's sentence and word count.
I know, I know, yawn seen it!
But I'm a beginner so cut me some slack.
Anyone care to take a minute to look over my code to see if and how you would change anything?

#include <cstdlib>
#include <iostream>

using namespace std;

int main(int argc, char *argv[]){

int spaceCount = 0, sentenceCount = 0, trueWordCount = 0;
char paragraph[ 10000 ], characters[ ] = { ' ', '.', '?', '!' };

cout << "Enter a paragraph: " << endl;
gets( paragraph );

if( paragraph[ 0 ] != characters[ 0 ] ) spaceCount++;

for( int i = 0; paragraph[ i ]; i++ ){

if( paragraph[ i ] == characters[ 0 ] ) spaceCount++;

if( paragraph[ i ] == characters[ 1 ] || paragraph[ i ] == characters[ 2 ] || paragraph[ i ] == characters[ 3 ] ) sentenceCount++;
}

trueWordCount = spaceCount % strlen( paragraph );

cout << "Sentence count: " << sentenceCount << endl;
cout << "Word count: " << trueWordCount << endl;

system( "PAUSE" );
return EXIT_SUCCESS;
}


Sponsor
KibiyamaAug 11, 2007 2:58am
You're mixing C and C++.

I'd use a string for paragraph, but leave characters as a char[] because it truly is an array of characters...

I'd use cin >> instead of gets()

Best practice would probably be to put the checking of this line...
paragraph[ i ] == characters[ 1 ] || paragraph[ i ] == characters[ 2 ] || paragraph[ i ] == characters[ 3 ]
...in a function like this:

bool checkMatch(char _array[], char _character)
{
    for (int i = 0; i < sizeof(_array); i++)
    {
      if (_array[i] == _character)
        return true;

    }
    return false;

}

That way you only have to add a character to characters[] if you wanted to pick up on more punctuation in the future. Like I said, best practice, but not necessary.

Also, this line is just plain wrong:
trueWordCount = spaceCount % strlen( paragraph );
By definition, spaceCount is <= strlen(paragraph), so you will always get a result of spaceCount, unless spaceCount == strlen(paragraph), in which case you get 0, which is correct.**

A few nitpick things:

I prefer the bracing style:
foo bar
{
    //

}

It's a well-known law that if you see someone coding with K&R bracing, you are legally obligated to stab them in the head and say "NO, stop it."

I also don't like it when people declare multiple variables on one line. Especially because it lends itself poorly to commenting, and because white space is your friend. All it takes is a tap of the enter key, after all.

You're fine in a source file, but I would recommend you don't get in the habit of "using namespace std", because namespaces are there for a reason and if you were to put that in a header, everything that #includes it would be using namespace std as well and you might encounter a naming conflict there. You also might not, but it's not worth the potential confusion just to save typing "std::".

It's been a long time since I wrote a console app, but I recall using cin rather than system("PAUSE") to wait for input before returning. Might be bad practice, though, I don't know.

** Forgot about this... Why are you doing this:
if( paragraph[ 0 ] != characters[ 0 ] ) spaceCount++;
?

That reminds me... I generally put an if on one line, and the code that executes on the next.

if (foo)
{
    bar;

}

I also use the brackets regardless of whether they are necessary. Not worth debugging a stupid mistake just because I wanted to leave out two characters.

I also do compound conditions like this:

if (foo ||
    bar ||
    baz )


Aligning the ORs and the end parenthesis with the longest line, which is hard to do on SU because the only way to indent is to use the <ul> tag. (which also puts in those random funky spaces you see)

StumblephonicAug 11, 2007 8:00am
Wow! Not even for a fleeting moment did any of that stuff occur to me! This is exactly the kind of advice that I wanted. Thanks!
I don't understand that thing about the 'trueWordCount'. I tried to use: trueWordCount = strlen( paragraph ) / (sentenceCount - spaceCount ) but it didn't recognize one-word sentences. I guess my next step is to keep track of all of the letters and use that as a substitute for strlen( paragraph )? I am working on adding support for double spaces now. I will incorporate all of your advice to the program now. Once again thanks for your time! By not using namesapace std do you mean to write cout as std::cout?


Sponsor
KibiyamaAug 11, 2007 9:04am
trueWordCount = strlen( paragraph ) / (sentenceCount - spaceCount )

That makes even less sense. Fact is, there is no way to determine how many words are in a paragraph solely from the number of sentences, spaces, and characters in it.

The best way to do this is to do something like this:

for (int i = 0; i < paragraph.length(); i++)
{
    if (!checkMatch(paragraph.at(i), characters)) //found a word
    {
      while (!checkMatch(paragraph.at(i), characters)) &&
        i < paragraph.length() ) //get to the end of the word, but don't pass the end of the paragraph

      {
        i++;

      }
      wordCount++; //tally up the word

    }

}

You can even get fancy with it and keep track of how many characters you go through in that while loop and only count words that are more than 2 characters or something.

By not using namesapace std do you mean to write cout as std::cout?

Whether you follow my advice on that depends on how far you plan on taking this. If it's for some business programming class, don't even bother. But if you want to end up proficient in C++ and write good code, you should refrain from the "using namespace" statement, because there is no way to undo it and the result is what they call namespace pollution.

Namespace pollution just means that if you are using code that defines zomg::cout, and you do using namespace zomg and using namespace std, you're fucked. It sounds like a rarity, but if you get into advanced areas like games, and especially if you're mixing different libraries (sets of code written by other people) you'll find they define a lot of the same things, like BITMAP, for instance. And if you don't respect namespaces when you're in the trenches like that, you can shoot yourself in the foot real fast, and by the time you realize it you may have to go back and change a loooot of code.

It never hurts to be more precise, when you're programming.

StumblephonicAug 11, 2007 10:28am
Nope, no business classes here. Just trying to learn programming and c++ on my own. I would like to become knowledgeable about c++ one day. I have no grand ideas about any world changing software just yet. I have just always wanted to be able to program a computer. It sounds ultimate.

*EDIT* DO you mean to not put the paragraph string into an array? Work with it solely as a string?
I know you're not a help center but I have just one more question: when I pass a char argument into a function am I gonna need to use pointers?

Or anyone else looking at this thread is welcome to contribute too...


Sponsor
KibiyamaAug 11, 2007 12:18pm
I may not be a help center, but feel free to treat me like one. I'm pretty much used to it, I do this a lot.

DO you mean to not put the paragraph string into an array? Work with it solely as a string?

Correct. In C, "strings" are not actually strings, just arrays of characters. But C++ has the data type std::string. (which is really a templated wrapper around an array of characters... but that's a technicality)

There are a lot of reasons to use std::string over char[].

The reason I find most compelling is that all the standard operators work as expected. Doing string1 + string2 is more natural than strncat(string1, string2)

There's also the concern of buffer overflows. For one thing, these can be exploited to inject code into the program. Other than that, it's just a pain in the ass to constantly have to be aware of the size of the string and make sure not to overstep the boundary.

std::string can be converted into a c-style string with .c_str(), so it's not like you're missing out on anything. It's just easier, safer, and more clearly communicates your intentions to other programmers who read the code.

I have just one more question: when I pass a char argument into a function am I gonna need to use pointers?

Depends what you mean. The function I wrote earlier:

(Actually, I'm going to swap these parameters, because it's more natural to say "check for _character in _array" than it is to say "check _array for _character" -- and by the way, the underscore thing I do is not necessarily "what the pros would do", I just like it because it helps me differentiate function parameters from locals and globals. Style is very subjective and you'll have to figure out what works for you.)

bool checkMatch(char _character, char _array[])
{
    for (int i = 0; i < sizeof(_array); i++)
    {
      if (_array[i] == _character)
        return true;

    }
    return false;

}

You don't need "pointers" there, but arrays are technically pointers.

I have no idea how much you know about pointers, so I don't know exactly where to start there... it's a big topic, and an important one, but it's probably the hardest thing to learn. Do you have a good book you're learning from, or what?

ThePornAmbitionAug 11, 2007 12:54pm
I don't get it either...

StumblephonicAug 11, 2007 12:58pm
I have a book called C++ How to Program 3rd ed Deitel & Deitel. I use tutorials, forums, and experimenting. I don't know much about pointers.

**Edit** I am rewriting my program this time based around functions instead of trying to insert functions into preexisting code. Will report...


Sponsor
KibiyamaAug 17, 2007 5:38pm
How goes the coding?

StumblephonicAug 17, 2007 7:59pm
Experimenting with various string operations such as 'stringName.copy', 'stringName.size', and 'stringName.find'. Tried to learn what 'stringName.at' is all about but no luck.


Look at my program?   11-17>|