文件读取问题

flcnrcn 2020-03-30 10:30:25
读取一个文本文件,如何实现读到分号时换行,并删除文本文件中的空格和空行。 例原文件格式为 :abc;空格efg; 空行,空行可能有多行。 hij;空格klm; 读取后的文件变为: abc; efg; hij; klm;
...全文
655 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
this_is_life_a 2020-04-17
  • 打赏
  • 举报
回复
我有个简单的思路,你那个字符中间是没有空格的,首先读文本,然后根据分号来split拆分成数组,循环数组,判断每个数组的trim看长度是否为0,不为0进行每个数组的trim加分号打印输出,但是这种情况只能用于字符间没有空格才行
苏大强太强了 2020-04-16
  • 打赏
  • 举报
回复
String,然后.find,找到了自己加一个换行。最好就是一个字符一个字符读,遇到分号清空,换行。
yukint 2020-04-03
  • 打赏
  • 举报
回复
最后补充一下,文本编辑器做的工作也和printf类似,你可以认为文本编辑器挨个字节读取 比如文件头3个字节存了"1" "2" "7"这3个字符,文件的内在表示其实是3个二进制字节 49(00‭10 1000‬), 50(0011 0010‬), 55 (0011 0111‬) 简单化的想法,假设你的显示器屏幕背后有127个机关(按键)每个按键上贴了数字贴纸,上面写着数字1到127, 对照ascii码表,你摁下49,屏幕显示1,摁下50显示2,摁下55显示7,3个同时摁,显示127, ==文本编辑器挨个接通了按键49, 50, 55,于是你在屏幕上看到了127 ……
yukint 2020-04-03
  • 打赏
  • 举报
