beginner: How do I improve usabillity

Hey!
so I just started taking classes to learn programming(self search and and the use of forums is highly encouraged so here I go)

(I've removed most comments as they were all originally in swedish and you guys probably know all this)

I'm supposed to create a simple program calculating the average value of numbers in an array. Just for getting an E the program is adequate but I hate doing things half-assed especially since I'm taking the course to learn by my own accord.
Naturally I wanted to improve usability in the program by preventing the user from inputting the wrong things and this is where I ran in to some problems:

problem 1: I wished to prevent the user from inputting too many values and to do this I figured I'd use a condition and ".length"(I did learn some JS before this)
to use the length or the array I learned that I'd have to use getline(cin.input) and .zize

problem 2: I already had my array passed in to my function and figured I could just replace cin>> with getline. This naturally produced a bunch of errors since
getline accepts string and not int's(or so I've come to understand)

problem 3: Using a few threads from here (one of them: http://www.cplusplus.com/forum/articles/9645/)I decided to try a string to number conversion. However I soon realized that templates "T"(is that correct? and stringstreams etc was a completely alien concept and I was even unable to use the pre-made functions and just adding my own values.

problem 4: even if I had the prerequisite skills to fully understand the conversion(I tried the harder ones with better usability) the values I was trying to pass were the same I wanted printed using getline in the first place.

so here I am!
In short what I wish to have help with is a nudge in the right direction how I shall proceed to either use getline and a condition to prevent user from inputting to many values
(I've yet to figure out how to prevent them from inputting the wrong kind aswell so perhaps a nudge there too)
or to approach the problem in a completely other manner.

please remember that so far I may have difficulty recognizing native c++ functions such as stringstreams and just variables and that english is not my native tongue and that some terminology I use might be wrong and that I might not understand it all at first without further explaning

sorry for the long post i shall learn how to program a potato of appreciation

(I have tried to reset the code as it was before my attempts but not tried it so if anything is obviously broken it may be a miss of mine or simply noobiness)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <string>
#include <sstream>
#include <iostream>
using namespace std;

//function to calculate average value of array
float medel(int v[],int n){
	float sum = 0;
	    for(int i = 0;i<n;i++){  
		    sum+=v[i]; 
	    }
	
	return sum/n;
}


int main(){
    
    cout << "We're going to calculate the average value of ten numbers of the users choice";
	int n = 10;
	int v[n]; 
	
	
	//have user input 10 numbers
	cout<< "Please enter ten numbers seperated by SPACE then press ENTER\n           Function input:\n";
	cin >>v[0]>>v[1]>>v[2]>>v[3]>>v[4]>>v[5]>>v[6]>>v[7]>>v[8]>>v[9];
	
        //called function
	float med =medel(v,n);
	
	//print average value
	cout << "The average value is: " << med;
    
}
Last edited on
Main thing about streams: it is just provides a sequence of characters. They are all conceptually the same, only difference is their source: console window, files, sockets... Sometimes we need to handle a sequence of characters in memory as stream. This is what stringstreams do.

So you want to get a line user inputs using getline and create a istringstream from that line.
Now you have a stream which behaves exactly as cin, but is not "infinite" (when cin runs out of characters it just asks user for more), so you can actually reach the end and definetly say how many values are there.

Now you just need to read n values. If at any time stream gets in failed state, then something is wrong in user input and you need to ask him again. That handles invald input. Now for too large input. For this you just need to attempt to read a single character after you get your numbers. If you succeed, it would mean that user entered something else after n numbers, if you fail, then there wasn't anything here and everything is correct.


Ask if you need code examples.
line 13 is an integer division. You need to cast at least one of those to float before the division.

return (float) sum / n;

Hope this helps.
no, see line 8 float sum = 0;


By the way, use a loop for line 26
Last edited on
Main thing about streams: it is just provides a sequence of characters. They are all conceptually the same, only difference is their source: console window, files, sockets... Sometimes we need to handle a sequence of characters in memory as stream. This is what stringstreams do.

So you want to get a line user inputs using getline and create a istringstream from that line.
Now you have a stream which behaves exactly as cin, but is not "infinite" (when cin runs out of characters it just asks user for more), so you can actually reach the end and definetly say how many values are there.

Now you just need to read n values. If at any time stream gets in failed state, then something is wrong in user input and you need to ask him again. That handles invald input. Now for too large input. For this you just need to attempt to read a single character after you get your numbers. If you succeed, it would mean that user entered something else after n numbers, if you fail, then there wasn't anything here and everything is correct.


Ask if you need code examples.


I think I do need an example of code as I've not yet come far enough to fully grasp what to do.
I understand what you are saying but I'm clueless on how to proceed.
The condition varification I think I can manage by looking at examples but the part about inputting values in getline I still don't know how to do it

Just like to add that I'm not here to finish a homework I'm only taking the class to learn and the grade doesn't matter so if you think I ask too much it's because I want to learn or understand more not have you complete my assignment


Jun 18, 2015 at 8:47am
ne555 (7586)


By the way, use a loop for line 26

A loop would definitely be more effective but not necessary as I wish to remove the cin
Just to learn something from it though
For(i=0;i<n;i++){
Cin >>v[i];
}
Would that be correct?
Here is an example. I tried to aim for clarity and not efficiency and elegancy. So no separating code into functions, no coomon ways to shorten code.

Ask if you have any questons:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
#include <sstream>
#include <string>

int main()
{
    constexpr size_t n = 10; //size of an array
    int values[n];
    bool input_correct;
    //A loop. We repeat input until everything is correct
    do {
        std::cout << "Please enter ten numbers seperated by SPACE then press ENTER\n"
                     "           Function input:\n";
        std::string user_input;

        //Read everything user inputs before pressing enter
        //and store it in user_input string
        std::getline(std::cin, user_input);

        //Create a string stream out of that string:
        std::istringstream line(user_input);

        //Now we need to extract n integers and make sure input was correct
        size_t i = 0; //a loop counter
        int temp; // An integer we will use to temporary store extracted value

        //Repeat loop while we either reach n iteration or error while reading happens
        while(i < n && line >> temp) {
            values[i] = temp; //Save extracted value
            ++i; //increment counter
        }
        //If we encountered an error while reading, that means input did not
        //contain 10 integers. Set error flag. Else input is (yet) correct
        if( !line )
            input_correct = false;
        else
            input_correct = true;

        //Now we need to check if there anything written after our 10 numbers
        //We will try to read a character and if we succeed, it means something was here.
        //This version allows whitespace characters after last number
        //Which I think is reasonable thing to do
        char c;
        if(line >> c) //If reading succeeded
            input_correct = false;

        //Output error message if something wrong:
        if( !input_correct )
            std::cout << "Invalid input\n";
    } while ( !input_correct);

    //Process input further here

}
ne555 wrote:
no, see line 8 float sum = 0;
It was an int at the time I responded.
Thank you! This is a lot more readable to me. I think I can finish my program in the way I want using this but to make sure I understand and learn from this I have a few questions before I try my best:

1: why not use "using namespace std;" does it draw more memory or just preference?

2: line7: constexpr size_t n = 10; I don't quite understand this part if we break it down is:
const(constant)expr(a type of variable?) size_t(a function? is t = template?) n=10(value)
(I don't know what templates are and what they do that's just what I got while trying to google why people where using "_T"
3: line 28: so you feed line(which is the stream/ input) in to temp to store the value each loop?
4: line 34: is this basically if input numbers not equal input numbers?
5: line 44: this I don't quite understand: is it input+a character(letter or number) means it's more than 10 which later gives an error message because !input_correct == false?
Last edited on
1) http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice

2) constexpr is a C++11 feature. It means that variable is a compile-time constant. It gives more guarantees and is very useful. If you want, replace it with const, it will do the same here.
size_t is an unsigned type which is guaranteed to be able to contain size on any entity in your program (_t stays for type, so type name is read as size type). If you have a 64bit PC, it is probably a type alias for unsigned long long. I used it because it is a good idea to store size in variable of type created to store size.

3) Yes, I extract value from a stream. Same way you would do with cin.

