Problem with ASCII Rotating Cursor (TUI) Animation - c++

I'm trying to create the rotating cursor animation thing.
Each time I compile this I always get a slash (or two) left at the end, and the backspace character does not work. I used two ways to do this: the sleep function and the chrono timer and they worked very similarly and left a slash after spinning, ignoring the backspace character.
This works differently and as expected if I leave out any newline character or manipulator.
void spinningCursor() {
for (int i = 1; i <= 100; ++i)
{
cout << "-" << flush;
this_thread::sleep_for(chrono::milliseconds(10));
cout << "\b" << flush;
cout << "\\" << flush;
this_thread::sleep_for(chrono::milliseconds(10));
cout << "\b" << flush;
cout << "|" << flush;
this_thread::sleep_for(chrono::milliseconds(10));
cout << "\b" << flush;
cout << "/" << flush;
this_thread::sleep_for(chrono::milliseconds(10));
cout << "\b" << flush;
}
}
Or...
void spinningCursor2() {
for (int i = 0; i < 100; i++) {
cout << "-";
cout.flush();
usleep(10000);
cout << "\b";
cout.flush();
cout << "\\";
cout.flush();
usleep(10000);
cout << "\b";
cout.flush();
cout << "|";
cout.flush();
usleep(10000);
cout << "\b";
cout.flush();
cout << "/";
cout.flush();
usleep(10000);
cout << "\b";
cout.flush();
}
}
main function...
int main()
{
spinningCursor();
cout <<"\nHello, World!"<< endl;
spinningCursor2();
cout <<"\nHello, World, Again!"<< endl;
return 0;
}

The output effect is not guaranteed but dividing it into sections might help.
Idea:
#include <algorithm>
#include <chrono>
#include <cstddef>
#include <iostream>
#include <string>
#include <thread>
using namespace std::chrono_literals; // a cumbersome way to be able to write 100ms
// unformatted output of one char, a backspace, flushing and Zzz...
void slow_put(char ch) {
static const auto delay = 100ms;
static const char bs = '\b';
std::cout.write(&ch, 1);
std::cout.write(&bs, 1);
std::cout.flush();
std::this_thread::sleep_for(delay);
}
// newline, but erase the char under it first
void nl() {
std::cout.write(" \n", 2);
}
// proxy ... decorate stuff here (for debugging etc)
void display(char ch) {
slow_put(ch);
}
// enabler to repeat a bunch of sequences
void spinner(const std::string& sequence) {
// execute the display function for one char at a time
std::for_each(sequence.begin(), sequence.end(), display);
}
// example use of the helpers above
void spinningCursorSchema(size_t times) {
static const std::string seq = R"raw(|/-\)raw"; // the pattern to display
while(times--) spinner(seq);
// add more patterns to this schema if wanted
}
int main() {
std::cout << "Spinner: [ ]\b\b";
spinningCursorSchema(100); // run the spinningCursor 100 times
nl(); // erasing newline
}
Edit: A brief explanation:
For every group of functions you called that I felt could be named, "do_this()" or "do_that()" I put them in a function and named them accordingly.
The purpose of this exercice was not primarily for me to find the error in your code but to provide a frame of reference. It's easier to identify/talk about/fix problems when one can say "your do_this() function needs this or that..." or similar. When everything is in one big code block everyone reading it needs to start from zero. A function with a clear name (or a comment to compensate for the poor naming as I did above, "proxy") and only a few lines of code can be reviewed by everyone without much background knowledge about the bigger problem.
In short, I took your code that was specifically created to do one thing and broke it down into a few functions that I used to rebuild something similar to your original idea. By doing that I made it easier to see flaws, talk about design decisions. If a function of 2-4 lines can be reviewed by 10000 people and they don't see a problem, it's very unlikely that that function is the problem (in itself). By building blocks of small functions with a clear purpose, bughunting becomes a lot more available for everyone, not only people deeply involved in the particular problem you're solving.
I now see that I used a function template from <algorithm> that may be unfamiliar: std::for_each. In this case, it could be replaced by:
for(char ch : sequence) display(ch);
Come to think of it, that's even clearer.
If this wasn't the overview you sought, just comment and point out the parts you want to get explained and I'll try again

The backspace character doesn't actually delete the previous character, all it does is move the cursor itself back one "space". It's the combination of backspace followed by writing another character that does the overwrite or "delete" the character.
Also, the backspace only goes as far as the beginning of the current line. Once you have printed a newline you can't go back "up" a line with a backspace.
On Windows you might be able to get better results by using the Windows console functions, and on POSIX systems (like Linux or macOS) maybe VT100 escape codes.

