Advertisement

Advice on coding style

Started by December 23, 2015 11:45 PM
45 comments, last by Hodgman 8 years, 11 months ago

Since everyone has covered the code, I'm going to give my advice on something else I noticed in the OP. I would warn against learning from SAMS Teach Yourself C++ in 21 Days and any book for that matter that claims to teach you <x language> in <x amount of time>. I would also recommend Code::Blocks ( http://codeblocks.org/ ) or MSVC over Dev-C++.The reason I don't recommend books that have time limits in the title or "for DUMMIES" or "Complete idiots guide" is because they are designed to "simplify things" and in the process may forget minute details that could give the reader that "AHA!" moment for understanding the language. Books like that also have a history of teaching poor or bad practices or never pointing out why some methods they teach should be avoided.

I always recommend this list and my reasoning:

1) Programming: Principles and Practice Using C++ 2nd Edition
Is a book designed to help you learn to program (if you have never programmed before) using C++ as a tool. It is also the intro course book for several degrees at Texas A&M University. Not to mention it is written by Bjarne Stroustrup himself.

2) C++ Primer 5th Edition
The usual recommendation for Beginner C++, but that phrase is a little misleading. It isn't a book for someone who as never programmed, but rather a book for a programmer who is experienced in another language and looking to learn C++ now. It covers C++ more in-depth.

3) The C++ Standard Library: A Tutorial and Reference
Covers the standard library in-depth.

4) The C++ Programming Language (as a reference)
I recommend this purely as a reference book. It too is written by Bjarne Stroustrup. You can certainly read it cover to cover if you like, but it makes a better reference than a book about learning due to its technical nature.

You can't go wrong with Scott Meyers' books either:

Effective C++

More Effective C++

Effective STL

Effective Modern C++

As for coding style, most of the books touch on the coding style, and you can see a good example of a commonly used style by looking at their code samples throughout the books. As mentioned you can also sift through the ISOCPP site ( https://isocpp.org/ ) which is loaded with information.

Can't afford books? There are some tutorials on sites (some with forums to ask advice):

Tutorial: http://www.cplusplus.com/doc/tutorial/ Forum: http://www.cplusplus.com/forum/

http://www.dreamincode.net/forums/forum/48-c-tutorials/

http://www.learncpp.com/

Then, of course, there is this site to ask advice on when you are stumped.

I've been plugging away during the holidays and what not, just read all the replies and would like to chime in (as I have another piece of code that is not making sense to me). I didn't add any safety features to anything as I'm just trying to learn the language from scratch. So there will be multiple areas where someone could crash the programs I'm making ATM. As for the sams teach yourself c++ in 21 days... You can't do it in 21 days as it's over 1000 pages with TONS of examples. That being said, I branched off to the book "Object-Oriented Programming in C++" and some of his examples on pointers made my head spin.

Onto the good:

I've been reading and going through Accelerated C++ after going about half way through those other two books, and let me tell you, this tiny book (mind you with a better knowledge of the language now) is making things one hell of a lot clearer in a small amount of time. As for the books, the effective series is up right after I can wrap my head around this language with a solid understanding. I don't want to jump into game development with a half ass knowledge on C++, then get discouraged and quit once I see code that I don't understand.

That being said, learning has had its ups and downs... but I'm having fun doing it. The only frustrating part is jumping between books and relearning items that I already knew... but solidifying that foundation is good as well.

Anyways, I have a problem that is probably extremely simple to fix. I've setup a loop, asked for a string and storing it in a vector. Here is the loop that fails (After the first student name is entered, it skips it and goes right for the while loop) and the output is all messed up..:


for( int i = 0; i < students; i++){
		cout << "Student name: ";
		cin >> name;
		classroom.push_back(name);
		count++;
	
		cout << "Enter the students grades: ";
		
		while(cin >> x)
			grades.push_back(x); 
		cin.clear();
		}

I can make the program work correctly while using separate while loops for some reason.... and I don't understand why??


do{
		cout << "Student name: ";
		cin >> name;
		classroom.push_back(name);
		count++;
	} while (count < students);
	
	cout << "Enter the students grades: ";
		
	count = 0;
		
	while(cin >> x) {
		grades.push_back(x); 
		count++;
		if(count == students)
			break;
	}

Like I said I'm sure I'm missing something but I'm not sure what. I've tried clearing the string "name" and the input during the for loop with no success. It just won't let me type in another Student Name.

Let me know if you need the full source code (I have a hard time continuing in lessons if an exercise doesn't work and I can't figure it out.... seems counter productive to continue which is why you guys are awesome!)

Advertisement

I'm not sure what you're asking. At first I thought you were running into the stream in issue with spaces, but from what you said it sounds like you're expecting it get several names and then get the grades after that?

But the code you posted tells it to get one name and then enter a grade input loop, then when the grade loop ends it should ask for the next name.

Could you explain what exact behavior you want to happen, and give an example of the input you're providing it?

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

Sorry I should have explained more... forgot I took out a lot of my comments while tinkering.

For every time the user enters a name, it grabs the grades until a not int is entered. (end-of-file for example). I originally had put 00 to indicate you were done before typing end-of-file.

Problem being, with the for loop, it takes the first name, takes the grade loop after words. But when it runs into the "Enter student name: " again, it goes right to the grades loop. I'll post both of the full programs to get a better understanding of what I'm saying (after running it, you will see). Again, it is NOT user error proof, just trying to grasp some basics :)

Working example:


// keep track of students names and grades, then display them beside eachother
#include <iostream>
#include <vector>
#include <string>
using namespace std;

