文件分割的思路,顶者也给分!

时间:2022-03-28 21:22:38
【学生成绩信息】
      姓名:张三
  性别:男
  年龄:22

  姓名:李四
  性别:男
  年龄:21

  姓名:王丽
  性别:女
  年龄:20

    以上是文件里的内容。需要把读出文件中的所有内容,把姓名、性别、年龄里的内容存到数组中。就是说当在程序中输入查找“姓名”时,会检索出“张三、李四、王丽”。类似于数据库表中的“字段”。
    这需要用到文件分割了,需要判断文件中的空格、换行符、冒号等等了,可是怎样具体定位到呢?文件里用许多空格、换行符、冒号。
    好像许多把数据存到小型文件中的程序都会遇到这个问题的!求思路!大家帮帮忙,谢谢!

61 个解决方案

#1


VC用CString的话可以直接操作汉字,读一行,find下,然后提取要的信息。
纯C的话要先汉字编码了。

#2


fread一段(最快能度出一个学生的数据)到缓冲去,然后用strstr搜索“姓名:”把返回地址加上串长度
//修改
作参数,如pstr,然后pstr+=strlen("姓名:");
保存。
char name[10][7];
int i=0,j=0;
mystrcpy(s[i++],pstr);//把pstr的内容复制到s[i],mystrcpy需自己定义,使其遇空格结束

#3


引用 1 楼 logic0 的回复:
VC用CString的话可以直接操作汉字,读一行,find下,然后提取要的信息。
纯C的话要先汉字编码了。
读一行是把一行的内容当成了整个字符串了,这个字符串还是要分割的啊,怎样分割呢?

#4


又是数据库,帮忙顶!!!

#5


顶............

#6


up!

#7


fgets行读取,去掉前后空格,判断是否为空行。
不为空行,则进行字符串分割.
像map一样,key是分号前的值(如姓名),值为真实姓名.

#8


引用 7 楼 huanmie_09 的回复:
fgets行读取,去掉前后空格,判断是否为空行。
不为空行,则进行字符串分割.
像map一样,key是分号前的值(如姓名),值为真实姓名.
弱弱的问一句:map是什么?

#9


c++里的一个类模板。

#10


boost::regex e("(?<=姓名:)(.*)|(?<=性别:)(.*)|(?<=年龄:)(.*)");
boost::smatch m;
string line;
while(getline(fin,line)){
bool matched=boost::regex_match(line,m,e,boost::match_default);
if(matched){
     for(size_t i=0;i<m.size();++i){
        cout<<m[i];//你要的东西全在 m 里面
     }
   }
}

#11


GetPrivateProfileString (GetPrivateProfileInt)

这个函数应该能解决LZ的问题,LZ自己去百度一下用法

#12


引用 9 楼 huanmie_09 的回复:
c++里的一个类模板。
可以说下是什么类的模板吗?谢谢

#13


这个不会,我是帮顶的……

#14


可以的话希望大家给些例子!!

#15


友情帮顶下

#16


这个不会,我是帮顶的……

#17


文件分割的思路,顶者也给分!
路过,顶

#18


读取一行后,考虑一下wcstok函数(strtok的宽字符版)。

thinking..

#19


在VS中的话应该还算好处理吧,读取子字符串存入数组,然后再从数组中取值。。

#20


像你这样的,可以读取四行,就分割一次.

#21


来接点分

#22


[code=C/C++] boost::regex e("(?<=姓名:)(.*)|(?<=性别:)(.*)|(?<=年龄:)(.*)");
boost::smatch m;
string line;
while(getline(fin,line)){
bool matched=boost::regex_match(line,m,e,boost::match_default);
if(matched){
  for(size_t i=0;i<m.size();++i){
  cout<<m[i];//你要的东西全在 m 里面
  }
  }
}[/
code]

#23


顶............

#24


ding

#25


ding

#26


ding...........

#27


文件分割的思路,顶者也给分!

#28


虽然从没有涉及过,但还是帮顶!

#29


  顶............ 

