//从文件创建树
int CreateTreeFromFile(char fileName[], pTree& T)
{
FILE* pFile; //定义顺序表的文件指针
char str[1000]; //存放读出一行文本的字符串
char strTemp[10]; //判断是否注释行
int i = 0, j = 0;
errno_t err = fopen_s(&pFile,fileName, "r");
if (!pFile)
{
cout<<"错误:文件打开失败."<<endl ;
return false;
}
while (fgets(str, 1000, pFile) != NULL) //跳过空行和注释行
{
strLTrim(str); //删除字符串左边空格
if (str[0] == '\n') //空行,继续读取下一行
continue;
strncpy_s(strTemp, str, 2); //将str中的前两个字符拷贝到strTemp中
if (strstr(strTemp, "//") != NULL) //跳过注释行
continue;
else //非注释行、非空行,跳出循环
break;
}
//循环结束,str中应该已经是文件标识,判断文件格式
if (strstr(str, "Tree or Forest") == NULL)
{
cout<<"错误:打开的文件格式错误!"<<endl;
fclose(pFile); //关闭文件
return false;
}
//读取结点数据,到str。跳过空行
while (fgets(str, 1000, pFile) != NULL)
{
strLTrim(str); //删除字符串左边空格
if (str[0] == '\n') //空行,继续读取下一行
continue;
strncpy_s(strTemp, str, 2);
if (strstr(strTemp, "//") != NULL) //注释行,跳过,继续读取下一行
continue;
else //非空行,也非注释行,即图的顶点元素行
break;
}
//结点数据存入树的结点数组
char* ptr = NULL;
char* token = strtok_s(str, " ",&ptr);
int nNum = 0;
while (token != NULL)
{
T.node[nNum].data = *token;
T.node[nNum].parent = -1; //父结点指针初始化为-1
token = strtok_s(NULL, " ",&ptr);
nNum++;
}
//循环读取边(父子队)数据
int nP; //父结点数组下标
int nC; //子结点数组下标
elementType Nf, Ns; //父子结点对的两个结点
while (fgets(str, 1000, pFile) != NULL)
{
//删除字符串左边空格
strLTrim(str);
if (str[0] == '\n') //空行,继续读取下一行
continue;
strncpy_s(strTemp, str, 2);
if (strstr(strTemp, "//") != NULL) //注释行,跳过,继续读取下一行
continue;
char* token = strtok_s(str, " ",&ptr); //以空格为分隔符,分割一行数据,写入邻接矩阵
if (token == NULL) //分割为空串,失败退出
{
cout << "错误:读取树的边数据失败!" << endl;
fclose(pFile); //关闭文件
return false;
}
Nf = *token; //获取父结点
token = strtok_s(NULL, " ",&ptr); //读取下一个子串,即子结点
if (token == NULL) //分割为空串,失败退出
{
cout<<"错误:读取树的边数据失败!"<<endl;
fclose(pFile); //关闭文件
return false;
}
Ns = *token; //获取边的第二个结点(子结点)
//取得父结点下标
for (nP = 0; nP < nNum; nP++)
{
if (T.node[nP].data == Nf) //从顶点列表找到第一个顶点的编号
break;
}
//获取子结点的数组下标
for (nC = 0; nC < nNum; nC++)
{
if (T.node[nC].data == Ns) //从顶点列表找到第二个顶点的编号
break;
}
T.node[nC].parent = nP; //nC的父结点的下标为nP
}
T.n = nNum; //树的结点数,即顶点数组的实际大小
fclose(pFile); //关闭文件
return true;
}
//二叉树数据文件
//二叉树标识--BinaryTree,无此标识将判定文件格式不对。
//每行表示二叉树中的一个结点。由3项组成:
//第一项是结点元素值;
//第二项表示此结点有无左子树,其中:1--有左子树,0--无左子树;
//第三项表示此结点有无右子树,其中:1--有右子树,0--无右子树。
//结点次序(从上到下)必须严格按照先序遍历次序排列。
//文件扩展名没有限制,程序只根据标识“BinaryTree”判定是否二叉树数据文件。
//文件中可以有空行。
//文件可以有注释行,注释行必须以“//”开始,且注释行必须是单独的行,不能混杂在标识行、数据行中
//此二叉树有10个结点
BinaryTree
A 1 1
B 1 1
C 0 0
D 1 0
E 0 0
F 1 1
G 0 1
H 0 0
I 1 0
J 0 0
# 从文件创建树
def CreateTreeFromFile(fileName, pTree):
# 打开文件
pFile = open(fileName, 'r')
if not pFile:
return False
# 读取文件内容
pText = pFile.read()
pFile.close()
# 解析文件内容
pToken = pText.split()
pNode = {}
pNode['label'] = pToken[0]
pNode['children'] = []
# 遍历文件内容,创建节点
for i in range(1, len(pText)):
if pText[i] == '(':
pNode['children'].append({'label': pToken[i+1], 'children': []})
pNode = pNode['children'][-1]
elif pText[i] == ')':
pNode['children'].pop()
pNode = pNode['children'][-1]
else:
# 判断是否注释行
if i > 0 and pText[i] == '/' and pText[i-1] == '/':
continue
# 判断是否非空行
if i > 0 and pText[i] != ' ':
continue
# 如果是注释行,跳过
if pText[i] == '/' and pText[i-1] == '/':
continue
# 如果是非空行,跳过
if pText[i] != ' ':
continue
# 处理节点,返回节点对象
return pNode
# 测试代码
tree = CreateTreeFromFile('data.txt', pTree)
print(tree)
不知道你这个问题是否已经解决, 如果还没有解决的话:可能的原因有很多,以下是一些常见的:
文件格式与读取函数不匹配。最好检查一下文件格式是否正确,以及读取函数是否能正确解析该格式的文件。如果文件格式不正确,则需要修改文件格式或重新编写读取函数以支持该格式。
文件损坏。如果文件被损坏,那么读取函数可能无法正确解析该文件,导致出现文件格式错误。可以尝试使用其他文件查看器或文件恢复软件来查找并恢复损坏的文件。
文件编码问题。某些文件可能使用非 ASCII 编码,这可能导致读取函数识别为格式错误。在这种情况下,您需要使用适当的编解码器来正确解析文件。
文本编辑器问题。有时候,文件可能看起来正确,但有些文本编辑器可能会在保存时改变某些字符,这可能导致读取函数无法正确解析文件。尝试使用其他文本编辑器或将文件转换为二进制文件来解决该问题。
针对这些常见的问题,我给出了一些常见的解决方案,但具体取决于您的具体情况。更好地理解您的问题,您可以提供更多的代码,错误消息以及文件示例。