int main()
{
	cout << "This will take a students name, and assign x number of grades to the student.";
	
	vector<string> classroom;
	vector<double> grades;
	string name;
	
	
	cout << "\nEnter number of students: ";
	int students;
	cin >> students;
	double x;
	int count = 0;
	
	do{
		cout << "Student name: ";
		cin >> name;
		classroom.push_back(name);
		count++;
	} while (count < students);
	
	cout << "Enter the students grades: ";
		
	count = 0;
		
	while(cin >> x) {
		grades.push_back(x); 
		count++;
		if(count == students)
			break;
	}
	
	cout << "Students names in order entered: ";
	
	for(int i = 0; i < students; i++){
		cout << classroom[i] << endl;
	}
	
	cout << "Grades entered from left to right: ";
	
	for(int i = 0; i < students; i++){
		cout << grades[i] << " ";
	}
	
	return 0;
}

non working example:


// keep track of students names and grades, then display them beside eachother
#include <iostream>
#include <vector>
#include <string>
using namespace std;

int main()
{
	cout << "This will take a students name, and assign x number of grades to the student.";
	
	vector<string> classroom;
	vector<double> grades;
	string name;
	
	
	cout << "\nEnter number of students: ";
	int students;
	cin >> students;
	double x;
	int count = 0;
	
	for( int i = 0; i < students; i++){
		cout << "Student name: ";
		cin >> name;
		classroom.push_back(name);
		count++;
	
		cout << "Enter the students grades: ";
		
		while(cin >> x)
			grades.push_back(x); 
		cin.clear();
		}
	
	cout << "Students names in order entered: ";
	
	for(int i = 0; i < students; i++){
		cout << classroom[i] << endl;
	}
	
	cout << "Grades entered from left to right: ";
	
	for(int i = 0; i < students; i++){
		cout << grades[i] << " ";
	}
	
	return 0;
}

The code isn't clean as I was messing around trying to get it to work.... which obviously failed. Khatharr you're awesome btw. I really do appreciate you taking the time to help out!

Ah. The stream is in an error state or has some retained data.

To get a string from cin use std::getline().

To get a number use this (you should study it to learn how and why everything is there):

https://github.com/khatharr/getUserValue/blob/master/getUserValue.cpp

Usage example:


int numberOfApples = getUserValue<int>("How many apples are there? ", 0, 100);
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

haven't learned about template yet, or how the usage example would imply to what i'm doing (or frankly what it does). It is possible the answer is not into something I have learned yet. As the example only asks to store two different vectors... I was trying to somewhat associate them with a user.

As for the stream is in error, that's what I thought. I tried to .clear() on input, output and the string itself with no success!

Advertisement

You can de-templatize the function if you'd prefer. Just remove the <template> line and replace all of the 'T's with 'int's or 'float's. I'll remove the min/max check as well:


#include <iostream>
#include <string>

int getUserValue(const std::string& requestString) {

  int retval;
  while(true) {
    std::cout << requestString;
    std::cin >> retval;

    // Reset the input stream, since it can get cranky if there's invalid input.
    // Note that 'ok' is fetched first because cin.good() will be reset as well.
    bool ok = std::cin.good();
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    if(ok) { return retval; }

    std::cout << "Invalid input." << std::endl;
  }
}

Usage:


int appleCt = getUserValue("How many apples are there? ");

In your own code you do indeed call cin.clear(), but you do not purge the erroneous data (probably just a \n) that remains in the stream.

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.
Bad:
	while(cin >> x) {
		grades.push_back(x); 
		count++;
		if(count == students)
			break;
	}
Good:
	while(cin >> x) {
		grades.push_back(x); 
		count++;
		if(count == students) {
			break;
		}
	}
Never omit braces “just because you can”. So what if the language allows it? The language allows you to shoot yourself in the foot in tons of ways—that in no-way means you are encouraged to actually do it.
Omitting braces is not only a tacky sign of laziness, it causes bugs later down the road when you want to modify the code. What if you wanted to print something in that case (perhaps for debug)?

	while(cin >> x) {
		grades.push_back(x); 
		count++;
		if(count == students)
			cout << "Count == Students." << endl;
			break;
	}
Now you’ve wasted your life figuring out why the while loop always exits after only 1 iteration and why your message never gets printed.

There is just no excuse for it. It’s tacky, inconsistent (compared to every other place where you must use braces), and not only provides no benefit, it can harm you too.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Omitting braces is not only a tacky sign of laziness, it causes bugs later down the road when you want to modify the code. What if you wanted to print something in that case (perhaps for debug)?
Now you’ve wasted your life figuring out why the while loop always exits after only 1 iteration and why your message never gets printed.

I see that as a common reason given as to why you should always use braces, even for 1-liners, but TBH I've never seen that hypothetical bug happen. The missing braces in your buggy example are so painfully obvious even at a glance that the person adding the cout would have to be blind in order to forget to add the braces...

Personally, I'd change the while to a for and still leave off the braces laugh.png
	for( count = 0; count != students && cin >> x; ++count )
		grades.push_back(x); 

Omitting braces is not only a tacky sign of laziness, it causes bugs later down the road when you want to modify the code. What if you wanted to print something in that case (perhaps for debug)?
Now you’ve wasted your life figuring out why the while loop always exits after only 1 iteration and why your message never gets printed.

I see that as a common reason given as to why you should always use braces, even for 1-liners, but TBH I've never seen that hypothetical bug happen. The missing braces in your buggy example are so painfully obvious even at a glance that the person adding the cout would have to be blind in order to forget to add the braces...

ray_charles_183795.jpg
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

This topic is closed to new replies.

Advertisement