回复
这个解释起来,一大堆东西,重点就是,在计算机世界没有文本文件。 所谓文本文件,只是从该文件的解读者(文本编辑器)来说的,其实不管你怎么写 他都是在写二进制,只不过经过封装,有些人喜欢把这种行为人为的贴上标签,说写文本文件。 文本只是人的认知分别,最直接了当的是用记事本这种“文本编辑器”,你直接打开,就可以看到里面是一行行人可读的文字 因为记事本就是这么一个专用的工具,他用以下呆板的方式解释文件(为了是使windows记事本足够呆,我们可以把记事本编码格式设置成ascii): 记事本读文件的每一个字节,然后输出到屏幕。(当然这里的输出类似于调用printf("%c", ch), 自己脑补一下就好了,再细节就要看屏幕的驱动xxxxx各种知识,点到即止) (当然utf-8编码的时候,可能多个二进制字节代表一个字,比如看到第一个字节ascii码(二进制值大于128),具体可以去查相关资料,不懂也不妨碍理解所谓文本文件的概念) ============================================= 所以总的来说,所谓文本文件,简单粗暴的想法就是,用记事本打开,人能直接看懂是文字的,大家称为文本文件, 这里有个前提,就是用记事本打开,不然文件是啥?肉眼能看吗?不能,linux或者windows系统,命令行里只能看到个文件名。 你看不出他到底是什么,再来界面版本的,windows只是简单根据后缀名,还有你选择固定用什么程序打开他,给该文件换个图标而已。 ==================================== 最后说正经的,回到怎么写文件的问题,文件接口(frwite, fprintf)这些,其实并没有谁给他们标签,说哪个是文本文件的接口, 哪个是二进制文件的接口,设计这个接口人没有这么说。只是有时候脑袋里的错误认知给他们安上标签了。 先从这个例子开始 int i = 127; printf("%d", i); 1.请问屏幕输出是什么?很简单,127,很愉快是不是 2.再问计算机的内部表示是什么?0000 0000 0000 11111111(为了简单直观起见,直接用二进制,而不是一般情况下的补码表示法) 3.printf输出是我们想要的吗?是的,因为我们就想看i代表的整数是多少,而不是看他躺在内存/文件中的二进制形式。 4.这里的printf是不是有点像文本编辑器的功能,他实际做了什么呢?一种实现的猜测, a)他把i %10, 即除以10取余数,得到7(个位) b)i/10, 得到12, 12 %10, 得到2(10位) c)b中得到的12 / 10,==》1,1 % 10 ==》1(百位), d)1 /10 ==>0高位是0了,结束,这个0不用管了,0127,0不要 5.简单化的想法,假设你的显示器屏幕背后有127个机关(按键)每个按键上贴了数字贴纸,上面写着数字1到127, 对照ascii码表,你摁下49,屏幕显示1,摁下50显示2,摁下55显示7,3个同时摁,显示127, ==》为了人眼能看的127,得这么麻烦,原来不就是个i=127吗,我知道他是127呀,可是在内存里,表示的是二进制的01位串 再来看这个语句 int i = 127; fprintf(fp, "%d", i); <==上面的语句有什么作用?啊啊,这个我懂,这个就是写文本文件啊,我知道我知道。 我前面说了那么多,白说了~~~~!不要有这种思想,没有写文本文件这种东西,抛弃掉这种思想。 说这种话会混淆你自己,还显得你外行。(开玩笑的,我并不想以高姿态自居,一种也曾经被愚弄的自嘲) 可是可是,为啥我用这样两个语句去操作一个文件,然后用记事本打开就没有乱码,屏幕上看到的是127, 这不就是写文本文件吗, 还说不是?,他到底玩了什么魔法? ==》你要这么说,我也没办法,你被他的魔法骗了。你要这么认为,所以才造就了你提的问题,你的困惑,不是吗? ~~~~~ 实质上,正如我们前面简单分析了printf的例子,其实他是把这个数拆成1,2, 7然后把这3个的ascii值以二进制的形式写到文件中去了 3个字节 等效于 char a1 = 49; // 字符‘1’的asscii值 char a2 = 50;// char a3 = 55; // '7' fwrite(&a1, 1, 1, fp); fwrite(&a2, 1, 1, fp); fwrite(&a3, 1, 1, fp); ~~~~~~~~~~~~~~~ 最后,你知道,内存里表示是二进制0001111这种二进制串,文件(硬盘)又何尝不是呢, 你不要臆想着h, a, b,c ,2, 7这种东西会飞进你的 文件/硬盘之中, 记住,计算机的原始世界只有0和1,000111010101,就连你硬盘里存的小电影也不例外,全是0和1 --最后的最后,解释这种魔楞问题,真的太费劲了,这也是我害怕解答的原因。 如果你还没想明白你提的那个问题, 字符,,,其实也是ascii,去百度一下ascii码,比如字符‘A’用65表示,他和前面提到的字符‘1’用40表示 有太大的本质区别吗?你打开文本文件看到一个字符'A',本质上他是65的二进制表示,读到内存中 char ch = 65; char ch = 'A'; 两者是一样的,那么写回去 fwrite(&ch, 1, 1, fp);他还是65 还是'A'对不 至于int i = 127; fwrite(&i, 4, 1, fp);你都知道第二参数里是4,表示把整形的4个字节都写进去。跟之前讲的fprintf的本质对比一下 明白了吗?
flcnrcn 2020-04-02
  • 打赏
  • 举报
回复
引用 9 楼 yukint的回复:
测试换行的时候,读取文件,没有重置文件位置指针 加上这行就好了fseek(fp, 0L, SEEK_SET);

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