#30


如果是这种小型的文件数据库存储,一般全部直接读出来,再来切分,解析成二维数组,或是hashtable
不需要考虑定位问题的
简单的来做,就是以\n来分隔一条记录,以,来分隔一个字段
形成
xxx,yyy,zzz
aaa,bbb,ccc

这有一个问题,就是如果你存储的内容中有,或是\n就会出错了
因此,这时候,你可以用特定字符,如,E_LINE表示分行,E_COMMA,表示逗号
于是,文本就成
xxxE_COMMAyyyE_COMMAzzzE_COMMAELINEaaaE_COMMAbbbE_COMMAcccE_COMMA

我有做过小型数据库,支持sql查询,原理类似于这样,不过,当然具体会复杂很多,

#31


PYTHON做就简单多了。。

#32


 

//
//=============================================
//对INI文件进行分割,默认以"="号分开,无新类
//返回分割个数
int CGkFile::IniSeparate(CStringArray* strapItemStrArr,//整行的内容数组
 CString strIgnoreToEnd,//从此字串起,忽略到行尾
 CString strSparate//分割字符串
  )
{if(fpFileRead==0)return 0;//没文件
int iNowItem=0;//各类当前项目计数
do{
CString strNewLine;
if(1==ReadUntill('\n',&strNewLine))
{fpFileRead->Seek(1,CFile::current);
if(strIgnoreToEnd!=""&&-1!=strNewLine.Find(strIgnoreToEnd))//省略
{strNewLine=strNewLine.Left(strNewLine.Find(strIgnoreToEnd));}
int iEqualMark=strNewLine.Find(strSparate);
if(iEqualMark==-1)continue;//无等号
CString strLeft=strNewLine.Left(++iEqualMark-1);
strLeft.TrimLeft();
strLeft.TrimRight();
CString strRight=strNewLine.Mid(++iEqualMark-1);
strRight.TrimLeft();
strRight.TrimRight();
strapItemStrArr->Add(strLeft);
strapItemStrArr->Add(strRight);//AfxMessageBox(strNewLine.Left(++iEqualMark-1));
}else break;
}while(1);
return iNowItem;
}

							     

#33


你文件是规范的吗?比如三行是一个块,第一行是姓名,冒号,人名,第二行和第三行是你写的。然后第4行开始是第二个块的话。
char line[20];
fgets(line,20,fp);
然后处理line,以冒号为分隔符,对字符串分隔,注意中文编码是2个字节。

#34


帮顶,学习~~~~~~~~~~~~~~~~

#35


 帮顶
 帮顶
 帮顶
 帮顶
 帮顶

#36


fread 一次读固定一块,一次读入固定一块(要求文件内容规则),然后编写一个字符串匹配算法。

#37


先来接分

#38


写入文件的时候就按照某种格式写入,然后读取时就很容易进行定位了

#39


帮顶,我学习的是纯C

#40


typdedef struct {
  char name[20];
  char gender;//如0代表男,非0代表女
  char age;
}TStudent;
不在乎空间和效率的话先定义一个大数组,然后一行行的读,逐个识别学生的三种信息后;用fread一次性读取大块数据效率会高一些,还可以根据实际需要动态创建数组。

#41


顶什么?

#42


帮顶,没时间看了,现在自身难保啊

#43


这个问题其实只要文件格式设置的好很容易就能做到,C++中重载了>>输入运算符,能自动转换类型,跳过空格,回车,制表符
下面这段代码能实现,实现方法较简单,不用进行字符串操作,希望对你有帮助
配置文件格式
person.txt
3//行数
张三 男 22
李四 男 21
王丽 女 20

代码:
#include <iostream>
#include<fstream>
#include<string>
using namespace std;

