C++牛人,字符串格式化问题.(Programmable formatting string)

freeia 2003-07-21 03:05:10
char buf[80] = {0};
sprintf(buf, "%.16f ", nDoubleValue);
我想其中的16是可编程的,根据自己的意思来设定精度.
那么这个代码怎么写好呢?

偶的代码如下:
bool CMatrix::SaveDataIntoFile(string& strFileName, const unsigned long& nPrecision/* = 16*/)
{
ofstream outfile(strFileName.c_str(), ios_base::out);
if(!outfile)
{
cerr<<"cannot open "<<strFileName<< " for output."<<endl;
return false;
}

char buf1[80] = {0};
char buf2[80] = {0};
char CrLf[] = "\n";

char buf_format[80] = {0};
sprintf(buf_format, "%%.%dlf ", nPrecision);

for(unsigned long i = 0; i < m_nRow; ++i)
{
for(unsigned long j = 0; j < m_nCol; ++j)
{
sprintf(buf1, buf_format, m_pMatrix[i][j]);
outfile.write(buf1, sizeof(buf1));
strcpy(buf1, buf2);
}
outfile.write(CrLf, sizeof(CrLf) - 1);
}

outfile.close();

return true;
}

但我还是觉得有改进的余地,请指点.
我觉得爽的,给高分!
觉得这个帖子有学习意义的up一下,觉得这个帖子是垃圾的,down一下.
来个的,路过的兄弟姐妹,做个记号流个言在走.
:)

...全文
301 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
freeia 2003-07-21
  • 打赏
  • 举报
回复
我现在就需要string类中有踢去空格的函数,如果没有,看来要自己写了.
Find对应的我找到了.
谢谢stukov2002,明天结贴!
idontlikenickname 2003-07-21
  • 打赏
  • 举报
回复


long double类型具有19位小数,但是在printf()函数族的格式化输出中没有与之相对应的字符,也就是说你只能使用%f,%e,%g等输出double型的指示字符,结果也只能是13位小数,虽然在内存中的位数是19位.
string类中的好像没见过与Trimleft等对应函数,Find有对应的函数~

freeia 2003-07-21
  • 打赏
  • 举报
回复
(上面没说清楚:关于编译通不过的问题已经解决!)
还有,标准库中的string类中有像CString 中这样的函数吗?

XC

CString strData;
strData.TrimLeft ();
strData.TrimRight ();
nIndex = strData.Find (SPACE_CHARACTER);
freeia 2003-07-21
  • 打赏
  • 举报
回复
错了,我是说我想得到更高精度的该如何做?
freeia 2003-07-21
  • 打赏
  • 举报
回复
To stukov2002(卡拉是头猪) () 信誉:115 :
我想得到高精度的呢?
用long double就会好一些吗?最好不用与具体的编译器拓展相关的指令,只用标准C++语法.
idontlikenickname 2003-07-21
  • 打赏
  • 举报
回复


如果还有编译错误就帖出来~

idontlikenickname 2003-07-21
  • 打赏
  • 举报
回复


什么语法错误?我在vc中使用这种方法从没遇见过错误~应该不是这种方法引起的.

bool CMatrix::SaveDataIntoFile(string& strFileName, const unsigned long& nPrecision/* = 16*/)
{
ofstream outfile(strFileName.c_str(), ios_base::out);
if(!outfile)
{
cerr<<"cannot open "<<strFileName<< " for output."<<endl;
return false;
}

char buf1[80] = {0};
char buf2[80] = {0};
char CrLf[] = "\n";

// char buf_format[80] = {0};
// sprintf(buf_format, "%%.%dlf ", nPrecision);

for(unsigned long i = 0; i < m_nRow; ++i)
{
for(unsigned long j = 0; j < m_nCol; ++j)
{
// sprintf(buf1, buf_format, m_pMatrix[i][j]);
// 举例: 输出宽度为16位, 其中有小数8位. 具体数字可以用变量代替.
sprintf(buf1, "%*.*f ", 16, 8, m_pMatrix[i][j]);
outfile.write(buf1, sizeof(buf1));
strcpy(buf1, buf2);
}
outfile.write(CrLf, sizeof(CrLf) - 1);
}

outfile.close();

return true;
}