/*行转化, 返回目标长度,返回0表示本行不用处理,一般是空行,或者空格+换行
返回>0表示转换后的长度,(可能变成多行)*/
int line_transfer(char *src, char *dst, const char *newline)
{
        int i = 0;
        int j = 0;
        while(src[i] == ' ' || src[i] == '\t'){   //去掉行的前导空白 
            i++;
        }
        if(src[i] == newline[0])  //此时i==0则是空行,否则是前面一些空格,然后换行,(还是相当于空行)
            return 0;   //跳过该行继续读下一行

        int add_newline = 0;
        while(src[i] != 0)
        {
            if(src[i] == ';' && src[i] != *newline){		//注意如果本身就是;之后跟换行,则不处理,
                dst[j++] = src[i++];
                strcpy(dst+j, newline); //把换行写进去
                j += strlen(newline);
            }else if(src[i] == ' ' || src[i] == *newline){
                i++;
            }else{
                dst[j++] = src[i++];
            }
        }
        return j;       //转换后j的长度
}
const char *get_newline_str(FILE *fp)
{
    char buf[4096];
    char *retbuf = fgets(buf, sizeof(buf), fp);
    if(retbuf == NULL){
        printf("empty file \n");
        return NULL;
    }
	fseek(fp, 0L, SEEK_SET);
    int len = strlen(buf);
    /*这里假设文件单行不会超过4093字节,不然就有问题
    buf[len]是字符串结束符0,fgets函数自动加上去的*/
    if(buf[len - 1] == '\n'){
        if(buf[len - 2] == '\r'){
            return "\r\n";
        }
        else{
            return "\n";
        }

    }else{
        printf("unknown newline format, may be not a txt file\n");
        return NULL;
    }
}
/*windows 文本文件换行是"\r\n", unix是'\n',
windows环境传入'\r', unix 则传入'\n'*/
int format_file(const char *pathname)
{
    char *tmp = "tmp_proc00000";
    FILE *fpsrc = fopen(pathname, "r");
    FILE *fpdst = fopen(tmp, "a+");
    if(!fpsrc || !fpdst){
        printf("failed to open file");
        return -1;
    }
    
    const char *newline_str = get_newline_str(fpsrc);
    if(newline_str == NULL){
        return -1;
    }
    char bufr[4096];    //for read
    char bufw[4096];    //for write
    char *retbuf; 
    while((retbuf = fgets(bufr, sizeof(bufr), fpsrc)) != NULL)
    {
        int ret_len = line_transfer(bufr, bufw, newline_str);
        if(ret_len > 0){
            fwrite(bufw, 1, ret_len, fpdst);
        }
    }
    fclose(fpsrc);
    fclose(fpdst);
    remove(pathname);
    rename(tmp, pathname);
}

void print_file(const char *fname)
{
    FILE *fp = fopen(fname, "r");
    if(!fp){
        printf("failed to open %s\n", fname);
        return ;
    }
    char buf[1024];
    char *retbuf;
    while((retbuf = fgets(buf, sizeof(buf), fp)) != NULL){
        printf("%s", buf);
    }
    printf("\n");
}
int main()
{
    char fname[256];
    printf("Enter file name you want to transfer\n");
    scanf("%s", fname);
    format_file(fname);
    print_file(fname);

    return 0;
}

兄弟在么,能否回答下fwrite函数的问题
flcnrcn 2020-04-01
  • 打赏
  • 举报
回复
引用 9 楼 yukint的回复:
测试换行的时候,读取文件,没有重置文件位置指针 加上这行就好了fseek(fp, 0L, SEEK_SET);

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

/*行转化, 返回目标长度,返回0表示本行不用处理,一般是空行,或者空格+换行
返回>0表示转换后的长度,(可能变成多行)*/
int line_transfer(char *src, char *dst, const char *newline)
{
        int i = 0;
        int j = 0;
        while(src[i] == ' ' || src[i] == '\t'){   //去掉行的前导空白 
            i++;
        }
        if(src[i] == newline[0])  //此时i==0则是空行,否则是前面一些空格,然后换行,(还是相当于空行)
            return 0;   //跳过该行继续读下一行

        int add_newline = 0;
        while(src[i] != 0)
        {
            if(src[i] == ';' && src[i] != *newline){		//注意如果本身就是;之后跟换行,则不处理,
                dst[j++] = src[i++];
                strcpy(dst+j, newline); //把换行写进去
                j += strlen(newline);
            }else if(src[i] == ' ' || src[i] == *newline){
                i++;
            }else{
                dst[j++] = src[i++];
            }
        }
        return j;       //转换后j的长度
}
const char *get_newline_str(FILE *fp)
{
    char buf[4096];
    char *retbuf = fgets(buf, sizeof(buf), fp);
    if(retbuf == NULL){
        printf("empty file \n");
        return NULL;
    }
	fseek(fp, 0L, SEEK_SET);
    int len = strlen(buf);
    /*这里假设文件单行不会超过4093字节,不然就有问题
    buf[len]是字符串结束符0,fgets函数自动加上去的*/
    if(buf[len - 1] == '\n'){
        if(buf[len - 2] == '\r'){
            return "\r\n";
        }
        else{
            return "\n";
        }

    }else{
        printf("unknown newline format, may be not a txt file\n");
        return NULL;
    }
}
/*windows 文本文件换行是"\r\n", unix是'\n',
windows环境传入'\r', unix 则传入'\n'*/
int format_file(const char *pathname)
{
    char *tmp = "tmp_proc00000";
    FILE *fpsrc = fopen(pathname, "r");
    FILE *fpdst = fopen(tmp, "a+");
    if(!fpsrc || !fpdst){
        printf("failed to open file");
        return -1;
    }
    
    const char *newline_str = get_newline_str(fpsrc);
    if(newline_str == NULL){
        return -1;
    }
    char bufr[4096];    //for read
    char bufw[4096];    //for write
    char *retbuf; 
    while((retbuf = fgets(bufr, sizeof(bufr), fpsrc)) != NULL)
    {
        int ret_len = line_transfer(bufr, bufw, newline_str);
        if(ret_len > 0){
            fwrite(bufw, 1, ret_len, fpdst);
        }
    }
    fclose(fpsrc);
    fclose(fpdst);
    remove(pathname);
    rename(tmp, pathname);
}