int main()
{
ifstream fin("person.txt");
if(!fin)
{
cout<<"文件打开失败"<<endl;
return 1;
}
int n=0;
fin>>n;
int a=0;
string name;
string gender;
int year;
cout<<"选择查询操作:"<<endl;
cout<<"1.姓名"<<endl;
cout<<"2.年龄"<<endl;
cout<<"3.性别"<<endl;
cin>>a;
if(a==1)
{
for(int i=0;i<n;i++)
{
fin>>name;
cout<<name<<' ';
fin>>gender;
fin>>year;
}
cout<<endl;
}
if(a==2)
{
for(int i=0;i<n;i++)
{
fin>>name;
fin>>gender;
cout<<gender<<' ';
fin>>year;
}
cout<<endl;
}
if(a==3)
{
for(int i=0;i<n;i++)
{
fin>>name;
fin>>gender;
fin>>year;
cout<<year<<' ';
}
cout<<endl;
}
fin.close();
}

#44


注意配置文件中 //行数 是标注,不要加进去

#45


看看有帮助不。纯C,没有使用第三方库。可惜估计效率比较低。


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LENGTH 20

typedef struct Student
{
    char name[MAX_LENGTH];
    char gender[3];
    int age;
} Student;


int main(void)
{
    int i = 0;
    char buf[100];
    char *tmp = NULL, *content;
    char *delim = ":";
    FILE *fp = fopen("stu.txt", "r");


    if (fp == NULL) 
    {
        printf("file error!\n");
        return -1;
    }

    fscanf(fp, "%s", buf);
    while (EOF != fscanf(fp, "%s", buf))
    {
        
        printf("%s\n", buf);
        tmp = strtok(buf, delim);
        do 
        {
            content = tmp; 
            /*printf("%s\n", tmp);*/
        } while (NULL != (tmp = strtok(NULL, delim)));
        /* 此时content指向的就是分割结果的最后一个(即字段的数据字符串)*/
        /* 后面的处理暂时我也想不起来 */
        printf("\n");
    }

    fclose(fp);
    return 0;
}

#46