4) It tests if there were any errors during extraction. If there were errors then data passed was not correct and we need to prompt input again.
Essentually it is not <Everything is okay>
http://en.cppreference.com/w/cpp/io/basic_ios/operator!

5) I try to read a single character to test if there is something written after nth number.
If I succeed, then there was something here and input was not correct, so I need to set variable to false.
If I fail, then there was nothing here and variable should stay as it is now (note taht it might still be false if value reading earlier failed).

..............
Last edited on Jun 17, 2015 at 10:36pm



line 13 is an integer division. You need to cast at least one of those to float before the division.

return (float) sum / n;

Hope this helps.
Jun 18, 2015 at 4:13am


nope it was a float all along ;D

thanks everyone I'll do my best and if I need anymore help I'll keep posting how far I got!
So this is what I've come up with and it's pretty much identical to the template you provided. I'd much rather create something original but as far as I've come I'm not quite there yet. I understand the basics but not enough to be creative.

I just have a few more questions:

1: In your code line 14: why is string an std::? I don't know what std:: is really.
I realize it's bothersome to ask questions I probably could have as easily googled but I feel that I learn more through it. The book I purchased for class so far is more: "This is how you do it" and not "This is how you do it and why" and I really need my why's or I wont learn

2: how do I make my condition accept decimal numbers?(the conversion in the sticky I wanted to use but couldn't understand was premade to accept decimals but is there a simpler way I could understand?)

3: line 11 and 50: why do you have do{ and }while(!input_correct);(also why ";" and not
"{"? this part I don't understand at all unfortunately.
in my code I removed it all together and it worked(nevermind see Q4)

4: I acctually realised the above question as I wrote it and it's something I've been wondering about: to start the loop over instead of ending the program do you create an internal loop using do{ and }while; ending it with ";" or how does it work?

yet again I've removed all comments as they are in swedish explaining why I've done what I've done and how I learned it and I think you all get it anyway

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
#include <string>
#include <sstream>



float medel(int v[],int n){
	float sum = 0;
	    for(int i = 0;i<n;i++){ 
		    sum+=v[i]; 
	    }
	return sum/n;
}


int main(){
    
    bool inputCorrect;
    const int n = 10;
	int v[n];
	
    std::cout << "We're going to calculate the average value of ten numbers of the users choice";

    do{
    	
    
        std::cout<< "Please enter ten numbers seperated by SPACE then press ENTER\n Function input:\n";
        std::string userInput; 
        	
        std::getline(std::cin, userInput);
      
        std::istringstream line(userInput);
        	
        long i = 0;
       
        long temp;
        
        while(i < n && line >> temp){
            v[i] = temp; //
            i++;
        }
        	

        if(!line){
           inputCorrect = false;
        }   else {
                inputCorrect = true;
    	    }
    	   
        char check;
        if(line>>check){
            inputCorrect = false;
        }
        
        if(!inputCorrect){
            std::cout << "Invalid input please enter ten numbers seperated by SPACE and press ENTER\n";
        }
        } while(!inputCorrect);
	
	
	float med =medel(v,n);
	
	
	std::cout << "The average value is: " << med;
    
}
Last edited on
1) std:: is a namespace. Mainly namespace where all standard library stuff reside.
http://www.cplusplus.com/forum/beginner/61121/
Some bad teachers promote bad habit of dumping that namespace in global namespace by using using namespace std;. Which is considered bad practice: http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice

2) This is a little tricky. First of all int stands for integer. It can accept only whole numbers. So to make it work with decimals you need to change it to something which can hold fractions: double.
You need to change type of your array, type of temp variable and signature of your function. Do not change n or i, as they are not receiving your values but here to hold some natural number (which cannot be decimal)