void print_file(const char *fname)
{
    FILE *fp = fopen(fname, "r");
    if(!fp){
        printf("failed to open %s\n", fname);
        return ;
    }
    char buf[1024];
    char *retbuf;
    while((retbuf = fgets(buf, sizeof(buf), fp)) != NULL){
        printf("%s", buf);
    }
    printf("\n");
}
int main()
{
    char fname[256];
    printf("Enter file name you want to transfer\n");
    scanf("%s", fname);
    format_file(fname);
    print_file(fname);

    return 0;
}

你好!临时文件是用fwrite函数写的数据,此函数是以二进制形式对文件操作的,为什么用文本编辑器打开后是文本而不是乱码呢?谢谢!!!
flcnrcn 2020-03-31
  • 打赏
  • 举报
回复
引用 10 楼 coo135 的回复:
你这种情况,直接格式化读入然后输出就好了啊~~

#include <iostream>
#include <fstream> 
#include <string>
#include <vector>

using namespace std;
int main () {
	string s;
	vector<string> v;
	//读 
	ifstream in("1.txt");
	while(in>>s)
		v.push_back(s);
	in.close();
	//写 
	ofstream out("1.txt");
	for(vector<string>::iterator it=v.begin();it!=v.end();++it)
		out<<*it<<'\n';
	return 0;
}
兄弟你这个只能处理第一行。
coo135 2020-03-31
  • 打赏
  • 举报
回复
你这种情况,直接格式化读入然后输出就好了啊~~

#include <iostream>
#include <fstream> 
#include <string>
#include <vector>

using namespace std;
int main () {
	string s;
	vector<string> v;
	//读 
	ifstream in("1.txt");
	while(in>>s)
		v.push_back(s);
	in.close();
	//写 
	ofstream out("1.txt");
	for(vector<string>::iterator it=v.begin();it!=v.end();++it)
		out<<*it<<'\n';
	return 0;
}
yukint 2020-03-31
  • 打赏
  • 举报
回复
测试换行的时候,读取文件,没有重置文件位置指针 加上这行就好了fseek(fp, 0L, SEEK_SET);

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

/*行转化, 返回目标长度,返回0表示本行不用处理,一般是空行,或者空格+换行
返回>0表示转换后的长度,(可能变成多行)*/
int line_transfer(char *src, char *dst, const char *newline)
{
        int i = 0;
        int j = 0;
        while(src[i] == ' ' || src[i] == '\t'){   //去掉行的前导空白 
            i++;
        }
        if(src[i] == newline[0])  //此时i==0则是空行,否则是前面一些空格,然后换行,(还是相当于空行)
            return 0;   //跳过该行继续读下一行

        int add_newline = 0;
        while(src[i] != 0)
        {
            if(src[i] == ';' && src[i] != *newline){		//注意如果本身就是;之后跟换行,则不处理,
                dst[j++] = src[i++];
                strcpy(dst+j, newline); //把换行写进去
                j += strlen(newline);
            }else if(src[i] == ' ' || src[i] == *newline){
                i++;
            }else{
                dst[j++] = src[i++];
            }
        }
        return j;       //转换后j的长度
}
const char *get_newline_str(FILE *fp)
{
    char buf[4096];
    char *retbuf = fgets(buf, sizeof(buf), fp);
    if(retbuf == NULL){
        printf("empty file \n");
        return NULL;
    }
	fseek(fp, 0L, SEEK_SET);
    int len = strlen(buf);
    /*这里假设文件单行不会超过4093字节,不然就有问题
    buf[len]是字符串结束符0,fgets函数自动加上去的*/
    if(buf[len - 1] == '\n'){
        if(buf[len - 2] == '\r'){
            return "\r\n";
        }
        else{
            return "\n";
        }

    }else{
        printf("unknown newline format, may be not a txt file\n");
        return NULL;
    }
}
/*windows 文本文件换行是"\r\n", unix是'\n',
windows环境传入'\r', unix 则传入'\n'*/
int format_file(const char *pathname)
{
    char *tmp = "tmp_proc00000";
    FILE *fpsrc = fopen(pathname, "r");
    FILE *fpdst = fopen(tmp, "a+");
    if(!fpsrc || !fpdst){
        printf("failed to open file");
        return -1;
    }
    
    const char *newline_str = get_newline_str(fpsrc);
    if(newline_str == NULL){
        return -1;
    }
    char bufr[4096];    //for read
    char bufw[4096];    //for write
    char *retbuf; 
    while((retbuf = fgets(bufr, sizeof(bufr), fpsrc)) != NULL)
    {
        int ret_len = line_transfer(bufr, bufw, newline_str);
        if(ret_len > 0){
            fwrite(bufw, 1, ret_len, fpdst);
        }
    }
    fclose(fpsrc);
    fclose(fpdst);
    remove(pathname);
    rename(tmp, pathname);
}

