BCB字符串处理的怪事

Jack_TT 2009-06-10 09:30:49
目的:从文件中读出字符串,该文件可以视为文本文件。

文本字符串示例:
1P5V_DUAL_PHASE_20; PR505.2 PC505.1 PL500.1 PQ502.D,
PQ500.S PJP500.1 PU501.8 PR503.2,
PC550.1

说明:该示例为一个项目,我通过判断逗号来判断是否应该读取下一行和上面的行来组成一个字符串,项目的存取通过链表实现。

BUG:我在多台计算机上测试,只有一台计算机显示字符串为:1P5V_DUAL_PHASE_20; PR505.2 PC505.1 PL500.1 PQ502.D,(错误)
其他的计算机都显示为:1P5V_DUAL_PHASE_20; PR505.2 PC505.1 PL500.1 PQ502.D, PQ500.S PJP500.1 PU501.8 PR503.2, PC550.1(正确)

问题:为什么会出现同一文件在一台计算机上的读取错误,而其他计算机又是正确的。

代码:

void __fastcall TForm1::OpenTheSecondFile1Click(TObject *Sender)
{
int i, j, length;
int x, LineCount;
char *pFileTwoContent;
AnsiString FileTwoContent;

OpenDialog1->FileName = "";
if(OpenDialog1->Execute())
{
FileTwoRichEdit->Clear();
if(OpenDialog1->FileName!="")
{
FileTwoRichEdit->Lines->LoadFromFile(OpenDialog1->FileName);
F_TwoEdit->Text = OpenDialog1->FileName;
}
}

LineCount = FileTwoRichEdit->Lines->Count; //返回文件文本行数

if(OpenDialog1->FileName!="")
{
pFileTwoNETS1 = pFileTwoNETS2 = (struct CheckContentNETS *)malloc(LENN);
for(j=0;j<50;j++)
{
pFileTwoNETS1->Name[j] = '\0';
}
pFileTwoNETSHead = pFileTwoNETS1;

for(i = 1;((FileTwoContent = FileTwoRichEdit->Lines->Strings[i])!="$END")&&(i<LineCount);i++)
{
for(;FileTwoContent == "";i++)//跳过空行
{
FileTwoContent = FileTwoRichEdit->Lines->Strings[i];
}

if(i==1)
{
pFileTwoNETSHead = pFileTwoNETS1;
}
else
{
pFileTwoNETS2->Next = pFileTwoNETS1;
}
if(FileTwoContent == "$NETS")//跳过标志行
{
i = i + 1;
FileTwoContent = FileTwoRichEdit->Lines->Strings[i];
}
pFileTwoContent = FileTwoContent.c_str();
for(j=0;*(pFileTwoContent+j) != '\0';j++)//将指针移动到一行文本末端
{}

while(*(pFileTwoContent+j-1) == ',')//判断和读取完一条完整的信息
{
i = i + 1;
FileTwoContent = FileTwoContent + FileTwoRichEdit->Lines->Strings[i];
pFileTwoContent = FileTwoContent.c_str();
for(j=0;*(pFileTwoContent+j) != '\0';j++)
{}
}//这里读取完后就可以用控件打印FileTwoContent的信息,但是就会出现上述错误

for(j=0;(*(pFileTwoContent+j) != ';')&&(*(pFileTwoContent+j)!= '\0'); j++)//读取项目名
{
pFileTwoNETS1->Name[j] = *(pFileTwoContent+j);
}

//将一条项目的文本信息包括名字全部存入链表
length = FileTwoContent.Length() + 1;
pFileTwoNETS1->Content = new char[length];
memset(pFileTwoNETS1->Content, '\0', length);
memcpy(pFileTwoNETS1->Content, pFileTwoContent, length);

pFileTwoNETS2 = pFileTwoNETS1;
pFileTwoNETS1 = (struct CheckContentNETS*)malloc(LENN);
for(j=0;j<50;j++)
{
pFileTwoNETS1->Name[j] = '\0';
}
}
pFileTwoNETS2->Next = NULL;
free(pFileTwoNETS1); // Release the null struct
MessageDlg("File Two is loaded completed!", mtInformation, mbOKCancel, 0);
}
}


...全文
79 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
ccrun.com 2009-06-10
  • 打赏
  • 举报
回复
你用十六进制编辑器打开文件,看看PQ502.D,的后面除了回车换行外,是不是有不可显字符?

另外,你说这些需求,我觉得用String的[]操作起来更方便。遍历TStrings的每一行,判断最后一个字符是否为',',伪代码:

String str;
for (int i = 0; i < RichEdit->Lines->Count; i++)
{
str = RichEdit1->Lines->Strings[i];
if (str.Length() > 0 && str[str.Length()] == ',')
....
}
Jack_TT 2009-06-10
  • 打赏
  • 举报
回复
好的,我再说下,可能刚才我说的不清楚。

1P5V_DUAL_PHASE_20; PR505.2 PC505.1 PL500.1 PQ502.D,
PQ500.S PJP500.1 PU501.8 PR503.2,
PC550.1

上面一段是需要检查文件的一项。这种文件的内容格式比较特殊,“;”前表示项目名称,后面则表示项目的内容。“,”表示这个项目的内容没有完,下面的的一行也是该项目的内容,一直直到一行没有“,”才算该项目结束。

我在上面的代码是在打开文件的时候就把文件读入一个链表(用一个char*来保存这个内容和一个char[]来保存名字),通过“,”来判断是否该项目结束。

我在我的电脑和大多数电脑上做debug,将链表的内容全部打印出来,就上面的内容来说正确的格式和内容应该是:
1P5V_DUAL_PHASE_20; PR505.2 PC505.1 PL500.1 PQ502.D, PQ500.S PJP500.1 PU501.8 PR503.2, PC550.1
除了一台电脑外其他电脑都能正确的将这些内容存入电脑。

而在一台测试电脑上却出现了错误的内容如下:
1P5V_DUAL_PHASE_20; PR505.2 PC505.1 PL500.1 PQ502.D,

而且剩下的内容: PQ500.S PJP500.1 PU501.8 PR503.2, PC550.1被存为了下一个链表中。

我之所以要读这些内容是为了接下来进行文件对比。我对比的时候是用链表进行对比的,先看项目名相等了在比较内容。在错误的内容被存入链表后根本找不到“,”所以 PQ500.S PJP500.1 PU501.8 PR503.2, PC550.1就会被认为不存在这样的错误。

另外我在出问题的电脑上检测到在 PQ500.S PJP500.1 PU501.8 PR503.2, PC550.1被读入链表后,后面会跟一串乱码。
ccrun.com 2009-06-10
  • 打赏
  • 举报
回复
你能把需求说的再详细一些吗?感觉现在的效率很低啊,也许是我理解错你的需求了?
Jack_TT 2009-06-10
  • 打赏
  • 举报
回复
debug = new char[FileTwoContent.Length()+1];
strcpy(debug, FileTwoContent.c_str());
for(j=0;*(debug+j) != '\0';j++)
{}
while(*(debug+j-1) == ',')
{
i = i + 1;
FileTwoContent = FileTwoContent + FileTwoRichEdit->Lines->Strings[i];
delete debug;
debug = new char[FileTwoContent.Length()+1];
strcpy(debug, FileTwoContent.c_str());
for(j=0;*(debug+j) != '\0';j++)
{}
}

我把逗号运算的地方改成了以上代码,但是结果还是一样。
Jack_TT 2009-06-10
  • 打赏
  • 举报
回复
了解了,谢谢!

妖哥和songhtao都来了,好感动!
ccrun.com 2009-06-10
  • 打赏
  • 举报
回复
对于String的.c_str()函数,以前的大牛们讨论过无数次了,.c_str()返回的是String内部的char *指针,这个指针是变化的。你使用这个指针进行一些读写操作,是有风险的。
我不懂电脑 2009-06-10
  • 打赏
  • 举报
回复
建议你在,出问题那台机器上单步调试,发现问题。
我不懂电脑 2009-06-10
  • 打赏
  • 举报
回复
么pFileTwoContent = FileTwoContent.c_str();存在隐患呢?
因为c_str是一片临时内存,随时可能被回收或覆盖。
Jack_TT 2009-06-10
  • 打赏
  • 举报
回复
妖哥来拉!谢谢妖哥的回复。

但是不明白为什么pFileTwoContent = FileTwoContent.c_str();存在隐患呢?
ccrun.com 2009-06-10
  • 打赏
  • 举报
回复
说实话,你的代码比较乱,我大概的看了看,至少其中存在一些隐患,类似
pFileTwoContent = FileTwoContent.c_str();
这样的代码,不建议使用。你可以使用String的[]操作符来遍历字符串,也可以开辟一个缓冲,将FileTwoContent.c_str()复制到缓冲再用C的方法遍历。
Jack_TT 2009-06-10
  • 打赏
  • 举报
回复
问题已经解决了,其实是RICHEDIT的自动换行问题,出问题的那机器的屏幕小分辨率小导致对话框变小,我又从控件里读所以出了问题。把RICHEDIT的自动换行关闭,把横向滚动条打开就可以了。

这里非常感谢妖哥和songhtao对我的帮助,今天学到了很多。

13,874

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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