3) This is a do-while loop
http://www.learncpp.com/cpp-tutorial/56-do-while-statements/
http://www.cplusplus.com/doc/tutorial/control/#dowhile

4) Yes, this is pretty much that, see #3
2) Of course it was obvious once I thought about it... was quite late when I finished so it never occurred.
I had used long for temp when I should've used float.... I was told to use the input "v[i], n" in my function so I'm not sure I should change it as it was specified but unless I do if I use decimal values it will only round up or down the value to the nearest integer

1) I think it is to teach the basics before moving on to more advance stuff but for me I just get confused as nobody else does it

MiiNiPaa (7325)
1) std:: is a namespace. Mainly namespace where all standard library stuff reside.
http://www.cplusplus.com/forum/beginner/61121/
Some bad teachers promote bad habit of dumping that namespace in global namespace by using using namespace std;. Which is considered bad practice: http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice

2) This is a little tricky. First of all int stands for integer. It can accept only whole numbers. So to make it work with decimals you need to change it to something which can hold fractions: double.
You need to change type of your array, type of temp variable and signature of your function. Do not change n or i, as they are not receiving your values but here to hold some natural number (which cannot be decimal)

3) This is a do-while loop
http://www.learncpp.com/cpp-tutorial/56-do-while-statements/
http://www.cplusplus.com/doc/tutorial/control/#dowhile

4) Yes, this is pretty much that, see #3
as nobody else does it
Err, aside from any competent programmer? I just browsed several projects on github. Several facebook utilites, Xenia, Notepad++, cocos2d — no one is using namespace directive.

I think it is fine for beginning, but only after explaining about namespaces, what using directive does and dangers of it. And, of course, prohibiting it after learning basics.
meant nobody used namespace std not the other way around... that's why I was getting sceptical why I should use it
Topic archived. No new replies allowed.