Search code examples
c++linuxstdfstream

Invalid argument STD error after compiling - no errors in VS Code IDE


I need some help with a simple program I am writing to get output from the /sys/class/thermal/thermal_zone0/temp file. Ordinarily using the command cat /sys/class/thermal/thermal_zone0/temp outputs the temperature as a five digit integer (i.e. 45000). The intention of my program is to take that output and convert it to human readable in degrees Celsius, degrees Fahrenheit, and Kelvin.

One of the instructions in the code is to take the sysTemp variable which will be read in as a string and convert it to a double called tempLong named because it will contain the original read in from the /sys/class/thermal/thermal_zone0/temp file. From there a little math conversions take place to output to the user temperature data in the three aforementioned formats. This is where I believe the error is originating from.

Showing no errors in VS Code. After compiling in Linux using g++ (version 9.4.0) the program will not run. Instead I get the following error (I included the command I used to compile):

$ g++ -o tempmon Repositories/TemperatureMonitor/src/tempmonCPU.cpp
$ ./tempmon
terminate called after throwing an instance of 'std::invalid_argument'
  what():  stod
Aborted (core dumped)

Here is my code:

// Preprocessor directives and namespace usage
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>

using namespace std;

// Main function
int main()
{
    ifstream thermal;
    string sysTemp = ""; // Will store the output of thermal
    double tempLong = stod(sysTemp); // Convert string to double
    double tempCelsius = tempLong / 1000; // Convert output to human readable
    double tempFahrenheit = tempCelsius * (9/5) + 32; // Convert to Fahrenheit
    double tempKelvin = tempCelsius + 273.15; // Convert to Kelvin
    setprecision(3); // Use 3 significant digits

    // Read in /sys/.../temp file
    // Point read pointer to beginning of file
    thermal.open ("/sys/class/thermal/thermal_zone0/temp", ios::in);

    // Check if file is open and output in human readable format
    if (thermal.is_open())
    {
        while (getline (thermal, sysTemp))
        {
            // Output to human readable format
            cout << "   System temperature (Celsius):  " << tempCelsius << " \u00B0C\n"
                 << "System temperature (Fahrenheit):  " << tempFahrenheit << " \u00B0F\n"
                 << "    System temperature (Kelvin):  " << tempKelvin << " K\n";
        }
        thermal.close();
    }
    else // File does not open
    {
        cout << "Failure to open '/sys/class/thermal/thermal_zone0/temp'\n"
             << "Please try again . . .\n\n";
    }

    // Exit program without errors
    return 0;
}

Code can also be found at my GitHub: https://github.com/kawilkins/TemperatureMonitor

I am absolutely certain I jacked up some syntax somewhere. File I/O I applied pretty much from memory, except for a few sanity checks to make sure I was remembering the syntax correctly.

At this point any help would be appreciated.


Solution

  • Variables in C++ will not automatically updated like wire in Verilog.

    Do the conversion after reading lines.

    // Preprocessor directives and namespace usage
    #include <iostream>
    #include <iomanip>
    #include <fstream>
    #include <string>
    
    using namespace std;
    
    // Main function
    int main()
    {
        ifstream thermal;
        string sysTemp = ""; // Will store the output of thermal
        // do not do conversion here
        //double tempLong = stod(sysTemp); // Convert string to double
        //double tempCelsius = tempLong / 1000; // Convert output to human readable
        //double tempFahrenheit = tempCelsius * (9/5) + 32; // Convert to Fahrenheit
        //double tempKelvin = tempCelsius + 273.15; // Convert to Kelvin
        setprecision(3); // Use 3 significant digits
    
        // Read in /sys/.../temp file
        // Point read pointer to beginning of file
        thermal.open ("/sys/class/thermal/thermal_zone0/temp", ios::in);
    
        // Check if file is open and output in human readable format
        if (thermal.is_open())
        {
            while (getline (thermal, sysTemp))
            {
                // do conversion here
                double tempLong = stod(sysTemp); // Convert string to double
                double tempCelsius = tempLong / 1000; // Convert output to human readable
                double tempFahrenheit = tempCelsius * (9/5) + 32; // Convert to Fahrenheit
                double tempKelvin = tempCelsius + 273.15; // Convert to Kelvin
                // Output to human readable format
                cout << "   System temperature (Celsius):  " << tempCelsius << " \u00B0C\n"
                     << "System temperature (Fahrenheit):  " << tempFahrenheit << " \u00B0F\n"
                     << "    System temperature (Kelvin):  " << tempKelvin << " K\n";
            }
            thermal.close();
        }
        else // File does not open
        {
            cout << "Failure to open '/sys/class/thermal/thermal_zone0/temp'\n"
                 << "Please try again . . .\n\n";
        }
    
        // Exit program without errors
        return 0;
    }