用c语言将一个文件中的行向后复制到另一个文件中
我正在尝试以相同的权限、相同的大小、相同的所有内容复制到另一个文件(新),我这样做了,但复制内容正常,但现在尝试向后复制(新文件的最后一行是第一行),我如何计划这一点,首先获取文件的行数,如下所示:用c语言将一个文件中的行向后复制到另一个文件中,c,C,我正在尝试以相同的权限、相同的大小、相同的所有内容复制到另一个文件(新),我这样做了,但复制内容正常,但现在尝试向后复制(新文件的最后一行是第一行),我如何计划这一点,首先获取文件的行数,如下所示: while (!feof(fp)) { ch = fgetc(fp); if (ch == '\n') { lines++; } } 然后创建一个数组来放置文件中的每一行,一旦我用for for (unsigned i = n; i-- > 0;) {
while (!feof(fp)) {
ch = fgetc(fp);
if (ch == '\n') {
lines++;
}
}
然后创建一个数组来放置文件中的每一行,一旦我用for
for (unsigned i = n; i-- > 0;) {
//n is the number of lines
}
那么在这个上,对于
我写入一个文档,然后它将被向后写入,有更好的选择吗
如果是的话,你能给我举个例子吗?我不能在这里写完整的代码,因为你似乎在设计上有很多问题 但你应该能够通过以下方式做你想做的事:
read
或fread
strchr
或strtok
(更简单,但需要注意)查找所有换行符,将它们的位置存储到指针数组中(realloc
如果您不知道前面有多少行,则是您的朋友)write
或fwrite
)(您需要记住某个变量中的行数)因此,如果您希望程序尽可能正常工作,则更适合
strchr
。然而,这将稍微难以使用。最重要的是,您需要记住每次依次调用它,以便在最后一次调用它的结果之后在char上调用它,并确保对字符串的结尾执行null检查。此外,您还需要确保在将行写回时只写到下一个换行符,因为strchr
不会将它们替换为空字符。对于具有中等长度行的中等大小文件,下面是一个快速而肮脏的递归实现:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
static char buf[10000];
if (fgets(buf, sizeof(buf), stdin)) {
char *str = strdup(buf);
main();
fputs(str, stdout);
free(str);
}
return 0;
}
#包括
#包括
#包括
内部主(空){
静态字符buf[10000];
if(fgets(buf、sizeof(buf)、stdin)){
char*str=strdup(buf);
main();
fput(str、stdout);
自由基(str);
}
返回0;
}
这是一个非常简单的过滤器:它从标准输入读取文件,并将行以相反的顺序写入标准输出
现在,由于您没有进行任何编码,您的任务将是识别这种方法的潜在问题。- 将文件读入内存(如果适合…)
- 反转整个文件(按字符)
- 反转结果行中的字符
- 写文件
- 请不要重新格式化。我有权使用不同的缩进样式,我也不喜欢你的
#包括
#包括
#包括
int main(int argc,字符**argv)
{
大小\u t大小、beg、end、this、used;
char*all=NULL;
int-ch;
文件*fp;
fp=fopen(argv[1],“rb+”);
如果(!fp){
perror(“开放式失败”);
退出(退出失败);
}
fprintf(stderr,“读取文件…\n”);
用于(大小=已使用=0;1;已使用++){
ch=getc(fp);
如果(使用+1>=大小){
大小和新闻大小;
新闻大小=(大小==0)?1024:大小*2;
fprintf(stderr,“Realloc%zu这里有一种使用mmap
访问文件进行行反转的方法。对于较大的文件应该更快
我已经测试过了,它似乎可以处理大多数边缘情况
为了进一步提高速度,可以添加madvise
调用
旁注:关于\u GNU\u源代码
,很抱歉。这是为了获得memrchr
的定义。如果您的系统没有该定义,那么创建一个就足够简单了
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#define sysfault(_fmt...) \
do { \
fprintf(stderr,_fmt); \
exit(1); \
} while (0)
#ifdef DEBUG
#define dbgprt(_fmt...) fprintf(stderr,_fmt)
#else
#define dbgprt(_fmt...) /**/
#endif
typedef unsigned char byte;
typedef struct {
const char *map_file; // filename
int map_fd; // file descriptor
size_t map_siz; // file size
byte *map_base; // base of map area
byte *map_ptr; // current map pointer
size_t map_off; // current file offset
struct stat map_st; // stat syscall
} filemap;
// mapopen -- open the file
void
mapopen(filemap *map,const char *file,int mode,filemap *mapfm)
{
int prot;
int err;
memset(map,0,sizeof(filemap));
map->map_file = file;
map->map_fd = open(map->map_file,mode,0644);
if (map->map_fd < 0)
sysfault("mapopen: unable to open '%s' -- %s\n",
map->map_file,strerror(errno));
// create new file
if (mode & O_CREAT) {
map->map_siz = mapfm->map_siz;
err = ftruncate(map->map_fd,map->map_siz);
if (err < 0)
sysfault("mapopen: unable to ftruncate -- %s\n",strerror(errno));
map->map_off = 0;
}
// process existing file
else {
fstat(map->map_fd,&map->map_st);
map->map_siz = map->map_st.st_size;
map->map_off = map->map_siz - 1;
lseek(map->map_fd,map->map_off,0);
}
prot = 0;
if (mode & O_CREAT)
prot |= PROT_WRITE;
else
prot |= PROT_READ;
do {
if (map->map_siz == 0)
break;
map->map_base = mmap(NULL,map->map_siz,prot,MAP_SHARED,map->map_fd,0);
if (map->map_base == MAP_FAILED)
sysfault("mapopen: unable to map map_file='%s' map_siz=%ld -- %s\n",
map->map_file,map->map_siz,strerror(errno));
// get starting offset for file
map->map_ptr = map->map_base + map->map_off;
} while (0);
}
// mapclose -- close the file
void
mapclose(filemap *map)
{
if (map->map_base != NULL)
munmap(map->map_base,map->map_siz);
map->map_base = NULL;
if (map->map_fd >= 0)
close(map->map_fd);
map->map_fd = -1;
}
// mapreverse -- reverse copy lines in file
void
mapreverse(const char *srcfile,const char *dstfile)
{
filemap src;
filemap dst;
byte *base;
byte *prev;
byte *cur;
ssize_t lhslen;
ssize_t rawlen;
ssize_t curlen;
mapopen(&src,srcfile,O_RDONLY,NULL);
mapopen(&dst,dstfile,O_RDWR | O_CREAT,&src);
base = src.map_base;
// point past last char in file
lhslen = src.map_siz;
prev = base + lhslen;
do {
// empty file
if (lhslen <= 0)
break;
// assume file with last line that has _no_ newline
// bug out if short file
cur = prev - 1;
if (cur < base) {
dbgprt("mapreverse: SHORT\n");
break;
}
// well behaved file with newline as last char
if (*cur == '\n') {
dbgprt("mapreverse: NICE\n");
lhslen -= 1;
}
} while (0);
// copy over the bulk of the file
while (lhslen > 0) {
dbgprt("mapreverse: LOOP lhslen=%ld prev=%ld\n",lhslen,prev - base);
// locate next (i.e. "previous") line
cur = memrchr(base,'\n',lhslen);
// copy over final part
if (cur == NULL) {
dbgprt("mapreverse: FINAL\n");
break;
}
// get length of current line (including newline on left)
rawlen = prev - cur;
dbgprt("mapreverse: CURLEN cur=%ld prev=%ld rawlen=%ld\n",
cur - base,prev - base,rawlen);
// remove newline on left from copy buffer and length
curlen = rawlen - 1;
// copy current line
dbgprt("mapreverse: COPY\n");
memcpy(dst.map_ptr,cur + 1,curlen);
dst.map_ptr += curlen;
dst.map_siz -= curlen;
// cut back on the length we scan
lhslen = cur - base;
// point one past the newline we just found
prev = cur + 1;
}
// copy over final part
if (dst.map_siz > 0) {
dbgprt("mapreverse: FINAL map_siz=%ld\n",dst.map_siz);
memcpy(dst.map_ptr,base,dst.map_siz);
}
mapclose(&src);
mapclose(&dst);
}
// main -- main program
int
main(int argc,char **argv)
{
char *cp;
--argc;
++argv;
for (; argc > 0; --argc, ++argv) {
cp = *argv;
if (*cp != '-')
break;
switch (cp[1]) {
default:
break;
}
}
setlinebuf(stderr);
if (argc != 2)
sysfault("main: must have exactly two arguments\n");
mapreverse(argv[0],argv[1]);
return 0;
}
定义GNU源
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义系统故障(_fmt…)\
做{\
fprintf(标准,fmt)\
出口(1)\
}而(0)
#ifdef调试
#定义dbgprt(_fmt…)fprintf(stderr,_fmt)
#否则
#定义dbgprt(_fmt…)/**/
#恩迪夫
typedef无符号字符字节;
类型定义结构{
const char*map_file;//文件名
int map_fd;//文件描述符
size\u t map\u siz;//文件大小
byte*map_base;//映射区域的底部
byte*map_ptr;//当前映射指针
size\u t map\u off;//当前文件偏移量
struct stat map_st;//stat syscall
}文件映射;
//mapopen——打开文件
无效的
mapopen(文件映射*映射,常量字符*文件,int模式,文件映射*映射FM)
{
int-prot;
INTERR;
memset(map,0,sizeof(filemap));
映射->映射文件=文件;
map->map\u fd=open(map->map\u文件,模式,0644);
如果(映射->映射\u fd<0)
sysfault(“mapopen:无法打开'%s'--%s\n”,
map->map_文件,strerror(errno));
//创建新文件
if(模式和O_创建){
地图->地图大小=地图大小->地图大小;
err=ftruncate(映射->映射\u fd,映射->映射大小);
如果(误差<0)
sysfault(“mapopen:无法ftruncate--%s\n”,strerror(errno));
map->map\u off=0;
}
//处理现有文件
否则{
fstat(地图->地图fd和地图->地图st);
地图->地图大小=地图->地图大小;
地图->地图关闭=地图->地图大小-1;
lseek(map->map\u fd,map->map\u off,0);
}
prot=0;
if(模式和O_创建)
prot |=prot|u WRITE;
其他的
prot |=prot|u READ;
做{
如果(映射->映射大小==0)
打破
map->map\u base=mmap(NULL,map->map\u size,prot,map\u SHARED,map->map\u fd,0);
如果(地图->地图基础==M
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#define sysfault(_fmt...) \
do { \
fprintf(stderr,_fmt); \
exit(1); \
} while (0)
#ifdef DEBUG
#define dbgprt(_fmt...) fprintf(stderr,_fmt)
#else
#define dbgprt(_fmt...) /**/
#endif
typedef unsigned char byte;
typedef struct {
const char *map_file; // filename
int map_fd; // file descriptor
size_t map_siz; // file size
byte *map_base; // base of map area
byte *map_ptr; // current map pointer
size_t map_off; // current file offset
struct stat map_st; // stat syscall
} filemap;
// mapopen -- open the file
void
mapopen(filemap *map,const char *file,int mode,filemap *mapfm)
{
int prot;
int err;
memset(map,0,sizeof(filemap));
map->map_file = file;
map->map_fd = open(map->map_file,mode,0644);
if (map->map_fd < 0)
sysfault("mapopen: unable to open '%s' -- %s\n",
map->map_file,strerror(errno));
// create new file
if (mode & O_CREAT) {
map->map_siz = mapfm->map_siz;
err = ftruncate(map->map_fd,map->map_siz);
if (err < 0)
sysfault("mapopen: unable to ftruncate -- %s\n",strerror(errno));
map->map_off = 0;
}
// process existing file
else {
fstat(map->map_fd,&map->map_st);
map->map_siz = map->map_st.st_size;
map->map_off = map->map_siz - 1;
lseek(map->map_fd,map->map_off,0);
}
prot = 0;
if (mode & O_CREAT)
prot |= PROT_WRITE;
else
prot |= PROT_READ;
do {
if (map->map_siz == 0)
break;
map->map_base = mmap(NULL,map->map_siz,prot,MAP_SHARED,map->map_fd,0);
if (map->map_base == MAP_FAILED)
sysfault("mapopen: unable to map map_file='%s' map_siz=%ld -- %s\n",
map->map_file,map->map_siz,strerror(errno));
// get starting offset for file
map->map_ptr = map->map_base + map->map_off;
} while (0);
}
// mapclose -- close the file
void
mapclose(filemap *map)
{
if (map->map_base != NULL)
munmap(map->map_base,map->map_siz);
map->map_base = NULL;
if (map->map_fd >= 0)
close(map->map_fd);
map->map_fd = -1;
}
// mapreverse -- reverse copy lines in file
void
mapreverse(const char *srcfile,const char *dstfile)
{
filemap src;
filemap dst;
byte *base;
byte *prev;
byte *cur;
ssize_t lhslen;
ssize_t rawlen;
ssize_t curlen;
mapopen(&src,srcfile,O_RDONLY,NULL);
mapopen(&dst,dstfile,O_RDWR | O_CREAT,&src);
base = src.map_base;
// point past last char in file
lhslen = src.map_siz;
prev = base + lhslen;
do {
// empty file
if (lhslen <= 0)
break;
// assume file with last line that has _no_ newline
// bug out if short file
cur = prev - 1;
if (cur < base) {
dbgprt("mapreverse: SHORT\n");
break;
}
// well behaved file with newline as last char
if (*cur == '\n') {
dbgprt("mapreverse: NICE\n");
lhslen -= 1;
}
} while (0);
// copy over the bulk of the file
while (lhslen > 0) {
dbgprt("mapreverse: LOOP lhslen=%ld prev=%ld\n",lhslen,prev - base);
// locate next (i.e. "previous") line
cur = memrchr(base,'\n',lhslen);
// copy over final part
if (cur == NULL) {
dbgprt("mapreverse: FINAL\n");
break;
}
// get length of current line (including newline on left)
rawlen = prev - cur;
dbgprt("mapreverse: CURLEN cur=%ld prev=%ld rawlen=%ld\n",
cur - base,prev - base,rawlen);
// remove newline on left from copy buffer and length
curlen = rawlen - 1;
// copy current line
dbgprt("mapreverse: COPY\n");
memcpy(dst.map_ptr,cur + 1,curlen);
dst.map_ptr += curlen;
dst.map_siz -= curlen;
// cut back on the length we scan
lhslen = cur - base;
// point one past the newline we just found
prev = cur + 1;
}
// copy over final part
if (dst.map_siz > 0) {
dbgprt("mapreverse: FINAL map_siz=%ld\n",dst.map_siz);
memcpy(dst.map_ptr,base,dst.map_siz);
}
mapclose(&src);
mapclose(&dst);
}
// main -- main program
int
main(int argc,char **argv)
{
char *cp;
--argc;
++argv;
for (; argc > 0; --argc, ++argv) {
cp = *argv;
if (*cp != '-')
break;
switch (cp[1]) {
default:
break;
}
}
setlinebuf(stderr);
if (argc != 2)
sysfault("main: must have exactly two arguments\n");
mapreverse(argv[0],argv[1]);
return 0;
}