void print_file(const char *fname)
{
    FILE *fp = fopen(fname, "r");
    if(!fp){
        printf("failed to open %s\n", fname);
        return ;
    }
    char buf[1024];
    char *retbuf;
    while((retbuf = fgets(buf, sizeof(buf), fp)) != NULL){
        printf("%s", buf);
    }
    printf("\n");
}
int main()
{
    char fname[256];
    printf("Enter file name you want to transfer\n");
    scanf("%s", fname);
    format_file(fname);
    print_file(fname);

    return 0;
}

flcnrcn 2020-03-31
  • 打赏
  • 举报
回复
引用 6 楼 yukint的回复:
1按行处理,假设文件test.txt,把文件读出来,写到临时文件 2删掉文件test.txt 3把临时文件重命名为test.txt
#include <stdio.h>
#include <string.h>

/*行转化, 返回目标长度,返回0表示本行不用处理,一般是空行,或者空格+换行
返回>0表示转换后的长度,(可能变成多行)*/
int line_transfer(char *src, char *dst, const char *newline)
{
        int i = 0;
        int j = 0;
        while(src[i] == ' ' || src[i] == '\t'){   //去掉行的前导空白 
            i++;
        }
        if(src[i] == newline[0])  //此时i==0则是空行,否则是前面一些空格,然后换行,(还是相当于空行)
            return 0;   //跳过该行继续读下一行

        int add_newline = 0;
        while(src[i] != 0)
        {
            if(src[i] == ';' && src[i] != *newline){		//注意如果本身就是;之后跟换行,则不处理,
                dst[j++] = src[i++];
                strcpy(dst+j, newline); //把换行写进去
                j += strlen(newline);
            }else if(src[i] == ' ' || src[i] == *newline){
                i++;
            }else{
                dst[j++] = src[i++];
            }
        }
        return j;       //转换后j的长度
}
const char *get_newline_str(FILE *fp)
{
    char buf[4096];
    char *retbuf = fgets(buf, sizeof(buf), fp);
    if(retbuf == NULL){
        printf("empty file \n");
        return NULL;
    }

    int len = strlen(buf);
    /*这里假设文件单行不会超过4093字节,不然就有问题
    buf[len]是字符串结束符0,fgets函数自动加上去的*/
    if(buf[len - 1] == '\n'){
        if(buf[len - 2] == '\r'){
            return "\r\n";
        }
        else{
            return "\n";
        }

    }else{
        printf("unknown newline format, may be not a txt file\n");
        return NULL;
    }
}
/*windows 文本文件换行是"\r\n", unix是'\n',
windows环境传入'\r', unix 则传入'\n'*/
int format_file(const char *pathname)
{
    char *tmp = "tmp_proc00000";
    FILE *fpsrc = fopen(pathname, "r");
    FILE *fpdst = fopen(tmp, "a+");
    if(!fpsrc || !fpdst){
        printf("failed to open file");
        return -1;
    }
    
    const char *newline_str = get_newline_str(fpsrc);
    if(newline_str == NULL){
        return -1;
    }
    char bufr[4096];    //for read
    char bufw[4096];    //for write
    char *retbuf; 
    while((retbuf = fgets(bufr, sizeof(bufr), fpsrc)) != NULL)
    {
        int ret_len = line_transfer(bufr, bufw, newline_str);
        if(ret_len > 0){
            fwrite(bufw, 1, ret_len, fpdst);
        }
    }
    fclose(fpsrc);
    fclose(fpdst);
    remove(pathname);
    rename(tmp, pathname);
}