另:
double的精度是有限的,一般能精确输出小数点后13位,你要输出16位小数肯定超出这个精度了.
比如:
double val = 100.12345678901234567890;
char str[80];
int width = 32, precision = 20;
sprintf(str, "%*.*f\n", width, precision, val);
printf(str);
输出只能是:
100.12345678901235000000

freeia 2003-07-21
  • 打赏
  • 举报
回复
楼上的楼上高人!不过有以疑问,后面输出的数据不精确啊!
freeia 2003-07-21
  • 打赏
  • 举报
回复
楼上的不行啊,编译通不过.提示语法错误!
"%.*f ",这种不行的啊.
idontlikenickname 2003-07-21
  • 打赏
  • 举报
回复


十分简单~库函数本身就有这种功能~~

char buf[80] = {0};
int nPrecision = 16;
sprintf(buf, "%.*f ", nPrecision, nDoubleValue);
其中的nPrecision是可变的,根据自己的意思来设定精度~

freeia 2003-07-21
  • 打赏
  • 举报
回复
其实我只想知道两点.
用ifstream的get() or getline()又要设计到要用streambuf()
这几个我都不熟.
我的目的:
我想得到一个文件的行数,如何处理?
还想把每一行的信息提取出来分析,用string类可以做到这一点?
我以前用mfc写的,现在想改用标准C/C++写
happycock 2003-07-21
  • 打赏
  • 举报
回复
看的我头大,我的建议是对照你的源码,将功能互换,个别标准库里没有的,另外实现,string类很强大。想想以前学C的时候,明明有个string.h,老师连个去空格都让我们自己写,结果养成一个凡是自己动手的恶习,经常想不起标准库中现成的函数。
freeia 2003-07-21
  • 打赏
  • 举报
回复
还有一问,我想得到一个文件的行数,如何处理?
还想把每一行的信息提取出来分析,用string类可以做到这一点?
我以前用mfc写的,现在想改用标准C/C++写

偶以前的代码:

bool CMatrix::LoadDataFromFile(CString& strFileName)
{
CStdioFile dataFile;
LPCTSTR lpszFileName = "";

// CString convert to LPCTSTR
strFileName.TrimLeft ();
strFileName.TrimRight ();
//strFileName.Format (lpszFileName);

lpszFileName = (LPCTSTR)strFileName;

if(!dataFile.Open (lpszFileName,CFile::modeRead | CFile::typeText))
{
::AfxMessageBox (TEXT("不能打开要读取数据的文件!"),MB_OK | MB_ICONERROR);
dataFile.Close ();
return FALSE;
}

// 用来存储提取文本文件中一行的数据
CString strData;
// 用来记录文本文件中一共有多少行数据?
unsigned int nRow = 0;

/////////////////////////////////////////////////////////////////////////
// Step 1: 得到文件的行列数目并根据文本文件的行列数目来设置对象(矩阵)的行
// 列数目
//

while(dataFile.ReadString (strData) != FALSE)
{
++nRow;
}

// 根据文本文件的数据的行数设置对象(矩阵)的行数
m_nRow = nRow;
SetMatrixRowNumber(m_nRow);

// 重新定位当前文件指针到文件开头
dataFile.SeekToBegin ();

dataFile.ReadString (strData);
strData.TrimLeft ();
strData.TrimRight ();

TCHAR SPACE_CHARACTER = ' ';
// 用来记录文本文件中一行有多少列?
unsigned int nCol = 0;

// 空格符在字符串中的位置索引
int nIndex = 0;

do
{
nIndex = strData.Find (SPACE_CHARACTER);

++nCol;

// 提取字符串的子字符串,即提取一个double型实数数据
//CString strDoubleNumber = strData.Left (nIndex);

// 将字符串转换为double型实数
//double RealNumber = atof(strDoubleNumber);

//int nTempNumber = strData.GetLength ();

strData = strData.Right (strData.GetLength () - nIndex -1);

// 去掉多余的空格
strData.TrimLeft ();

// Use for debugging
//int nTempNum = strData.GetLength ();

}while(nIndex != -1);

// 根据文本文件的数据的列数设置对象(矩阵)的列数
m_nCol = nCol;
SetMatrixColNumber(m_nCol);

// End of Getting the Rows and Cols of the Text File
/////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////
// Step 2: 根据文本文件中的数据对矩阵赋值,并检测每行的列数是否和第一行的
// 列数相等,不相等提示出错信息
//

// 重新定位当前文件指针到文件开头
dataFile.SeekToBegin ();

// 对矩阵中的元素装入文本文件的数据
for(unsigned int i=0; i < m_nRow; i++)
{
dataFile.ReadString (strData);
strData.TrimLeft ();
strData.TrimRight ();

// 验证每行的列数是否与第一行的列数相等
unsigned int nVerifyColNum = 0;

do
{
nIndex = strData.Find (SPACE_CHARACTER);

++nVerifyColNum;

if(nIndex != -1)
{
// 提取字符串的子字符串,即提取一个double型实数数据
CString strDoubleNumber = strData.Left (nIndex);

// 将字符串转换为double型实数
double RealNumber = atof(strDoubleNumber);

m_pTMatrix [i][nVerifyColNum - 1] = RealNumber;
//int nTempNumber = strData.GetLength ();

strData = strData.Right (strData.GetLength () - nIndex -1);

// 去掉多余的空格
strData.TrimLeft ();

// Using for debugging
//double nReadNumber = m_pTMatrix [i][nVerifyColNum - 1];

// Using for debugging
//int nTempNum = strData.GetLength ();
}
else
{
double RealNumber = atof(strData);

m_pTMatrix [i][nVerifyColNum - 1] = RealNumber;
}

}while(nIndex != -1);

if(nVerifyColNum != m_nCol)
{
CString strRowNumber;
strRowNumber.Format("%d",i + 1);

CString strColNumber;
strColNumber.Format("%d",m_nCol);

CString strVerifyColNumber;
strVerifyColNumber.Format("%d",nVerifyColNum);

CString strMessage = CString(TEXT("文本文件第")) + strRowNumber + CString(TEXT("行一共有")) + strVerifyColNumber + CString(TEXT("列,与第一行中的列数")) + strColNumber + CString(TEXT("不相等!"));

LPCTSTR lpszText = "";
lpszText = (LPCTSTR)strMessage;

//strMessage.FormatMessage (lpszText);
//::AfxMessageBox (lpszText,MB_OK);


::AfxMessageBox (lpszText,MB_OK | MB_ICONERROR);
dataFile.Close ();
return false;
}


}


dataFile.Close ();

return TRUE;
}
happycock 2003-07-21
  • 打赏
  • 举报
回复
合理不合理我说不上,不过你要的可编程格式我是给出解答了。如果你要输出的每种类型另外附加格式,建议将数据和输出函数封装到一起,或者将数据和输出格式封装到一起。
不过事实上没人这么做,我只是提个想法。
freeia 2003-07-21
  • 打赏
  • 举报
回复
明白你的意思.看看我的设计合理否?
happycock 2003-07-21
  • 打赏
  • 举报
回复
比如这样
char s[] = "%.16f";
printf(s,1.1);
很简单吧,只要动态的修改s的值就能改变格式,因为可以将非const赋给const,所以不需要什么转换,我上面的说法可能让你糊涂了。
freeia 2003-07-21
  • 打赏
  • 举报
回复
说明一下:
偶的代码已经实现了我想要的功能了.但我想改进一下.主要是速度和健壮性.
(编译环境BCB6.0+sp4)
happycock 2003-07-21
  • 打赏
  • 举报
回复
楼上的也不看看他的代码,一会流输入流输出,一会又printf(),看的我真是……
我来个C的实现:
不知你看过printf()的原型没有,printf(const char*,...),明白我的意思了吧,只要生成一个满足你的要求的const的字符串就可以了
freeia 2003-07-21
  • 打赏
  • 举报
回复
其实用C还是用C++关系不大的,有时候C++反而会稍微降低效率(这就是为什么系统底层用C而不用C++写的原因).
pengzhenwanli 2003-07-21
  • 打赏
  • 举报
回复
你可以使用ostringstream
你上面的做法还是C的做法。
比如说ostringstream buf;

setprecision( int size );
直接改变size就可以改变精度。
double d = 111.222;
setprecision( 10 );
buf <<d;
buf.str();
加载更多回复(3)

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