You are not logged in.

#1 2016-11-01 09:00:32

mikaelbrun
Member
From: Tistedal/ Norway
Registered: 2016-01-01
Posts: 43

[SOLVED]Advice using classes/structs/templates/functions in C++

I'm currently trying to learn some programing in C++ (not for profecionally purpose), and I have made a little project to practice what I have learned.

About the project:
The program is a blocklet for my i3blocks-gaps showing temperature of the CPU or GPU and showing it with a dynamic color.
The color is changing with smooth transition between a cold color and a hot color.
Currently the program is set to show CPU temperature with predefined colors (the choice between CPU and GPU and userdefined colors will be added later)

I have written a simple script/ program that works, but is only operating inside the main function. My skills are very basic, but I want to expand to using classes, structures, templates and functions. Even though I have searched the internet and read some books, I think it's hard to understand how I best can implement this to the program, and I hope some of you can guide me in the right direction.

Here is what I have so far:

// Reading CPU and GPU temperature and outputs the temperature in a dynamic color

#include <fstream> // Read temperature from file
#include <sstream> // Convert string to integer
#include <string>
#include <iomanip> // Manipulate inputs and outputs
#include <iostream>
using namespace std;


int main()
{
  string readings;
  int value;
  float currentTemp;
  float maxTemp = 70;
  int minTemp = 30;
  float factor;

  // Predifining colors
  // This will later be a config option set outside the program (like a config file i.e) 
  int colorHot = 0xFF0000;
  int colorCold = 0x0191C8;
  
  // Reading temperature from hwmon and convert it from millidegrees to degrees
  ifstream cpuValue ("/sys/class/hwmon/hwmon3/temp1_input");

  if (cpuValue.is_open())
    {
      while (getline(cpuValue, readings))
	{
	  stringstream sstrm(readings);
	  sstrm >> value;
	  currentTemp = value / 1000;
	}
      cpuValue.close();
    }
  else cout << "Unable to open file" << endl;

  // Caclulating factor
  int tempRange = maxTemp - minTemp; // Temperature range
  factor = (currentTemp - minTemp) / tempRange; // The range is considered as 100%, while current temperature is a percentage of this

  // Extracting RGB from hex
  int hotR = ((colorHot >> 16) & 0xFF);
  int hotG = ((colorHot >> 8) & 0xFF);
  int hotB = (colorHot & 0xFF);

  int coldR = ((colorCold >> 16) & 0xFF);
  int coldG = ((colorCold >> 8) & 0xFF);
  int coldB = (colorCold & 0xFF);

  // New color for current temperature
  int colorRangeR = hotR - coldR;
  int colorRangeG = hotG - coldG;
  int colorRangeB = hotB - coldB;

  // This expression includes the temperature position and the RGB color range to make sure of smooth transition
  int newR = hotR - ((1 - factor) * colorRangeR);
  int newG = hotG - ((1 - factor) * colorRangeG);
  int newB = hotB - ((1 - factor) * colorRangeB); 

  // Printing temperature (to get color working, i3blocks-gaps needs both Long and Short since the third cout is read as color)
  cout << "CPU: " << currentTemp << " °C" << endl; // Long
  cout << "CPU: " << currentTemp << " °C" << endl; // Short

  // Printing the new color as hex-value
  // Since C++ don't implement zeros in the beginning of a hexadecimal I use setfill() and setw() to make sure it will output at least 6 numbers 
  if ( currentTemp <= minTemp )
    cout << "#" << setfill('0') << setw(6) << hex << colorCold << dec << endl; // Sets a the minimum color value if temperature drops below pre-defined minTemp

  else if ( currentTemp >= maxTemp )
    cout << "#" << setfill('0') << setw(6) << hex << colorHot << dec << endl;

  else
    // Here I have setw(2) for each RGB value to make sure I will end up with six numbers. 
    cout << "#" << setfill('0') << setw(2) << hex << newR  << setw(2) << newG << setw(2) << newB << dec << endl;

  return 0;

}

My thoughts is to at least put the color part as a class with functions. The conversion of the hex-color should output the the RGB values.
The new color should maybe be a sub class of the color, and should be converted back to hex format.
The temperature could be a class, and the calculation of the temperature factor could be a sub class.

I have no experince using of this besides tutorials and reading, but I think I should try to figure out the codeing myself, but some guidence would be great.
How would you have done this?
(BTW: I will make the program recognize the manufacturer of the CPU and GPU and pick up the values from the right place later)

EDIT: compiling and running this program, works on my computer, but I have experienced that the location of the correct hwmon folder is random on each installation. Compiling and running in a terminal will give the temperature 2 times and the hex color.

Last edited by mikaelbrun (2016-11-02 22:00:12)