void print_file(const char *fname)
{
    FILE *fp = fopen(fname, "r");
    if(!fp){
        printf("failed to open %s\n", fname);
        return ;
    }
    char buf[1024];
    char *retbuf;
    while((retbuf = fgets(buf, sizeof(buf), fp)) != NULL){
        printf("%s", buf);
    }
    printf("\n");
}
int main()
{
    char fname[256];
    printf("Enter file name you want to transfer\n");
    scanf("%s", fname);
    format_file(fname);
    print_file(fname);

    return 0;
}
你好!还有点缺陷会删除abc;和efg;就是删除了第一行内容
flcnrcn 2020-03-31
  • 打赏
  • 举报
回复
引用 6 楼 yukint的回复:
1按行处理,假设文件test.txt,把文件读出来,写到临时文件 2删掉文件test.txt 3把临时文件重命名为test.txt
#include <stdio.h>
#include <string.h>

/*行转化, 返回目标长度,返回0表示本行不用处理,一般是空行,或者空格+换行
返回>0表示转换后的长度,(可能变成多行)*/
int line_transfer(char *src, char *dst, const char *newline)
{
        int i = 0;
        int j = 0;
        while(src[i] == ' ' || src[i] == '\t'){   //去掉行的前导空白 
            i++;
        }
        if(src[i] == newline[0])  //此时i==0则是空行,否则是前面一些空格,然后换行,(还是相当于空行)
            return 0;   //跳过该行继续读下一行

        int add_newline = 0;
        while(src[i] != 0)
        {
            if(src[i] == ';' && src[i] != *newline){		//注意如果本身就是;之后跟换行,则不处理,
                dst[j++] = src[i++];
                strcpy(dst+j, newline); //把换行写进去
                j += strlen(newline);
            }else if(src[i] == ' ' || src[i] == *newline){
                i++;
            }else{
                dst[j++] = src[i++];
            }
        }
        return j;       //转换后j的长度
}
const char *get_newline_str(FILE *fp)
{
    char buf[4096];
    char *retbuf = fgets(buf, sizeof(buf), fp);
    if(retbuf == NULL){
        printf("empty file \n");
        return NULL;
    }

    int len = strlen(buf);
    /*这里假设文件单行不会超过4093字节,不然就有问题
    buf[len]是字符串结束符0,fgets函数自动加上去的*/
    if(buf[len - 1] == '\n'){
        if(buf[len - 2] == '\r'){
            return "\r\n";
        }
        else{
            return "\n";
        }

    }else{
        printf("unknown newline format, may be not a txt file\n");
        return NULL;
    }
}
/*windows 文本文件换行是"\r\n", unix是'\n',
windows环境传入'\r', unix 则传入'\n'*/
int format_file(const char *pathname)
{
    char *tmp = "tmp_proc00000";
    FILE *fpsrc = fopen(pathname, "r");
    FILE *fpdst = fopen(tmp, "a+");
    if(!fpsrc || !fpdst){
        printf("failed to open file");
        return -1;
    }
    
    const char *newline_str = get_newline_str(fpsrc);
    if(newline_str == NULL){
        return -1;
    }
    char bufr[4096];    //for read
    char bufw[4096];    //for write
    char *retbuf; 
    while((retbuf = fgets(bufr, sizeof(bufr), fpsrc)) != NULL)
    {
        int ret_len = line_transfer(bufr, bufw, newline_str);
        if(ret_len > 0){
            fwrite(bufw, 1, ret_len, fpdst);
        }
    }
    fclose(fpsrc);
    fclose(fpdst);
    remove(pathname);
    rename(tmp, pathname);
}

void print_file(const char *fname)
{
    FILE *fp = fopen(fname, "r");
    if(!fp){
        printf("failed to open %s\n", fname);
        return ;
    }
    char buf[1024];
    char *retbuf;
    while((retbuf = fgets(buf, sizeof(buf), fp)) != NULL){
        printf("%s", buf);
    }
    printf("\n");
}
int main()
{
    char fname[256];
    printf("Enter file name you want to transfer\n");
    scanf("%s", fname);
    format_file(fname);
    print_file(fname);

    return 0;
}
你好!还有点缺陷会删除abc;和efg;就是删除了第一行内容
yukint 2020-03-31
  • 打赏
  • 举报