补充一点
///////////////////////////
    if (fp == NULL) 
    {
        printf("file error!\n");
        return -1;
    }

     fscanf(fp, "%s", buf); //这里是跳过第一行的【学生成绩信息】
    while (EOF != fscanf(fp, "%s", buf))
    {
        
        printf("%s\n", buf);

///////////////////////////

#47


帮顶吧 文件分割的思路,顶者也给分!

#48


#include <CStdioFile.h>
..
int i=0;
CString str[M][N];
CString line;
CStdioFile file(只读打开);
file.ReadLine(line);
line.
while

#49


顶............

#50


支持楼主

#1


VC用CString的话可以直接操作汉字,读一行,find下,然后提取要的信息。
纯C的话要先汉字编码了。

#2


fread一段(最快能度出一个学生的数据)到缓冲去,然后用strstr搜索“姓名:”把返回地址加上串长度
//修改
作参数,如pstr,然后pstr+=strlen("姓名:");
保存。
char name[10][7];
int i=0,j=0;
mystrcpy(s[i++],pstr);//把pstr的内容复制到s[i],mystrcpy需自己定义,使其遇空格结束

#3


引用 1 楼 logic0 的回复:
VC用CString的话可以直接操作汉字,读一行,find下,然后提取要的信息。
纯C的话要先汉字编码了。
读一行是把一行的内容当成了整个字符串了,这个字符串还是要分割的啊,怎样分割呢?

#4


又是数据库,帮忙顶!!!

#5


顶............

#6


up!

#7


fgets行读取,去掉前后空格,判断是否为空行。
不为空行,则进行字符串分割.
像map一样,key是分号前的值(如姓名),值为真实姓名.

#8


引用 7 楼 huanmie_09 的回复:
fgets行读取,去掉前后空格,判断是否为空行。
不为空行,则进行字符串分割.
像map一样,key是分号前的值(如姓名),值为真实姓名.
弱弱的问一句:map是什么?

#9


c++里的一个类模板。

#10


boost::regex e("(?<=姓名:)(.*)|(?<=性别:)(.*)|(?<=年龄:)(.*)");
boost::smatch m;
string line;
while(getline(fin,line)){
bool matched=boost::regex_match(line,m,e,boost::match_default);
if(matched){
     for(size_t i=0;i<m.size();++i){
        cout<<m[i];//你要的东西全在 m 里面
     }
   }
}

#11


GetPrivateProfileString (GetPrivateProfileInt)

这个函数应该能解决LZ的问题,LZ自己去百度一下用法

#12


引用 9 楼 huanmie_09 的回复:
c++里的一个类模板。
可以说下是什么类的模板吗?谢谢

#13


这个不会,我是帮顶的……

#14


可以的话希望大家给些例子!!

#15


友情帮顶下

#16


这个不会,我是帮顶的……

#17


文件分割的思路,顶者也给分!
路过,顶

#18


读取一行后,考虑一下wcstok函数(strtok的宽字符版)。

thinking..

#19


在VS中的话应该还算好处理吧,读取子字符串存入数组,然后再从数组中取值。。

#20


像你这样的,可以读取四行,就分割一次.

#21


来接点分

#22


[code=C/C++] boost::regex e("(?<=姓名:)(.*)|(?<=性别:)(.*)|(?<=年龄:)(.*)");
boost::smatch m;
string line;
while(getline(fin,line)){
bool matched=boost::regex_match(line,m,e,boost::match_default);
if(matched){
  for(size_t i=0;i<m.size();++i){
  cout<<m[i];//你要的东西全在 m 里面
  }
  }
}[/
code]

#23


顶............

#24


ding

#25


ding

#26


ding...........

#27


文件分割的思路,顶者也给分!

#28


虽然从没有涉及过,但还是帮顶!

#29


  顶............ 

#30


如果是这种小型的文件数据库存储,一般全部直接读出来,再来切分,解析成二维数组,或是hashtable
不需要考虑定位问题的
简单的来做,就是以\n来分隔一条记录,以,来分隔一个字段
形成
xxx,yyy,zzz
aaa,bbb,ccc

这有一个问题,就是如果你存储的内容中有,或是\n就会出错了
因此,这时候,你可以用特定字符,如,E_LINE表示分行,E_COMMA,表示逗号
于是,文本就成
xxxE_COMMAyyyE_COMMAzzzE_COMMAELINEaaaE_COMMAbbbE_COMMAcccE_COMMA

我有做过小型数据库,支持sql查询,原理类似于这样,不过,当然具体会复杂很多,

#31


PYTHON做就简单多了。。

#32


 

//
//=============================================
//对INI文件进行分割,默认以"="号分开,无新类
//返回分割个数
int CGkFile::IniSeparate(CStringArray* strapItemStrArr,//整行的内容数组
 CString strIgnoreToEnd,//从此字串起,忽略到行尾
 CString strSparate//分割字符串
  )
{if(fpFileRead==0)return 0;//没文件
int iNowItem=0;//各类当前项目计数
do{
CString strNewLine;
if(1==ReadUntill('\n',&strNewLine))
{fpFileRead->Seek(1,CFile::current);
if(strIgnoreToEnd!=""&&-1!=strNewLine.Find(strIgnoreToEnd))//省略
{strNewLine=strNewLine.Left(strNewLine.Find(strIgnoreToEnd));}
int iEqualMark=strNewLine.Find(strSparate);
if(iEqualMark==-1)continue;//无等号
CString strLeft=strNewLine.Left(++iEqualMark-1);
strLeft.TrimLeft();
strLeft.TrimRight();
CString strRight=strNewLine.Mid(++iEqualMark-1);
strRight.TrimLeft();
strRight.TrimRight();
strapItemStrArr->Add(strLeft);
strapItemStrArr->Add(strRight);//AfxMessageBox(strNewLine.Left(++iEqualMark-1));
}else break;
}while(1);
return iNowItem;
}

							     

#33


你文件是规范的吗?比如三行是一个块,第一行是姓名,冒号,人名,第二行和第三行是你写的。然后第4行开始是第二个块的话。
char line[20];
fgets(line,20,fp);
然后处理line,以冒号为分隔符,对字符串分隔,注意中文编码是2个字节。

#34


帮顶,学习~~~~~~~~~~~~~~~~

#35


 帮顶
 帮顶
 帮顶
 帮顶
 帮顶

#36


fread 一次读固定一块,一次读入固定一块(要求文件内容规则),然后编写一个字符串匹配算法。

#37


先来接分

#38


写入文件的时候就按照某种格式写入,然后读取时就很容易进行定位了

#39


帮顶,我学习的是纯C

#40


typdedef struct {
  char name[20];
  char gender;//如0代表男,非0代表女
  char age;
}TStudent;
不在乎空间和效率的话先定义一个大数组,然后一行行的读,逐个识别学生的三种信息后;用fread一次性读取大块数据效率会高一些,还可以根据实际需要动态创建数组。

#41


顶什么?

#42


帮顶,没时间看了,现在自身难保啊

#43


这个问题其实只要文件格式设置的好很容易就能做到,C++中重载了>>输入运算符,能自动转换类型,跳过空格,回车,制表符
下面这段代码能实现,实现方法较简单,不用进行字符串操作,希望对你有帮助
配置文件格式
person.txt
3//行数
张三 男 22
李四 男 21
王丽 女 20

代码:
#include <iostream>
#include<fstream>
#include<string>
using namespace std;

int main()
{
ifstream fin("person.txt");
if(!fin)
{
cout<<"文件打开失败"<<endl;
return 1;
}
int n=0;
fin>>n;
int a=0;
string name;
string gender;
int year;
cout<<"选择查询操作:"<<endl;
cout<<"1.姓名"<<endl;
cout<<"2.年龄"<<endl;
cout<<"3.性别"<<endl;
cin>>a;
if(a==1)
{
for(int i=0;i<n;i++)
{
fin>>name;
cout<<name<<' ';
fin>>gender;
fin>>year;
}
cout<<endl;
}
if(a==2)
{
for(int i=0;i<n;i++)
{
fin>>name;
fin>>gender;
cout<<gender<<' ';
fin>>year;
}
cout<<endl;
}
if(a==3)
{
for(int i=0;i<n;i++)
{
fin>>name;
fin>>gender;
fin>>year;
cout<<year<<' ';
}
cout<<endl;
}
fin.close();
}

#44


注意配置文件中 //行数 是标注,不要加进去

#45


看看有帮助不。纯C,没有使用第三方库。可惜估计效率比较低。


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LENGTH 20

typedef struct Student
{
    char name[MAX_LENGTH];
    char gender[3];
    int age;
} Student;


int main(void)
{
    int i = 0;
    char buf[100];
    char *tmp = NULL, *content;
    char *delim = ":";
    FILE *fp = fopen("stu.txt", "r");


    if (fp == NULL) 
    {
        printf("file error!\n");
        return -1;
    }

    fscanf(fp, "%s", buf);
    while (EOF != fscanf(fp, "%s", buf))
    {
        
        printf("%s\n", buf);
        tmp = strtok(buf, delim);
        do 
        {
            content = tmp; 
            /*printf("%s\n", tmp);*/
        } while (NULL != (tmp = strtok(NULL, delim)));
        /* 此时content指向的就是分割结果的最后一个(即字段的数据字符串)*/
        /* 后面的处理暂时我也想不起来 */
        printf("\n");
    }

    fclose(fp);
    return 0;
}

#46


补充一点
///////////////////////////
    if (fp == NULL) 
    {
        printf("file error!\n");
        return -1;
    }

     fscanf(fp, "%s", buf); //这里是跳过第一行的【学生成绩信息】
    while (EOF != fscanf(fp, "%s", buf))
    {
        
        printf("%s\n", buf);

///////////////////////////

#47


帮顶吧 文件分割的思路,顶者也给分!

#48


#include <CStdioFile.h>
..
int i=0;
CString str[M][N];
CString line;
CStdioFile file(只读打开);
file.ReadLine(line);
line.
while

#49


顶............

#50


支持楼主