Offline

#2 2016-11-01 12:05:59

drcouzelis
Member
From: Connecticut, USA
Registered: 2009-11-09
Posts: 4,092
Website

Re: [SOLVED]Advice using classes/structs/templates/functions in C++

I think your code looks nice.

I'm sorry, I don't see an obvious way to add classes, structs, or functions to your code. Especially not templates... tongue

You had a "problem", and you used code to make a "solution". The code is easy to read, it works, and it's fast. That's great! Other programming tools (classes, structs...) can help make programming easier, but you don't need them for every project.

So, I will give you general advice instead:

Functions: Did you "copy and paste" many lines of code? Does your code have too many indentations? Are you doing the same thing again and again with LITTLE changes each time? The you probably should use a function.

Structs: Do you have a logical grouping of data to store? For example:

CPU #1
    Current temperature: 60
    Current speed: 1.0
    Load: 1%

CPU #2
    Current temperature: 50
    Current speed: 2.0
    Load: 2%

Then you probably should use a struct.

Classes: The most important thing about classes is that classes can have "subclasses"... But I can't think of any example that would apply to your program!

You said you are "learning C++". Do you have experience using another programming language?

(Note for any other programmers: I wrote this response to purposefully be short, simple for a beginner programmer, and applicable to the programming example that was given.)

Offline

#3 2016-11-01 13:34:29

mikaelbrun
Member
From: Tistedal/ Norway
Registered: 2016-01-01
Posts: 43

Re: [SOLVED]Advice using classes/structs/templates/functions in C++

Thanks for a quick and good reply, drcouzelis!

I have done some programming (or scripting) in Matlab when I studied for my Bachelor in Mechanical engineering. But that was mostly arithmetic programming, wich as far as I know is a derivative of the C/C++ language.
I have also been playing around with an Arduino starting kit. This is also based on the C/C++ language, but is more directed towards making physical things to happend (turning on and off lights, etc).
That is why I chose the C++ now, since I was introduced to it using the Arduino.

Besides that, I have done some Bash scripting, and my program would most likely been easier to make using Bash with sed and awk, but then again, I wouldn't learn any C++. I like to learn new stuff, and I don't like doing it the easy way.

I also think I have done a decent job on my program, and such a small program doesn't give much typeing effort, but I thought maybe I could implement some new elements in my C++ understanding.
I have read alot of tutorials and books, but I don't think they tells me how to use those elements the best way. It shows how to use it, and nothing more.

First I thought that the conversion of the hex colors would be a good start for using classes and/ or functions, but I couldn't excactly figure out how I could return the R, G and B from a function. Then I saw some tips to use struct.
That's the reason I would get some advice, so I don't push myself into a corner I can't get out of :-).

I'm happy you find my coding easy to read.

You also said it was fast, and that is great, but in i3blocks, I can set an interval to run the program multiple times. Is that a good practice thinking of resource usage, or should I make a while loop as long as the program is active?

Offline

#4 2016-11-01 14:19:17

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,523
Website

Re: [SOLVED]Advice using classes/structs/templates/functions in C++

mikaelbrun wrote:

First I thought that the conversion of the hex colors would be a good start for using classes and/ or functions, but I couldn't excactly figure out how I could return the R, G and B from a function. Then I saw some tips to use struct.

You could use a struct, but the way you've set this up, the color "gradient" would actually be the perfect place to use a class.  You want to set it up with the two hex colors, and have it do all the work behind the scenes to give you the rgb values for each "step".  So conceptually:

Class MYGRADIENT:
   defaultHot = 0xFF0000;
   defaultColor = 0x0191C8;

   constructor()

   constructor(int,int) // for initializing with different hot/cold colors as integer values

   // other constructors for initializing with "strings" of hex codes read in from a config file?

   getcolor() // does allthe calculations for the color you want, and returns the appropriately zero-padded hex code, or whatever is really needed

I've left this in very minimal pseudo code so you can play with it yourself.

Now all the hackery of calculating the hex color code needed is encapsulated in that class.  So your logic of getting the cpu use (or anything else you want color coded) is clean and it just calls the "getcolor" function for the next needed color.  Hint: getcolor will likely have a parameter, cpu percent perhaps.

Of course a class is of most use if it is more generic.  So rather than thinking of these as "hot" and "cold" colors, you could just use "start" and "end" colors and have this become a general purpose gradient class.


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Online

#5 2016-11-01 14:23:45

drcouzelis
Member
From: Connecticut, USA
Registered: 2009-11-09
Posts: 4,092
Website

Re: [SOLVED]Advice using classes/structs/templates/functions in C++

mikaelbrun wrote:

I like to learn new stuff, and I don't like doing it the easy way.

Sounds like Arch Linux was a good choice for you. wink

mikaelbrun wrote:

First I thought that the conversion of the hex colors would be a good start for using classes and/ or functions, but I couldn't excactly figure out how I could return the R, G and B from a function. Then I saw some tips to use struct.

DISCLAIMER: I love C, but I hate C++. My answer might be a little more "C oriented", but it should still apply to C++. smile

Your options for writing a function to convert a "0x######" hex value into an "RRGGBB" RGB value include:

Create the function:

bool convert_hex_to_rgb(int hex, int *r, int *g, int *b);

void main()
{
    int r, g, b;
    convert_hex_to_rgb(0x112233, &r, &g, &b);
}

This function will "return" the RGB values in the three "int" variables that are being pointed to. The actual "bool" that is returned could be "true" for success or "false" for failure. ("Computer, please convert 'HAMBURGER' into RGB values.") wink

...or...

Create a struct to basically do the same. This would be beneficial if you have a LOT of data that needs to be "returned".

typedef struct
{
    int r;
    int g;
    int b;
} COLOR;

bool convert_hex_to_rgb(int hex, COLOR *color);

void main()
{
    COLOR color;
    convert_hex_to_rgb(0x112233, &color);
}

...or...

Create a class representing a color that can be converted:

// High level, example code
class Color
{
    Color(int new_hex_value);

    int get_red();
    int get_green();
    int get_blue();

private:
    int hex;
};

Color color = new Color(0x112233);
int r = color.get_red();

...or...

FYI, Python (programming language) functions are able to return multiple values! big_smile

def convert_hex_to_rgb(hex):
    r = DO_CALCULATIONS_HERE
    g = DO_OTHER_CALCULATIONS
    b = MORE_PRETEND_CALCULATIONS
    return r, g, b

Kinda cool.

mikaelbrun wrote:

You also said it was fast, and that is great, but in i3blocks, I can set an interval to run the program multiple times. Is that a good practice thinking of resource usage, or should I make a while loop as long as the program is active?

You mean, you can tell "i3blocks" to (for example) run your program every 1 second? I think that's a good idea. "i3blocks" code is probably pretty good at sleeping quietly. Better than I can do at least. tongue

Offline

#6 2016-11-01 15:24:42

JohnBobSmith
Member
From: Canada
Registered: 2014-11-29
Posts: 804

Re: [SOLVED]Advice using classes/structs/templates/functions in C++

I have a few minor style gripes. Each person has there own style, but, in my opinion, the following can help make code more readable:
1) If you need to, especially for long comments, break it up over many lines. That way you dont have to scroll left/right to see what you are doing. Same goes for long function arguments or really anything requires a long width of code. Example:

//This really long comment describing someFunction(int param1, float param2, bool param3 = false) and its many parameters and what they do might be better put on multiple lines to become...
---------
//Some function, takes 3 paramenters:
//Param1: A random int
//Param2: A random float
//Param3: Do we really need this function?
someFunction(int param1, float param2, bool param3 = false) 

I really prefer to use brackets for all if, else, while, for, etc. etc. statements. That way each statement has a well defined start and end. So the following:

  if ( currentTemp <= minTemp )
    //Code...
  else if ( currentTemp >= maxTemp )
    //More code...
  else
    //More code!...

Becomes:

  if ( currentTemp <= minTemp ) {
    //Code...
  } else if ( currentTemp >= maxTemp ) {
    //More code...
  } else {
    //More code!...
  }

Now you should never have obscure compiler errors regarding missing brackets or lack thereof or what have you. Finally, I am not a fan using namespace std;. I always prefer to go std::cout, std::cin, etc. for readability and to avoid polluting the global namespace as much as possible. Its good habit imo. The idea is to prevent name clashes or confusion further down the road. Now. lets talk about classes. For my projects with classes, I like to give each class a clear purpose. For my bullet class of my current project, my thought process is: What variables and functions do my bullets need, what variables and functions do other files need access to, does this need to be modified and if not, should it be private? Things like this. As suggested, it may be a great idea to use a class for your hexadecimal code and color. Say...

class Color
{
    public:
    //Set the color
    void setHexColor(int hexColor);
    
    //Get the the color
    int getHexColor();

    //Calculate the color
    int extractRgbFromHex();

    //Print it
    void printColor();
   
    private:
    //Our working hex color.
    //To be modified internally by
    //Our functions, but not directly       
    int workingHexColor;
};

So now you would then define these functions and what you want them to do. I hope this helps!


I am diagnosed with bipolar disorder. As it turns out, what I thought was my greatest weakness is now my greatest strength.

