My fundamentals are still shaky and i need advice on better/simpler ways to print out the results.
with reference to code below
twoSum returns v, which is a vector that contains the indexes of vector nums (that contain elements adding to equal target)
so if twoSum returns v,
looking at how I use a for-loop to print the results, does it look cumbersome?
I feel that this line i wrote can be simplified further, but i can't think of how yet
std::vector<int> result = test.twoSum(num,target);
and the compiler hinted that i can use a range-for-loop, which i would read up later.
after 5 weeks of studying C++ daily, i still struggle with the fundamentals.
like to find out how to print the result vector, i have to google.
and while i find pages like https://www.geeksforgeeks.org/different-ways-to-print-elements-of-vector/
that gave detailed methods with different ways of doing so, it sorts of overwhelms me with realizing there's so much more i have to learn
std::vector<int> result = test.twoSum(num,target);
Its fine just like it is. If by simple, you mean shorter, you can do this:
auto result{test.twoSum(num,target)};
breaking that down, auto tells the compiler to figure out the type from the initializer.
it will match the result of the function call, which returns a vector of int. However it is harder to read and follow: the reader now has to look up what the function type returned to figure out what result's type is. Over using auto is horrible, but here and there it can save typing long types out. Use it with common sense, ask yourself if you were reading this if the auto is confusing.
{} initialization is slightly safer than = because it has stricter type checking. It is the favored way to initialize a variable in modern c++.
range for loops are pretty simple.
for(const int &i : result) cout << i << " ";
which says that for each thing in result, alias it to 'i'. If you leave off the &, it copies the thing from result into i, only do that if you need to modify i without modifying the original, just like pass by reference vs value in a function. The const prevents you from modifying result accidentally, leave it off if your loop is intended to modify the vector. That is pretty much all the scenarios with that loop type. These loops can't count in the loop body and they can't look at other locations (eg result[i+2] ) so they are not always the best choice. They also can't do the work in the loop.
speaking of doing the work in the loop: some people do that for one liners.
for(int i{0}, i<result.size(); cout<<result[i++]<<" ");
I am on the fence as to whether this is poor style or not. It saves space for trivial stuff, but its a little off putting.
you can do 3 or 4 more advanced things here.
you can add a print function to your so you just say test.print(). I do not like this at all:
- it locks the user into YOUR output format. what if they had wanted end of line instead of spaces after each item?
- it locks your user into a console program. What if the user wanted to use this fine class in a GUI program that does not support cout?
so that is often a 'bad' choice unless your class is super limited intentionally, which in itself is usually a bad choice. Still, you CAN do it, its your code.
you can overload the << operator so your class just works with cout.
then you can say cout << test;
this has the same drawbacks as above for YOUR choices on the format style. However it can at least be used in a GUI via streams rather than cout, and feed that forward to the text elements.
then it starts to get exciting. you can provide a virtual version of the overload so the user can define the format, and it can have a default with YOUR format style if they don't care to do that.
Another handy approach, you can provide a cast operator that dumps your class as a string (here, the result print as a single string) that you can use in cout or a GUI or do string processing on or whatever else. This is the most flexible option in my opinion, but it also has a drawback that you sometimes have to explicitly cast the class to a string (the compiler has moments when it simply can't figure out the implicit casting).
There are other ideas as well, but you see where this is going. It comes down to 2 main points:
- with a bit of work in the class development, you can make handling the output easy for the user. But there is no free lunch here, you have to do the work SOMEWHERE. For a program this small and at your level, a loop in main is JUST FINE.
- there is no sane way to just cout a vector or any other container. The reason is exactly like the reason above about putting stuff in your class to do output: that would be handy but it locks you into a generic format that may not be what was wanted by most users. Best to let each user decide how they want to print it out.
I see a lot here that I like. {} on one line loop/conditions is good practice.
use of std:: is good practice.
You are farther along than you think. C++ is arguably the hardest language going, but it is one of the most powerful as well (far, far less false limitations to prevent programmer from doing stuff).
the only thing I am really not 100% sure about is the for / find pairing around line 11. Find iterates so that loop may be doing too much work: you have to take care with some of the handy algorithms like find as they often hide a slow loop. The code is fine, its actually great that you used find and have learned this much in only 5 weeks. Just a warning that you can hide a lot of CPU work behind a word or two with the high level tools.
> and the compiler hinted that i can use a range-for-loop, which i would read up later.
If we just want to print the result, we can use the returned vector anonymously.
For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
namespace Solution {
std::vector <int> twoSum( const std::vector<int>& nums, int target ) {
std::vector<int> v ;
// fill up the vector with the right result
return v ;
}
}
int main()
{
const std::vector <int> num = {3 , 4 , 8 , 6 , 7};
constint target = 9;
for( auto&& v : Solution::twoSum(num,target) ) std::cout << v << '\n' ;
}