Related

Why are my char functions not doing their job?

So I am still new to C++, and I'm trying to make a program that has the user input a string, and then my functions return the string in reverse case, all lower case, and then all uppercase. Instead I just keep receiving the first letter of the string back, always uppercase. Not sure what I am doing wrong. Any suggestions?
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
char answer[255] = "";
int max = strlen(answer);
void reverse() {
for (int i = 0; i < max; i++) {
if (islower(answer[i])) {
isupper(answer[i]);
}
else if (isupper(answer[i])) {
islower(answer[i]);
}
else if (isspace(answer[i])) {
isspace(answer[i]);
}
}
cout << answer[max];
}
void lower() {
for (int i = 0; i < max; i++) {
if (isupper(answer[i])) {
islower(answer[i]);
}
else {
answer[i] = answer[i];
}
}
cout << answer[max];
}
void upper() {
for (int i = 0; i < max; i++) {
if (islower(answer[i])) {
isupper(answer[i]);
}
else {
answer[i] = answer[i];
}
}
cout << answer[max];
}
int main() {
cout << "Please enter a word, or a series of words: " << endl;
cin >> answer[max];
reverse();
lower();
upper();
system("pause");
return 0;
}
islower(char) is just a built in function to check if the char is in lowercase or not. Same goes with isupper. It does not change the case of the character.
In order to convert to lowercase/uppercase, use tolower/toupper. This would return the character in the converted case. But, it is important that you need to assign the returned value to the character itself.
Refer to this answer for some more clarity related to islower, isupper, tolower and toupper.
And now coming to the point why it's printing just the 1st character: As #user4581301 has mentioned in his comment,
"cin >> answer[max]; will read exactly one character because answer[max] is exactly one character, the first character. In C++ you have to do things in order. For example, int max = strlen(answer); will provide an answer based on what is in that string at that time. Since the string was initialized one line earlier and contains an empty string, max will be 0."
Hence your cin should be cin >> answer. BUT, this will accept the 1st word of your sentence. In order to accept all the words including the spaces, use getline() instead. And for using this, answer should be declared as string answer instead of a char array.
This is how you accept a full sentence: getline(cin,answer);
And your variable max will give an error in a few compilers as being ambiguous. This is because of the using namespace std;. to avoid this, rename max to something else, like maxlen.
And finding the length of answer: It would be better if you call answer.length() after accepting the string from user rather than doing it globally.
Your working code should look something like this:
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
string answer;
int maxlen;
void reverse() {
for (int i = 0; i < maxlen; i++) {
if (islower(answer[i])) {
answer[i] = toupper(answer[i]);
}
else if (isupper(answer[i])) {
answer[i] = tolower(answer[i]);
}
else if (isspace(answer[i])) {
answer[i]=' ';
}
}
cout << "Reversed string: " + answer << endl;
}
void lower() {
for (int i = 0; i < maxlen; i++) {
if (isupper(answer[i])) {
answer[i] = tolower(answer[i]);
}
else {
answer[i] = answer[i];
}
}
cout << "Lower case string: " + answer << endl;
}
void upper() {
for (int i = 0; i < maxlen; i++) {
if (islower(answer[i])) {
answer[i] = toupper(answer[i]);
}
else {
answer[i] = answer[i];
}
}
cout << "Upper case string: " + answer << endl;
}
int main() {
cout << "Please enter a word, or a series of words: " << endl;
getline(cin,answer);
cout << "Original string: " + answer << endl;
maxlen = answer.length();
reverse();
lower();
upper();
return 0;
}
With the output:
Please enter a word, or a series of words:
ReVeRsAl UPPER aNd lower
Original string: ReVeRsAl UPPER aNd lower
Reversed string: rEvErSaL upper AnD LOWER
Lower case string: reversal upper and lower
Upper case string: REVERSAL UPPER AND LOWER
cin >> answer[max];
will read exactly one character because answer[max] is exactly one character, the character in the array at position max.
max is 0 because you have to do things in order. For example,
int max = strlen(answer);
will provide the length of answer at that time this line is reached. Since the string was initialized one line earlier
char answer[255] = "";
and contains an empty string, max will be 0. This means answer[max] is answer[0] Nothing in the code ever changes max, so it will remain 0.
OK, say we change things a little and rather than reading into a single character, we read into answer as a string. You will need to
cin.getline(answer, sizeof(answer));
because
cin >> answer;
will read one whitespace-delimited token. One word. Your stated goal is to read more than one word. istream::getline will read everything it finds into the first parameter up to the end of the line or it finds the number of characters specified in the second parameter minus 1 (in order to reserve space for the string's null terminator). sizeof(answer) is literally the size of the answer array in bytes. We're operating in byte-sized characters so the count of characters and number of bytes are the same. Extra care must be taken if multibyte characters are being used.
This seems like a good place to recommend using std::string and std::getline instead. They make a large number of problems, such as the maximum number of characters that can be read, vanish for the vast majority of cases.
I'm not going to use them here, though because the assignment likely has a "No strings" policy.
So now that we have cin.getline(answer, sizeof(answer)); reading the user's input we can work on getting the size for max. We could strlen, but we could also use istream::gcount to get the number of characters read by getline.
main now looks something like
int main() {
cout << "Please enter a word, or a series of words: " << endl;
cin.getline(answer, sizeof(answer));
max = cin.gcount();
reverse();
lower();
upper();
system("pause");
return 0;
}
Whole bunch of stuff can go wrong at this point.
using namespace std; can wreak havoc on the max because of possible collisions with std::max. In general, avoid using namespace std; The few letters it saves you from typing often are recovered by the time wasted debugging the weird errors it can introduce.
isupper(answer[i]); doesn't do anything useful as others have noted in the comments. You want
answer[i] = toupper(static_cast<unsigned char>(answer[i]));
See Do I need to cast to unsigned char before calling toupper(), tolower(), et al.? for why that insane-and-pointless-looking cast may be necessary. Thank you HolyBlackCat for bringing that to my attention.
Self assignments like
answer[i] = answer[i];
are pointless for reasons that should be obvious once you stop and think about it.
Likewise
else if (isspace(answer[i])) {
isspace(answer[i]);
}
May not be particularly useful. If answer[i] is a space, set it to a space? It's already a space. What it would do is replace other forms of whitespace, tabs and carriage returns, with a space. Newline has already been picked off by getline. Also probably needs a cast similar to the one used in the toupper example above. I'm still reading up on that.
As hinted at above,
cout << answer[max];
is not effective. It prints out one character, and if max has been fixed, answer[max] will be the terminating null. Instead print out the whole array.
cout << answer;
General suggestions:
Don't write much code at a time. Write a few lines, a function at the most, before compiling and testing. If you had tested
int main() {
cout << "Please enter a word, or a series of words: " << endl;
cin >> answer[max];
cout << answer;
}
You would have immediately seen data was not being read correctly. and fixed it before proceeding. By allowing errors to build up, you make it harder to find any one bug. You may correctly fix a bug only to find the fix undone or concealed by another bug.
Avoid using global variables. Try to place variables in the smallest possible scope. In this case, move answer and max into main and pass them to the other functions as parameters. This makes it a lot easier to keep track of who set what variable and when. It also helps prevent accidental Variable Shadowing.

Why do I obtain this strange character?

Why does my C++ program create the strange character shown below in the pictures? The picture on the left with the black background is from the terminal. The picture on the right with the white background is from the output file. Before, it was a "\v" now it changes to some sort of astrological symbol or symbol to denote males. 0_o This makes no sense to me. What am I missing? How can I have my program output just a backslash v?
Please see my code below:
// SplitActivitiesFoo.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
int main()
{
string s = "foo:bar-this-is-more_text#\venus \"some more text here to read.\"";
vector<string> first_part;
fstream outfile;
outfile.open("out.foobar");
for (int i = 0; i < s.size(); ++i){
cout << "s[" << i << "]: " << s[i] << endl;
outfile << s[i] << endl;
}
return 0;
}
Also, assume that I do not want to modify my string 's' in this case. I want to be able to parse each character of the string and work around the strange character somehow.This is because in the actual program the string will be read in from a file and parsed then sent to another function. I guess I could figure out a way to programmatically add backslashes...
How can I have my program output just a backslash v?
If you want a backslash, then you need to escape it: "#\\venus".
This is required because a backslash denotes that the next character should be interpreted as something special (note that you were already using this when you wanted double-quotes). So the compiler has no way of knowing you actually wanted a backslash unless you tell it.
A literal backslash character therefore has the syntax \\. This is the case in both string literals ("\\") and character literals ('\\').
Why does my C++ program create the strange character shown below in the picture?
Your string contains the \v control character (vertical tab), and the way it's displayed is dependent on your terminal and font. It looks like your terminal is using symbols from the traditional MSDOS code page.
I found an image for you here, which shows exactly that symbol for the vertical tab (vt) entry at value 11 (0x0b):
Also, assume that I do not want to modify my string 's' in this case. I want to be able to parse each character of the string and work around the strange character somehow.
Well, I just saw you add the above part to your question. Now you're in difficult territory. Because your string literal does not actually contain the character v or any backslashes. It only appears that way in code. As already said, the compiler has interpreted those characters and substituted them for you.
If you insist on printing v instead of a vertical tab for some crazy reason that is hopefully not related to an XY Problem, then you can construct a lookup-table for every character and then replace undesirables with something else:
char lookup[256];
std::iota( lookup, lookup + 256, 0 ); // Using iota from <numeric>
lookup['\v'] = 'v';
for (int i = 0; i < s.size(); ++i)
{
cout << "s[" << i << "]: " << lookup[s[i]] << endl;
outfile << lookup[s[i]] << endl;
}
Now, this won't print the backslashes. To undo the string further check out std::iscntrl. It's locale-dependent, but you could utilise it. Or just something naive like:
const char *lookup[256] = { 0 };
s['\f'] = "\\f";
s['\n'] = "\\n";
s['\r'] = "\\r";
s['\t'] = "\\t";
s['\v'] = "\\v";
s['\"'] = "\\\"";
// Maybe add other controls such as 0x0E => "\\x0e" ...
for (int i = 0; i < s.size(); ++i)
{
const char * x = lookup[s[i]];
if( x ) {
cout << "s[" << i << "]: " << x << endl;
outfile << x << endl;
} else {
cout << "s[" << i << "]: " << s[i] << endl;
outfile << s[i] << endl;
}
}
Be aware there is no way to correctly reconstruct the escaped string as it originally appeared in code, because there are multiple ways to escape characters. Including ordinary characters.
Most likely the terminal that you are using cannot decipher the vertical space code "\v", thus printing something else. On my terminal it prints:
foo:bar-this-is-more_text#
enus "some more text here to read."
To print the "\v" change or code to:
String s = "foo:bar-this-is-more_text#\\venus \"some more text here to read.\"";
What am I missing? How can I have my program output just a backslash v?
You are escaping the letter v. To print backslash and v, escape the backslash.
That is, print double backslash and a v.
\\v

clearing out extra input from terminal

Here is an example code demonstrating the problem I'm facing.
#include <iostream>
#include <string>
extern "C" {
#include <unistd.h>
}
int main()
{
std::cout << "Making tests ready!" << std::endl;
std::cout << "\nTo start out, Enter an integer: ";
int a = 0;
std::cin >> a;
std::string input;
sleep(3); // what to do if user enters data during this?
std::cout << "\n Now enter a string";
std::getline(std::cin, input);
std::cout << "\nHere are your values - " << a << " & " << input;
return 0;
}
See the sleep call in between the code? This could be replaced with somewhat long delays while computing something when my program isn't accepting any inputs. Now if user presses some keys during this time, that input is captured by std::getline() in next line of code. I know this is the default behavior since it should capture the input being provided.
But what I want is to clear all that captured input and start fresh with 15th line that is std::cout << "\n Now enter a string";, which is immediately after sleep. I don't know exact term to describe this or else I would have used that. Thanking you.
Edit: I've tried using std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); in my code, but it asks for input and then discards it.
Please mind my english, not a native speaker.
Reading the comments causes me to think that you can't really solve this problem (at least by the means suggested there). There's an inherent race condition in any case. Consider the following lines:
sleep(3);
// (*) <- Potential location 1.
std::cout << "\n Now enter a string";
// (**) <- Potential location 2.
std::getline(std::cin, input);
The various comments show some (very technically-competent) ways to flush the standard input. The problem is, you cannot put them in the location marked (*) nor (**).
First location - you clear the standard input some way. Now you decide it's time to move to the next line (std::cout << ...). While you do that, the user types in some more input. Race!
Second location - You print out the message (std::cout << ...), and proceed to clear the standard input. Before you manage to do that, the user typed in something. Race!
It seems to me that any of the techniques described in the comment require locking the standard input, and I don't think there's a (standard) way to do so.

How to check if a string contains spaces/tabs/new lines (anything that's blank)?

I know there's an "isspace" function that checks for spaces, but that would require me to iterate through every character in the string, which can be bad on performance since this would be called a lot. Is there a fast way to check if a std::string contains only spaces?
ex:
function(" ") // returns true
function(" 4 ") // returns false
One solution I've thought of is to use regex, then i'll know that it only contains whitespace if it's false... but i'm not sure if this would be more efficient than the isspace function.
regex: [\w\W] //checks for any word character(a,b,c..) and non-word character([,],..)
thanks in advance!
With a regular string, the best you can do will be of the form:
return string::find_first_not_of("\t\n ") == string::npos;
This will be O(n) in the worst case, but without knowing else about the string, this will be the best you can do.
Any method would, of necessity, need to look at each character of the string. A loop that calls isspace() on each character is pretty efficient. If isspace() is inlined by the compiler, then this would be darn near optimal.
The loop should, of course, abort as soon as a non-space character is seen.
You are making the assumption regex doesnt iterate over the string. Regex is probably much heavier than a linear search since it might build a FSM and traverse based on that.
The only way you could speed it up further and make it a near-constant time operation is to amortize the cost by iterating on every update to the string and caching a bool/bit that tracks if there is a space-like character, returning that value if no changes have been made since, and updating that bit whenever you do a write operation to that string. However, this sacrifices/slows that speed of modifying operations in order to increase the speed of your custom has_space().
For what it's worth, a locale has a function (scan_is) to do things like this:
#include <locale>
#include <iostream>
#include <iomanip>
int main() {
std::string inputs[] = {
"all lower",
"including a space"
};
std::locale loc(std::locale::classic());
std::ctype_base::mask m = std::ctype_base::space;
for (int i=0; i<2; i++) {
char const *pos;
char const *b = &*inputs[i].begin();
char const *e = &*inputs[i].end();
std::cout << "Input: " << std::setw(20) << inputs[i] << ":\t";
if ((pos=std::use_facet<std::ctype<char> >(loc).scan_is(m, b, e)) == e)
std::cout << "No space character\n";
else
std::cout << "First space character at position " << pos - b << "\n";
}
return 0;
}
It's probably open to (a lot of) question whether this gives much (if any) real advantage over using isspace in a loop (or using std::find_if).
You can also use find_first_not_of if you all the characters to be in a given list.
Then you can avoid loops.
Here is an example
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string str1=" ";
string str2=" u ";
bool ContainsNotBlank1=(str1.find_first_not_of("\t\n ")==string::npos);
bool ContainsNotBlank2=(str2.find_first_not_of("\t\n ")==string::npos);
bool ContainsNotBlank3=(str2.find_first_not_of("\t\n u")==string::npos);
cout << ContainsNotBlank1 <<endl;
cout << ContainsNotBlank2 <<endl;
cout << ContainsNotBlank3 <<endl;
return 0;
}
Output:
1: because only blanks and a tab
0: because u is not into the list "\t\n "
1: because str2 contains blanks, tabs and a u.
Hope it helps
Tell me if you have any questions

count specific things within a code in c++

can anyone help me make this more generalised and more pro?
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
// open text file for input:
string file_name;
cout << "please enter file name: ";
cin >> file_name;
// associate the input file stream with a text file
ifstream infile(file_name.c_str());
// error checking for a valid filename
if ( !infile )
{
cerr << "Unable to open file "
<< file_name << " -- quitting!\n";
return( -1 );
}
else cout << "\n";
// some data structures to perform the function
vector<string> lines_of_text;
string textline;
// read in text file, line by
while (getline( infile, textline, '\n' ))
{
// add the new element to the vector
lines_of_text.push_back( textline );
// print the 'back' vector element - see the STL documentation
cout << lines_of_text.back() << "\n";
}
cout<<"OUTPUT BEGINS HERE: "<<endl<<endl;
cout<<"the total capacity of vector: lines_of_text is: "<<lines_of_text.capacity()<<endl;
int PLOC = (lines_of_text.size()+1);
int numbComments =0;
int numbClasses =0;
cout<<"\nThe total number of physical lines of code is: "<<PLOC<<endl;
for (int i=0; i<(PLOC-1); i++)
//reads through each part of the vector string line-by-line and triggers if the
//it registers the "//" which will output a number lower than 100 (since no line is 100 char long and if the function does not
//register that character within the string, it outputs a public status constant that is found in the class string and has a huge value
//alot more than 100.
{
string temp(lines_of_text [i]);
if (temp.find("//")<100)
numbComments +=1;
}
cout<<"The total number of comment lines is: "<<numbComments<<endl;
for (int j=0; j<(PLOC-1); j++)
{
string temp(lines_of_text [j]);
if (temp.find("};")<100)
numbClasses +=1;
}
cout<<"The total number of classes is: "<<numbClasses<<endl;
Format the code properly, use consistent style and nomenclature and throw out the utterly redundant comments and empty lines. The resulting code should be fine. Or “pro”.
Here, I’ve taken the efford (along with some stylistic things that are purely subjective):
Notice that the output is actually wrong (just run it on the program code itself to see that …).
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string file_name;
cout << "please enter file name: ";
cin >> file_name;
ifstream infile(file_name.c_str());
if (not infile) {
cerr << "Unable to open file " << file_name << " -- quitting!" << endl;
return -1;
}
else cout << endl;
vector<string> lines_of_text;
string textline;
while (getline(infile, textline)) {
lines_of_text.push_back(textline);
cout << lines_of_text.back() << endl;
}
cout << "OUTPUT BEGINS HERE: " << endl << endl;
cout << "the total capacity of vector: lines_of_text is: "
<< lines_of_text.capacity() << endl << endl;
int ploc = lines_of_text.size() + 1;
cout << "The total number of physical lines of code is: " << ploc << endl;
// Look for comments `//` and count them.
int num_comments = 0;
for (vector<string>::iterator i = lines_of_text.begin();
i != lines_of_text.end();
++i) {
if (i->find("//") != string::npos)
++num_comments;
}
cout << "The total number of comment lines is: " << num_comments << endl;
// Same for number of classes ...
}
I'm not really sure what you're asking, but I can point out some things that can be improved in this code. I'll focus on the actual statements and leave stylistic comments to others.
cin >> file_name;
To handle file names with spaces, better write
getline(cin, file_name);
int PLOC = (lines_of_text.size()+1);
Why do you claim that there's one more line than there actually is?
if (temp.find("//")<100)
with some complicated comment explaining this. Better write
if (temp.find("//")<temp.npos)
to work correctly on all line lengths.
cout<<"The total number of comment lines is: "<<numbComments<<endl;
Actually, you counted the number of end-of-line comments. I wouldn't call a comment at the end of a statement a "comment line".
You don't count /* */ style comments.
Counting the number of classes as };? Really? How about structs, enums, and plain superfluous semicolons? Simply count the number of occurences of the class keyword. It should have no alphanumeric character or underscore on either side.
Use proper indentation, your code is very difficult to read in its current form. Here is a list of styles.
Prefer ++variable instead of variable += 1 when possible; the ++ operator exists for a reason.
Be consistent in your coding style. If you're going to leave spaces between things like cout and <<, function arguments and the function parantheses do it, otherwise don't, but be consistent. Pick one naming convention for your variables and stick to it. There is a lot about styles you can find on google, for example here and here.
Don't use the entire std namespace, only what you need. User either using std::cout; or prefix all of your cout statements with std::
Avoid needless comments. Everyone knows what ifstream infile(file_name.c_str()); does for example, what I don't know is what your program does as a whole, because I don't really care to understand what it does due to the indentation. It's a short program, so rather than explaning every statement on its own, why not explain what the program's purpose is, and how to use it?
These are all stylistic points. Your program doesn't work in its current form, assuming your goal is to count comments and classes. Doing that is a lot more difficult than you are considering. What if I have a "};" as part of a string for example? What if I have comments in strings?
Don't import the whole std namespace, only things you need from it:
using std::string;
Use a consistent naming convention: decide whether you prefer name_for_a_variable or nameforavariable or nameForAVariable. And use meaningful names: numbComments makes me associate to very different things than would numberOfComments, numComments or commentCount.
If your original code looks like this, I strongly recommend to select a single consistent indentation style: either
if ( ... )
{
...
}
or
if ( ... )
{
...
}
bot not both in the same source file.
Also remove the useless comments like
// add the new element to the vector
This is "only" about the readability of your code, not even touching its functionality... (which, as others have already pointed out, is incorrect). Note that any piece of code is likely to be read many more times than edited. I am fairly sure that you will have trouble reading (and understanding) your own code in this shape, if you need to read it even a couple of months after.
"More professional" would be not doing it at all. Use an existing SLOC counter, so you don't reinvent the wheel.
This discussion lists a few:
http://discuss.techinterview.org/default.asp?joel.3.207012.14
Another tip: Don't use "temp.find("};}) < 100)", use "temp.find("};") != temp.npos;"
Edit: s/end()/npos. Ugh.