Everyday, I make a conscious choice to overcome my challenges and my problems. It's not easy, but its better than the alternative...

Offline

#7 2016-11-01 15:32:41

drcouzelis
Member
From: Connecticut, USA
Registered: 2009-11-09
Posts: 4,092
Website

Re: [SOLVED]Advice using classes/structs/templates/functions in C++

JohnBobSmith wrote:

For my bullet class of my current project

For a video game, right? I have a bullet struct in my current project too. big_smile

Making a simple video game is the best way to learn programming in my opinion. They can be as simple or as complex as you want. You can EASILY find places to implement structs, classes, templates, functions, and recursion in a video game.

And the world can never have too many video games. wink

Offline

#8 2016-11-01 16:15:49

mikaelbrun
Member
From: Tistedal/ Norway
Registered: 2016-01-01
Posts: 43

Re: [SOLVED]Advice using classes/structs/templates/functions in C++

This is why I posted this in the first place!
I get different ways of doing it, and I can pick whatever I feel the most comfortable with :-)

Trilby wrote:

I've left this in very minimal pseudo code so you can play with it yourself.

I'm glad you give me the opportunity to try it myself and not give me a code to copy/paste. That goes for everyone else doing the same thing.

drcouzelis wrote:

Sounds like Arch Linux was a good choice for you. wink

Absolutly the best choice for me. The downside is that I got kind of hooked on the programming :-P

drcouzelis wrote:

FYI, Python (programming language) functions are able to return multiple values! big_smile

I know there is many other languages more "userfriendly", but wouldn't that be the easy way? ;-)

drcouzelis wrote:

You mean, you can tell "i3blocks" to (for example) run your program every 1 second?

Yes, and I can tell to run without any delay, or I can tell it run once.

JohnBobSmith wrote:

So now you would then define these functions and what you want them to do. I hope this helps!

This helps alot! I now have alot to work with. I will try different sollution and, probobly get back when I'm stuck :-D

Offline

#9 2016-11-01 17:09:30

JohnBobSmith
Member
From: Canada
Registered: 2014-11-29
Posts: 804

Re: [SOLVED]Advice using classes/structs/templates/functions in C++

drcouzelis wrote:
JohnBobSmith wrote:

For my bullet class of my current project

For a video game, right? I have a bullet struct in my current project too. big_smile
...

You know it! Shameless self promotion: https://github.com/JohnBobSmith/SpaceyRocks. This is by far my best project to date, I'm really quite proud of it. I just finished adding a Makefile that (hopefully) works as intended. big_smile


I am diagnosed with bipolar disorder. As it turns out, what I thought was my greatest weakness is now my greatest strength.

Everyday, I make a conscious choice to overcome my challenges and my problems. It's not easy, but its better than the alternative...

Offline

#10 2016-11-01 17:44:54

drcouzelis
Member
From: Connecticut, USA
Registered: 2009-11-09
Posts: 4,092
Website

Re: [SOLVED]Advice using classes/structs/templates/functions in C++

C++, SFML, MIT license, music and sound effects... Very nice!

Please commit your Makefile, so I can try it out! smile

EDIT: I just found the Makefile. Oops. I'll try out your game tonight.

Last edited by drcouzelis (2016-11-01 17:47:23)

Offline

#11 2016-11-01 17:52:51

JohnBobSmith
Member
From: Canada
Registered: 2014-11-29
Posts: 804

Re: [SOLVED]Advice using classes/structs/templates/functions in C++

big_smile, thanks. Lets continue this conversation via forum PM or email. smile


I am diagnosed with bipolar disorder. As it turns out, what I thought was my greatest weakness is now my greatest strength.

Everyday, I make a conscious choice to overcome my challenges and my problems. It's not easy, but its better than the alternative...

Offline

#12 2016-11-02 21:58:23

mikaelbrun
Member
From: Tistedal/ Norway
Registered: 2016-01-01
Posts: 43

Re: [SOLVED]Advice using classes/structs/templates/functions in C++

Studying all of your advices takes some time, and I am working on it. (It's alot to process :-) )

JohnBobSmith wrote:

I really prefer to use brackets for all if, else, while, for, etc. etc. statements. That way each statement has a well defined start and end.

I couldn't agree more, and I actually usually does. I don't know why I didn't do it here. As you said, we all have our style. Mine is:

 
if ( currentTemp <= minTemp )
{
    // Code ...
}

else if ( currentTemp >= maxTemp) 
{
    // Code ...
}

else 
{
    // Final code ... 
}

This gives more blank spaces and more lines, but I find this easier to read (might be my ADHD that prevents me to separate compact codes).

Anyway, thanks for all your good advices. I believe I will find my way through this now.

Offline

Board footer

Powered by FluxBB