带有 getopt 的 atof coredump
atof coredump with getopt
我正在编写一个 C++ 应用程序,它将华氏度转换为摄氏度和开尔文,以及将开尔文转换为摄氏度和华氏度等。由于在这里编写交互式应用程序很愚蠢,我决定熟悉 unistd.h.
格式:
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 << "FAHR\t\tCELSIUS\t\tKELVIN" << std::endl;
std::cout << F << "\t\t" << FC(F) << "\t\t" << 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 << "FAHR\t\tCELSIUS\t\tKELVIN" << std::endl;
std::cout << CF(C) << "\t\t" << C << "\t\t" << 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 << "FAHR\t\tCELSIUS\t\tKELVIN" << std::endl;
std::cout << KF(K) << "\t\t" << KC(K) << "\t\t" << K << std::endl;
}
}
int main(int argc, char *argv[])
{
char arg = '[=10=]';
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 = '[=10=]';
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;
...
我正在编写一个 C++ 应用程序,它将华氏度转换为摄氏度和开尔文,以及将开尔文转换为摄氏度和华氏度等。由于在这里编写交互式应用程序很愚蠢,我决定熟悉 unistd.h.
格式:
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 << "FAHR\t\tCELSIUS\t\tKELVIN" << std::endl;
std::cout << F << "\t\t" << FC(F) << "\t\t" << 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 << "FAHR\t\tCELSIUS\t\tKELVIN" << std::endl;
std::cout << CF(C) << "\t\t" << C << "\t\t" << 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 << "FAHR\t\tCELSIUS\t\tKELVIN" << std::endl;
std::cout << KF(K) << "\t\t" << KC(K) << "\t\t" << K << std::endl;
}
}
int main(int argc, char *argv[])
{
char arg = '[=10=]';
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 = '[=10=]';
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;
...