atof coredump with getopt

atof coredump with getopt

本文关键字:getopt with coredump atof      更新时间:2023-10-16

我正在编写一个C++应用程序,它将华氏度转换为摄氏度和开尔文,将开尔文转换为摄氏度和华氏度等。由于在这里编写交互式应用程序是愚蠢的,我决定熟悉unistd.h中的getopt函数。

格式:F2C -k 273.15

输出:

FAHR CELSIUS KELVIN

32 0 273.15

这是我的代码:

#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#define VERSION 0.1
#define HELP help(argv[0])
#define OPTS "vk:f:c:h"
float ver = (float)VERSION;
void help(char *s);
namespace Fahrenheit
{
float FK(float F) {
return ((5.0/9.0) * (F - 32.0) + 273.15);
}
float FC(float F) {
return ((5.0/9.0) * (F - 32.0));
}
void printfahr(float F) {
std::cout << "FAHRttCELSIUSttKELVIN" << std::endl;
std::cout << F << "tt" << FC(F) << "tt" << FK(F) << std::endl;
}      
}
namespace Celsius
{
float CF(float C) {
return ((C*(9/5)) + 32);
}
float CK(float C) {
return (C+273.15);
}
void printc(float C) {
std::cout << "FAHRttCELSIUSttKELVIN" << std::endl;
std::cout << CF(C) << "tt" << C << "tt" << CK(C) << std::endl;
}
}
namespace Kelvin
{
float KF(float K) {
return (((9.0/5.0) * (K-273.15)) + 32);
}    
float KC(float K) {
return (K-273.15);
}    
void printk(float K) {
std::cout << "FAHRttCELSIUSttKELVIN" << std::endl;
std::cout << KF(K) << "tt" << KC(K) << "tt" << K << std::endl;
}
}
int main(int argc, char *argv[])
{
char arg = '';
if(argc < 2 && argc == 1 && argc > 0) {
help(argv[0]);
exit(1);
}
/*** Use function getopt() defined in unistd.h to accept 5 arguments: -v, -h, -k, -f, and -c ***/
while((arg=getopt(argc, argv, OPTS))!=-1)
{
float floatarg = atof(optarg);                                                      
switch(arg)
{
case 'v':
std::cout << "The current version is:" << ver << std::endl;
break;
case 'h':
HELP;
break;
case 'k':
Kelvin::printk(floatarg);
break;
case 'f':
Fahrenheit::printfahr(floatarg);
break;
case 'c':
Celsius::printc(floatarg);
break;
default:
HELP;
break;
}
}
return 0;
}
void help(char *s) {
std::cout << "Usage:t"<< s << " [-option] [argument]" << std::endl;
std::cout << "option:t" << "-c [temperature]: convert a Celsius temperature to Fahrenheit and Kelvin" <<  std::endl;
std::cout << "t" << "-f [temperature]: convert a Fahrenheit temperature to Celsius and Kelvin" << std::endl;
std::cout << "t" << "-h: show help information" << std::endl;
std::cout << "t" << "-k [temperature]: convert a Kelvin temperature to Fahrenheit and Celsius" << std::endl;
std::cout << "t" << "-v: show version information" << std::endl;
}

我的问题是,每当我使用不接受任何参数的选项(如 -v(时,我都会得到一个核心转储。

dbx向我展示了SIGSEV发生在第70行(float floatarg = atof(optarg);(。

当我像这样运行程序时:

./F2C -k 273.15

数学正确完成,我得到了清晰的打印输出。只有当我使用-v-h时,我的程序SIGSEV才会使用。

额外信息:

该程序是使用 Sun studio 编译器套件 5.12 版编译的。

我对为什么我的程序SIGSEV感到非常困惑。这是不一致的,毫无意义。 我将不胜感激任何可用的帮助。

应该做一些optarg检查。毕竟,您无法将null转换为浮点数。

新主((:

#define FLOATARG atof(optarg)
int main(int argc, char *argv[])
{
char arg = '';
if(argc < 2 && argc == 1 && argc > 0) {
help(argv[0]);
exit(1);
}
/*** Use function getopt() defined in unistd.h to accept 5 arguments: -v, -h, -k, -f, and -c ***/
while((arg=getopt(argc, argv, OPTS))!=-1)
{                                                      
switch(arg)
{
case 'v':
std::cout << "The current version is:  << ver << std::endl;
break;
case 'h':
HELP;
break;
case 'k':
Kelvin::printk(FLOATARG);
break;
case 'f':
Fahrenheit::printfahr(FLOATARG);
break;
case 'c':
Celsius::printc(FLOATARG);
break;
default:
HELP;
break;
}
}
return 0;
}

最短的修复是:

float floatarg = optarg ? atof(optarg) : 0.0;

你也可以重写你的代码,比如

float floatarg = 0.0;
switch(arg)
{
case 'v':
std::cout << "The current version is:" << ver << std::endl;
break;
case 'h':
HELP;
break;
case 'k':
floatarg = atof(optarg);
Kelvin::printk(floatarg);
break;
case 'f':
floatarg = atof(optarg);
Fahrenheit::printfahr(floatarg);
break;
...

float floatarg = 0.0;
if(optarg) {
floatarg = atof(optarg);
}
switch(arg)
{
case 'v':
std::cout << "The current version is:" << ver << std::endl;
break;
case 'h':
HELP;
break;
case 'k':
Kelvin::printk(floatarg);
break;
case 'f':
Fahrenheit::printfahr(floatarg);
break;
...