回复
1按行处理,假设文件test.txt,把文件读出来,写到临时文件 2删掉文件test.txt 3把临时文件重命名为test.txt
#include <stdio.h>
#include <string.h>

/*行转化, 返回目标长度,返回0表示本行不用处理,一般是空行,或者空格+换行
返回>0表示转换后的长度,(可能变成多行)*/
int line_transfer(char *src, char *dst, const char *newline)
{
        int i = 0;
        int j = 0;
        while(src[i] == ' ' || src[i] == '\t'){   //去掉行的前导空白 
            i++;
        }
        if(src[i] == newline[0])  //此时i==0则是空行,否则是前面一些空格,然后换行,(还是相当于空行)
            return 0;   //跳过该行继续读下一行

        int add_newline = 0;
        while(src[i] != 0)
        {
            if(src[i] == ';' && src[i] != *newline){		//注意如果本身就是;之后跟换行,则不处理,
                dst[j++] = src[i++];
                strcpy(dst+j, newline); //把换行写进去
                j += strlen(newline);
            }else if(src[i] == ' ' || src[i] == *newline){
                i++;
            }else{
                dst[j++] = src[i++];
            }
        }
        return j;       //转换后j的长度
}
const char *get_newline_str(FILE *fp)
{
    char buf[4096];
    char *retbuf = fgets(buf, sizeof(buf), fp);
    if(retbuf == NULL){
        printf("empty file \n");
        return NULL;
    }

    int len = strlen(buf);
    /*这里假设文件单行不会超过4093字节,不然就有问题
    buf[len]是字符串结束符0,fgets函数自动加上去的*/
    if(buf[len - 1] == '\n'){
        if(buf[len - 2] == '\r'){
            return "\r\n";
        }
        else{
            return "\n";
        }

    }else{
        printf("unknown newline format, may be not a txt file\n");
        return NULL;
    }
}
/*windows 文本文件换行是"\r\n", unix是'\n',
windows环境传入'\r', unix 则传入'\n'*/
int format_file(const char *pathname)
{
    char *tmp = "tmp_proc00000";
    FILE *fpsrc = fopen(pathname, "r");
    FILE *fpdst = fopen(tmp, "a+");
    if(!fpsrc || !fpdst){
        printf("failed to open file");
        return -1;
    }
    
    const char *newline_str = get_newline_str(fpsrc);
    if(newline_str == NULL){
        return -1;
    }
    char bufr[4096];    //for read
    char bufw[4096];    //for write
    char *retbuf; 
    while((retbuf = fgets(bufr, sizeof(bufr), fpsrc)) != NULL)
    {
        int ret_len = line_transfer(bufr, bufw, newline_str);
        if(ret_len > 0){
            fwrite(bufw, 1, ret_len, fpdst);
        }
    }
    fclose(fpsrc);
    fclose(fpdst);
    remove(pathname);
    rename(tmp, pathname);
}

void print_file(const char *fname)
{
    FILE *fp = fopen(fname, "r");
    if(!fp){
        printf("failed to open %s\n", fname);
        return ;
    }
    char buf[1024];
    char *retbuf;
    while((retbuf = fgets(buf, sizeof(buf), fp)) != NULL){
        printf("%s", buf);
    }
    printf("\n");
}
int main()
{
    char fname[256];
    printf("Enter file name you want to transfer\n");
    scanf("%s", fname);
    format_file(fname);
    print_file(fname);

    return 0;
}
宇来风满楼 2020-03-30
  • 打赏
  • 举报
回复
先读最后写的时候加endl就行
flcnrcn 2020-03-30
  • 打赏
  • 举报
回复
打错原文件中的内容不包括:
flcnrcn 2020-03-30
  • 打赏
  • 举报
回复
自己在顶。。。。。。。。。。。。。。。。。
flcnrcn 2020-03-30
  • 打赏
  • 举报
回复
没有大神吗??没有大神吗?
flcnrcn 2020-03-30
  • 打赏
  • 举报
回复
自己顶一下!!!!!!!!!!

64,652

社区成员

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

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