C语言字符串常用操作函数

  • C语言字符串、文件操作常用操作函数
      • 字符串输出 - puts()
      • 字符串输入 - gets()
      • 字符串比较 - strcmp()
      • 字符串复制 - strcpy()
      • 字符串连接 - strcat()
      • 字符串求长 - strlen()
      • 打开指定的文件 - fopen()
      • 文件关闭 - fclose()
      • 文件中读取块数据 - fread()
      • 向文件中写入块数据 - fwrite()
        • fread() 与 fwrite 实例
      • 将位置指针移动到文件开头 - rewind()
      • 将位置指针移动到任意位置 - fseek()
      • 从流 stream 读取格式化输入 - fscanf()
      • 发送格式化输出到流 stream 中 - fprintf()
      • 读取字符串并在字符串末尾添加‘\0’ - fgets()
        • fscanf 和 fprintf 函数实例
      • 将字符串输出到指针fp所指的文件中 - fputs()
      • 以只读或读写方式打开的文件上读字符 - fgetc()
      • 将字符c写到文件指针fp所指的文件 - fputc()
      • 将fp的文件位置指针从fromwhere开始移动offset个字节指示下一个要读取的数据的位置 - fseek()
      • 指针指向文件首字节 - rewind()
      • 读取当前文件指针的位置 - ftell()
      • 测试给定流 stream 的错误标识符 - ferror()
      • 检测流上的文件结束符 - feof()
      • 清除缓冲区的内容 - fflush()
      • 取当前文件指针位置 - ftell()
      • 文件此时的偏移量之间的大小-lseek()
    • 标准输入/输出重定向
    • 文件随机读写
    • 获取一个文件的大小
      • 使用fopen打开文件,使用fseek和ftell来获取文件的大小
      • 如果使用open打开文件,使用lseek来获取文件的大小
      • 使用stat.h
      • 只使用stdio
    • C语言的四种拷贝函数
      • 一、复制字符串 - strcpy()
      • 二、复制内存 - memcpy()
      • 三、复制内存内容 - memmove()
      • 四、复制字符串的前n个字符 - strncpy()
    • C语言插入、删除、更改文件内容
      • 文件复制
      • 文件内容插入函数
      • 文件内容删除函数
    • 文件操作补充

C语言字符串、文件操作常用操作函数

  • 字符串输出 - puts()

int puts(const char *str)
字符串写入到标准输出 stdout

  • 字符串输入 - gets()

char *gets(char *str)
标准输入 stdin 读取一行

  • 字符串比较 - strcmp()

int strcmp(const char *str1, const char *str2)
字符串进行比较

  1. 如果返回值小于 0,则表示 str1 小于 str2。
  2. 如果返回值大于 0,则表示 str1 大于 str2。
  3. 如果返回值等于 0,则表示 str1 等于 str2。
  • 字符串复制 - strcpy()

char *strcpy(char *dest, const char *src)
需要注意的是如果目标数组 dest 不够大,而源字符串的长度又太长,可能会造成缓冲溢出的情况。

  • 字符串连接 - strcat()

char *strcat(char *dest, const char *src)
指向的字符串追加到 所指向的字符串的结尾

  • 字符串求长 - strlen()

size_t strlen(const char *str)

  • 打开指定的文件 - fopen()

FILE *fopen(const char *filename, const char *mode)
fopen(文件路径,文件使用方式);

  • 文件关闭 - fclose()

fclose(文件指针)
若文件关闭成功则返回0,否则返回非0

  • 文件中读取块数据 - fread()

size_t fread ( void *ptr, size_t size, size_t count, FILE *fp );
fread(内存首地址, 数据块大小, 数据块个数, 文件指针)

  • 向文件中写入块数据 - fwrite()

size_t fwrite ( void * ptr, size_t size, size_t count, FILE *fp );
fwrite(内存首地址, 数据块大小, 数据块个数, 文件指针)

fread() 与 fwrite 实例
#include<stdio.h>
#define N 2
struct stu{char name[10]; //姓名int num;  //学号int age;  //年龄float score;  //成绩
}boya[N], boyb[N], *pa, *pb;
int main(){FILE *fp;int i;pa = boya;pb = boyb;if( (fp=fopen("d:\\demo.txt", "wb+")) == NULL ){printf("Cannot open file, press any key to exit!\n");getch();exit(1);}//从键盘输入数据printf("Input data:\n");for(i=0; i<N; i++,pa++){scanf("%s %d %d %f",pa->name, &pa->num,&pa->age, &pa->score);}//将数组 boya 的数据写入文件fwrite(boya, sizeof(struct stu), N, fp);//将文件指针重置到文件开头rewind(fp);//从文件读取数据并保存到数据 boybfread(boyb, sizeof(struct stu), N, fp);//输出数组 boyb 中的数据for(i=0; i<N; i++,pb++){printf("%s  %d  %d  %f\n", pb->name, pb->num, pb->age, pb->score);}fclose(fp);return 0;
}
//结果
Input data:
Tom 2 15 90.5↙
Hua 1 14 99↙
Tom  2  15  90.500000
Hua  1  14  99.000000
  • 将位置指针移动到文件开头 - rewind()

void rewind ( FILE *fp );

  • 将位置指针移动到任意位置 - fseek()

int fseek ( FILE *fp, long offset, int origin );
参数说明:

  1. fp 为文件指针,也就是被移动的文件。
  2. offset 为偏移量,也就是要移动的字节数。之所以为 long 类型,是希望移动的范围更大,能处理的文件更大。
  3. origin 为起始位置,也就是从何处开始计算偏移量。C语言规定的起始位置有三种,分别为文件开头、当前位置和文件末尾,每个位置都用对应的常量来表示:
起始值 常量名 常量值
文件开头 SEEK_SET 0
当前位置 SEEK_CUR 1
文件末尾 SEEK_END 2

值得说明的是,fseek() 一般用于二进制文件,在文本文件中由于要进行转换,计算的位置有时会出错。

//例如,把位置指针移动到离文件开头100个字节处:
fseek(fp, 100, 0);
  • 从流 stream 读取格式化输入 - fscanf()

int fscanf (FILE *fp, const char *format, ……);
fscanf_s(文件指针, 格式参数, 存入地址, 字节数)

  • 发送格式化输出到流 stream 中 - fprintf()

int fprintf (FILE *fp, onst char *format, ……);
fprintf(文件指针, 格式字符, 输出列表);

  • 读取字符串并在字符串末尾添加‘\0’ - fgets()

char *fgets(char *s,int n,FILE *fp);

fscanf 和 fprintf 函数实例
#include<stdio.h>
#define N 2
struct stu{char name[10];int num;int age;float score;
} boya[N], boyb[N], *pa, *pb;
int main(){FILE *fp;int i;pa=boya;pb=boyb;if( (fp=fopen("D:\\demo.txt","wt+")) == NULL ){printf("Cannot open file, press any key exit!");getch();exit(1);}//从键盘读入数据,保存到boyaprintf("Input data:\n");for(i=0; i<N; i++,pa++){scanf("%s %d %d %f", pa->name, &pa->num, &pa->age, &pa->score);   }pa = boya;//将boya中的数据写入到文件for(i=0; i<N; i++,pa++){fprintf(fp,"%s %d %d %f\n", pa->name, pa->num, pa->age, pa->score);   }//重置文件指针rewind(fp);//从文件中读取数据,保存到boybfor(i=0; i<N; i++,pb++){fscanf(fp, "%s %d %d %f\n", pb->name, &pb->num, &pb->age, &pb->score);}pb=boyb;//将boyb中的数据输出到显示器for(i=0; i<N; i++,pb++){printf("%s  %d  %d  %f\n", pb->name, pb->num, pb->age, pb->score);}fclose(fp);return 0;
}

fgets(内存首地址, 字符数, 文件指针);
最多读n-1个字符,当读到回车换行符、到达文件尾或读满n-1个字符时,就停止读取
(与gets()不同的是,fgets()从指定的流读取字符串,读到换行符时将换行符也作为字符串的一部分读到字符串中来)

  • 将字符串输出到指针fp所指的文件中 - fputs()

fputs(_In_z_ const char * _Str, _Inout_ FILE * _File);
fputs(字符串, 文件指针)
str是要输出的字符串,fp是文件指针,字符串末尾’\0’不输出
与puts()不同的是,fputs()不会在写入文件的字符串末尾加上换行符’\n’

  • 以只读或读写方式打开的文件上读字符 - fgetc()

int fgetc (FILE *fp)

  • 将字符c写到文件指针fp所指的文件 - fputc()

int fputc(int c, FILE *fp)
fputc(变量名, 文件指针)
fp是由函数fopen()返回的文件指针,c是要输出的字符(尽管C定义为int型,但只写入低字节)

  • 将fp的文件位置指针从fromwhere开始移动offset个字节指示下一个要读取的数据的位置 - fseek()

int fseek(FILE *fp,long offset,int fromwhere)
offset是一个偏移量,它告诉文件位置指针要跳过多少字节,offset为正时,向后移动,为负时,向前移动,ANSIC要求位移量offset是长整型数据(常量数据后要加L),

这样当文件的长度大于64k时不至于出问题

fromwhere用于确定偏移量计算的起始位置,它的可能取值有3种,SEEK_SET或0,代表文件开始处,SEEK_CUR或1,代表文件当前位置,SEEK_END或2,代表文件结尾处,

通过指定fromwork和offset的值,可使位置指针移动到文件的任意位置,从而实现文件的随机读取,如果函数fseek()调用成功,则返回0值,否则返回非0值

两种特殊使用方式:

将读写位置移动到文件开头:fseek(FILE *stream,0,SEEK_SET);
  将读写位置移动到文件尾:fseek(FILE *stream,0,0SEEK_END);

(fseek() 一般用于二进制文件,在文本文件中由于要进行转换,计算的位置有时会出错)

  • 指针指向文件首字节 - rewind()

void rewind(FILE *fp)

  • 读取当前文件指针的位置 - ftell()

long ftell(FILE *fp
ftell获得该文件指示符此时的偏移量,如果已经是在文件末尾,故能获得文件的大小
需要注意的是,当用err = fopen_s(&fp, “E:\ww.txt”, “a+”);打开文件后文件指针移到文件末尾,此时文件起始位置还是为文件头部并不是文件末尾)

  • 测试给定流 stream 的错误标识符 - ferror()

int ferror(FILE *stream)

  • 检测流上的文件结束符 - feof()

int feof(FILE *fp)
计算机突然死机或掉电,数据就会丢失,永远也找不回来,再如缓冲区被写入无用的数据时,如果不清除,其后的文件读操作都首先要读取这些无用的数据
为了解决这个问题C语言提供了fflush()函数

  • 清除缓冲区的内容 - fflush()

int fflush(FILE *fp)

  • 取当前文件指针位置 - ftell()

long ftell(FILE *fp)
(函数ftell()用于相对于文件起始位置的字节偏移量来表示返回的当前位置指针)

fflush(stdin);刷新标准输入缓冲区,把输入缓冲区里的东西丢弃[非标准]

fflush(stdout);刷新标准输出缓冲区,把输出缓冲区里的东西打印到标准输出设备上

fflush(NULL);将清洗所有的输出流

由于ANSIC规定函数fflush()处理输出数据流、确保输出缓冲区中的内容文件,但并未对清理输入缓冲区作出任何规定,只是部分编译器增加了此项功能,因此使用fflush(stdin)来清除缓冲区的内容,可能会带来移植性的问题

(fflush on input stream is an extension to the C standard(fflush 操作输入流是对 C 标准的扩充))

使用 fflush(stdin)是不正确的,至少是移植性不好的,因为那样的代码在一些环境下可能正常工作,但在另一些环境下则会出错,这导致程序不可移植,所以只能在写入文件的时候使用fflush

  • 文件此时的偏移量之间的大小-lseek()

例如:
long length = lseek(fd,0,SEEK_END);//回到文件的末尾,故返回的是文件的大小

标准输入/输出重定向

实际上,对于终端设备,系统会自动打开3个标准文件:标准输入、标准输出和标准错误输出,相应的,系统定义了3个特别的文件指针常数:stdin、stdout、stderr,

分别指向标准输入、标准输出和标准错误文件,这3个文件都以标准终端设备作为输入/输出对象,在默认情况下,标准输入设备时键盘,标注输出设备是屏幕

fprintf()是printf()的文件操作版,二者的差别在于fprintf()多了一个FILE *类型的参数fp,如果为其提供的第1个参数时stdout,那么它就和printf()完全一样,

同理可推广到fputc()和putchar()等其他函数,

例如:

putchar(c);和fputc(c,stdout);等价

getchar();和fgetc(stdin);等价

puts(str)和fputs(str,stdout);等价

但函数fgets()与gets()不同,从如下函数原型可知其区别在于fgets()还多了一个参数size

char *fgets(char *s,int size,FILE *stream);

char *gets(char *s);

fgets()用其第二个参数size来说明输入缓冲区的大小,使读入的字符数不能超过限定缓冲区的大小,从而达到防止缓冲区溢出攻击的目的,

假如已定义一个有32字节的缓冲区buffer[32],那么在下面两条读字符串的语句中,后者的安全性更高

gets(buffer);

fgets(buffer,sizeof(buffer),stdin);//安全性更高

虽然系统隐含的I/O是指终端设备,但其实标准输入和标准输出是可以重新定向的,操作系统可以重新定向它们到其他文件或具有文件属性的设备,只有标准错误输出不能进行一般的输出重定向,

例如,在没有显示器的主机上,把标准输出定向到打印机,各种程序不用做任何改变,输出内容就自动从打印机输出

这里用“<”表示输入重定向,用“>”表示输出重定向,例如:假设exefile时可执行程序文件名,执行该程序时,需要输入数据,现在如果要从文件file.in中读取数据,而非键盘输入,

那么在DOS命令提示符下,只要键入如下命令行即可

C:\exefile<file.in

于是exefile的标准输入就被“<”重定向到了file.in,c此时程序exefile只会专心致志地从文件file.in中读取数据,而不再理会你此后按下的任何一个按键,

再如,若键入如下命令行

C:\exefile>file.out

于是,exefile的标准输出就被“>”重定向到了文件file.out中,此时程序exefile的所有输出内容都被输出到了文件file.out中,而屏幕上没有任何显示

文件随机读写

在移动位置指针之后,就可以用前面介绍的任何一种读写函数进行读写了。由于是二进制文件,因此常用 fread() 和 fwrite() 读写。

//【示例】从键盘输入三组学生信息,保存到文件中,然后读取第二个学生的信息:
#include<stdio.h>
#define N 3
struct stu{char name[10]; //姓名int num;  //学号int age;  //年龄float score;  //成绩
}boys[N], boy, *pboys;
int main(){FILE *fp;int i;pboys = boys;if( (fp=fopen("d:\\demo.txt", "wb+")) == NULL ){printf("Cannot open file, press any key to exit!\n");getch();exit(1);}printf("Input data:\n");for(i=0; i<N; i++,pboys++){scanf("%s %d %d %f", pboys->name, &pboys->num, &pboys->age, &pboys->score);}fwrite(boys, sizeof(struct stu), N, fp);  //写入三条学生信息fseek(fp, sizeof(struct stu), SEEK_SET);  //移动位置指针fread(&boy, sizeof(struct stu), 1, fp);  //读取一条学生信息printf("%s  %d  %d %f\n", boy.name, boy.num, boy.age, boy.score);fclose(fp);return 0;
}

获取一个文件的大小

  1. 使用fopen打开文件,使用fseek和ftell来获取文件的大小

 FILE  *file = fopen(char *filename,"w+");if(file == NULL){printf("打开文件失败");return -1;}fseek(file,0,SEEK_END);//定位到文件的最后面long length  = ftell(file);//ftell获得该文件指示符此时的偏移量,此时已经是在文件末尾,故能获得文件的大小printf("%ld",length);
  1. 如果使用open打开文件,使用lseek来获取文件的大小

int fd = open(char *filename,int falgs);//这里的参数自行设置if(fd == -1){printf("文件打开失败\n");return -1;}//lseek函数成功的话,返回的是从文件开始到文件此时的偏移量之间的大小long length = lseek(fd,0,SEEK_END);//回到文件的末尾,故返回的是文件的大小printf("%ld\n",length);//输出这个文件的大小return  0;
  1. 使用stat.h

#include <sys/stat.h>
#include <stdio.h>
int main(int argc, char *args[]){struct stat sb = {0}; int fd = open("./filename.txt",O_RDONLY);fstat(fd,&sb);printf("%d",sb.st_size);//获取文件的长度
}
  1. 只使用stdio

#include <stdio.h>
long get_file_size(char *file_name){FILE *fp = NULL;if((fp = fopen(file_name,"r")) == NULL){printf("获取文件失败");return -1;}//从文件末尾偏移,偏移0位fseek(fp,0,SEEK_END);long file_size = ftell(fp);//ftell()存储当前文件描述符的读取的偏移位置,这里就是文件末尾fclose(fp);return file_size;
}
int main(int argc, char *args[]){printf("%ld",get_file_size("./filename.txt"));
}

C语言的四种拷贝函数

一、复制字符串 - strcpy()

char*strcpy(char *dest, const char *src);
【参数】dest 为目标字符串指针,src为源字符串指针。
src 和 dest 所指的内存区域不能重叠,且 dest必须有足够的空间放置 src 所包含的字符串(包含结束符NULL)。
【返回值】成功执行后返回目标数组指针 dest。
注意:如果参数 dest 所指的内存空间不够大,可能会造成缓冲溢出(bufferOverflow)的错误情况,在编写程序时需要特别留意,或者用strncpy()来取代。

//例:
#include <stdio.h>
#include <string.h>int  main  ()
{char  str1[]= "Sample string";char  str2[ 40];char  str3[ 40];strcpy  (str2,str1);strcpy  (str3, "copy successful");printf  ( "str1: %s\nstr2: %s\nstr3: %s\n",str1,str2,str3);return  0;
}

运行结果:
str1: Sample string
str2: Sample string
str3: copy successful

二、复制内存 - memcpy()

void *memcpy ( void * dest, const void * src, size_t num );
memcpy() 会复制 src 所指的内存内容的前 num 个字节到 dest所指的内存地址上。

memcpy()并不关心被复制的数据类型,只是逐字节地进行复制,这给函数的使用带来了很大的灵活性,可以面向任何数据类型进行复制。

//例:
#include  <string,h>
#include  <stdio.h>
#include  <stdlib.h>#define  N  ( 10)int  main()
{char  *p1  =  "abcde";char  *p2  =  ( char  *)malloc( sizeof( char)  *  N);char  *p3  =  ( char  *)memcpy(p2,  p1,  N);printf( "p2 = %s\np3 = %s\n",  p2,  p3);free(p2);p2  =  NULL;p3  =  NULL;system( "pause");return  0;
}

运行结果:
p2 = abcde
p3 = abcde

三、复制内存内容 - memmove()

void *memmove(void *dest, const void *src, size_t num);
memmove() 与 memcpy() 类似都是用来复制 src所指的内存内容前 num 个字节到 dest 所指的地址上。不同的是,memmove() 更为灵活,当src 和 dest所指的内存区域重叠时,memmove() 仍然可以正确的处理,不过执行效率上会比使用 memcpy()略慢些。

//例:
#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>int  main  ()
{char  str[]  =  "memmove can be very useful......";memmove  (str+ 20,str+ 15, 11);puts  (str);system( "pause");return  0;
}

运行结果:
memmove can be very very useful.

四、复制字符串的前n个字符 - strncpy()

char *strncpy(char *dest, const char *src, size_t n);
【参数说明】dest 为目标字符串指针,src 为源字符串指针。

注意:src 和 dest 所指的内存区域不能重叠,且 dest必须有足够的空间放置n个字符。使用strncpy()最安全方式是使n等于strlen(src)+1,即拷贝整个字符串,同时将’\0’追加到dest。

//例:
#include <stdio.h>
#include  <string.h>
int  main( void)
{char  dest1[ 20];char  src1[]  =  "abc";int  n1  =  3;char  dest2[ 20]  =  "********************";char  src2[]  =  "abcxyz";int  n2  =  strlen(src2)  +  1;char  dest3[ 100]  =  "http://see.xidian.edu.cn/cpp/shell/";char  src3[ 6]  =  "abcxyz";    // 没有'\0'int  n3  =  20;char  dest4[ 100]  =  "http://see.xidian.edu.cn/cpp/u/yuanma/";char  src4[]  =  "abc\0defghigk";int  n4  =  strlen(src3);strncpy(dest1,  src1,  n1);    // n1小于strlen(str1)+1,不会追加'\0'strncpy(dest2,  src2,  n2);    // n2等于strlen(str2)+1,恰好可以把src2末尾的'\0'拷贝到dest2strncpy(dest3,  src3,  n3);    // n3大于strlen(str3)+1,循环拷贝str3strncpy(dest4,  src4,  n4);    // src4中间出现'\0'printf( "dest1=%s\n",  dest1);printf( "dest2=%s, dest2[15]=%c\n",  dest2,  dest2[ 10]);printf( "dest3=%s\n",  dest3);printf( "dest4=%s, dest4[6]=%d, dest4[20]=%d, dest4[90]=%d\n",  dest4,  dest4[ 6],  dest4[ 20],  dest4[ 90]);return  0;
}

C语言插入、删除、更改文件内容

顺序文件的存储结构决定了它能够高效读取内容,但不能够随意插入、删除和修改内容。例如在文件开头插入100个字节的数据,那么原来文件的所有内容都要向后移动100个字节,这不仅是非常低效的操作,而且还可能覆盖其他文件。因此C语言没有提供插入、删除、修改文件内容的函数,要想实现这些功能,只能自己编写函数。

以插入数据为例,假设原来文件的大小为 1000 字节,现在要求在500字节处插入用户输入的字符串,那么可以这样来实现:
(1)创建一个临时文件,将后面500字节的内容复制到临时文件;
(2)将原来文件的内部指针调整到500字节处,写入字符串;
(3)再将临时文件中的内容写入到原来的文件(假设字符串的长度为100,那么此时文件内部指针在600字节处)。
删除数据时,也是类似的思路。假设原来文件大小为1000字节,名称为 demo.mp4,现在要求在500字节处往后删除100字节的数据,那么可以这样来实现:
(1)创建一个临时文件,先将前500字节的数据复制到临时文件,再将600字节之后的所有内容复制到临时文件;
(2)删除原来的文件,并创建一个新文件,命名为 demo.mp4;
(3)将临时文件中的所有数据复制到 demo.mp4。

修改数据时,如果新数据和旧数据长度相同,那么设置好内部指针,直接写入即可;如果新数据比旧数据长,相当于增加新内容,思路和插入数据类似;如果新数据比旧数据短,相当于减少内容,思路和删除数据类似。实际开发中,我们往往会保持新旧数据长度一致,以减少编程的工作量,所以我们不再讨论新旧数据长度不同的情况。

文件复制


/**
* 文件复制函数
* @param fSource 要复制的原文件
* @param offsetSource 原文件的位置偏移(相对文件开头),也就是从哪里开始复制
* @param len 要复制的内容长度,小于0表示复制offsetSource后边的所有内容
* @param fTarget 目标文件,也就是将文件复制到哪里
* @param offsetTarget 目标文件的位置偏移,也就是复制到目标文件的什么位置
* @return 成功复制的字节数
**/
long fcopy(FILE *fSource, long offsetSource, long len, FILE *fTarget, long offsetTarget)
{int bufferLen = 1024*4; // 缓冲区长度char *buffer = (char*)malloc(bufferLen); // 开辟缓存int readCount; // 每次调用fread()读取的字节数long nBytes = 0; //总共复制了多少个字节int n = 0; //需要调用多少次fread()函数int i; //循环控制变量fseek(fSource, offsetSource, SEEK_SET);fseek(fTarget, offsetTarget, SEEK_SET);if(len<0){ //复制所有内容while( (readCount=fread(buffer, 1, bufferLen, fSource)) > 0 ){nBytes += readCount;fwrite(buffer, readCount, 1, fTarget);}}else{ //复制len个字节的内容n = (int)ceil((double)((double)len/bufferLen));for(i=1; i<=n; i++){if(len-nBytes < bufferLen){ bufferLen = len-nBytes; }readCount = fread(buffer, 1, bufferLen, fSource);fwrite(buffer, readCount, 1, fTarget);nBytes += readCount;}}fflush(fTarget);free(buffer);return nBytes;
}
原文链接:https://blog.csdn.net/Neutionwei/article/details/109394920

文件内容插入函数

/**
* 向文件中插入内容
* @param fp 要插入内容的文件
* @param buffer 缓冲区,也就是要插入的内容
* @param offset 偏移量(相对文件开头),也就是从哪里开始插入
* @param len 要插入的内容长度
* @return 成功插入的字节数
**/
int finsert(FILE *fp, long offset, void *buffer, int len)
{long fileSize = fsize(fp);FILE *fpTemp; //临时文件if(offset>fileSize || offset<0 || len<0){ //插入错误return -1;}if(offset == fileSize){ //在文件末尾插入fseek(fp, offset, SEEK_SET);if(!fwrite(buffer, len, 1, fp)){return -1;}}if(offset < fileSize){ //从开头或者中间位置插入fpTemp = tmpfile();fcopy(fp, 0, offset, fpTemp, 0);fwrite(buffer, len, 1, fpTemp);fcopy(fp, offset, -1, fpTemp, offset+len);freopen(FILENAME, "wb+", fp );fcopy(fpTemp, 0, -1, fp, 0);fclose(fpTemp);}return 0;//fsize() 是在《 83-C语言获取文件大小(长度)》自定义的函数,用来获取文件大小(以字节计)。//判断数据的插入位置,如果是在文件末尾,就非常简单,直接用 fwrite() 写入即可。
//如果从文件开头或中间插入,就得创建临时文件。
//tmpfile() 函数用来创建一个临时的二进制文件,可以读取和写入数据,相当于 fopen() 函数以"wb+"方式打开文件。该临时文件不会和当前已存在的任何文件重名,并且会在调用 fclose() 后或程序结束后自动删除。
}

文件内容删除函数

int fdelete(FILE *fp, long offset, int len)
{long fileSize = getFileSize(fp);FILE *fpTemp;if(offset>fileSize || offset<0 || len<0){ //错误return -1;}fpTemp = tmpfile();fcopy(fp, 0, offset, fpTemp, 0); //将前offset字节的数据复制到临时文件fcopy(fp, offset+len, -1, fpTemp, offset); //将offset+len之后的所有内容都复制到临时文件freopen(FILENAME, "wb+", fp ); //重新打开文件fcopy(fpTemp, 0, -1, fp, 0);fclose(fpTemp);return 0;
}
//freopen() 以"w+"方式打开文件时,如果有同名的文件存在,那么先将文件内容删除,作为一个新文件对待。

文件操作补充

因为在Microsoft Visual C++ 2010 Express中使用fopen,fscanf等函数编译器会显示警告,

This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

所有在文件操作时将改用fopen_s、fscanf_s等函数

  • fopen_s()函数

函数原型:errno_t fopen_s( FILE** pFile, const char *filename, const char *mode );

pFile----文件指针将接收到打开文件指针指向的指针

infilename----文件名mode----允许访问的类型

fopen_s()打开文件成功返回0值,否则返回非0值

须定义另外一个变量errno_t err

  • fscanf_s()函数

函数原型:fscanf_s(Inout FILE * _File, In_z Scanf_s_format_string const char * _Format, …);

fscanf_s和fscanf的区别

在使用形式上fopen_s()比fopen()多使用了一个参数,第四个参数是字节数(注意长度(strlen)和字节数(sizeof)的区别)

C语言字符串、文件操作常用操作函数,相关推荐

  1. Shell脚本中字符串的一些常用操作

    Shell脚本中字符串的一些常用操作 字符串长度 ${#string}可以获得${string}的长度 例子: string='How are you' echo ${#string} # 输出结果为 ...

  2. python如何创建excel文件_Python xlrd/xlwt 创建excel文件及常用操作

    一.创建excel代码 备注:封装好了(可直接调用) """ -*- coding:utf-8 -*- @Time :2020/8/20 21:02 @Author :J ...

  3. mysql sql 字符串字段保留数字_SQL字符串以及数字常用操作汇总

    SQL字符串以及数字常用操作汇总 更新时间:2013年06月11日 09:05:12   作者: 本篇文章是对SQL字符串以及数字的常用操作进行了详细的总结与分析,需要的朋友参考下 --将字符串中从某 ...

  4. 第八章节 文件操作一 (文件夹常用操作)

    1.文件夹常用操作 1.文件夹管理是操作系统的重要组成部分,主要包括移动.复制.创建.删除等操作. 2. .NET提供了Directory类和DirectoryInfo类用于对磁盘和文件夹进行常用操作 ...

  5. c#文件夹常用操作,属性设置,遍历、压缩

    全栈工程师开发手册 (作者:栾鹏) c#教程全解 c#文件夹常用操作,属性设置,遍历.压缩 1.文件夹属性设置 c#使用设置文件夹属性,将文件夹设置为隐藏的.系统的.只读的. 测试代码 static ...

  6. python字符串、元组常用操作

    常用字符串操作函数: #Author:CGQ name="I \tam ChenGuoQiang" print(name.capitalize())#首字母大写,其他都小写 pri ...

  7. python中字符串大小写转换常用操作

    python中字符串的大小写转换操作 方法名 操作说明 upper() 把字符串中的字符全部转换为大写 lower() 把字符串中的字符全部转换为小写 swapcase() 把原字符串中的字符,大写变 ...

  8. Python之文件操作(常用操作)

    开始以下操作之前先导入import os 模块 1.获取当前文件所在的文件目录 f = os.path.dirname(__file__) print(f) 2.连接两个或更多的路径名组件 a = o ...

  9. Excel-VBA 快速上手(五、工作簿对象、Excel 文件的常用操作)

    文章目录 一.工作簿对象 1.1 获取 Excel 文件对应的工作簿对象 二.工作簿对象操作 Excel 的常见用法 2.1. 新建并打开 Excel 文件 2.2. 关闭 Excel 文件 2.3. ...

最新文章

  1. DUILIB中获取flash,webbrowser control的方法
  2. python 制作高斯mask_【趣味案例】用Python制作各种酷炫词云图,原来这么简单!...
  3. ajax 返回数据null,ajax post 返回的数据是null
  4. java----连接池C3p0使用的补充
  5. qemu+linux+x86+64,qemu以64位跟32位的方式跑busybox
  6. 历时 4 年,阿里云推出金融核心系统转型实践书
  7. Java 8 函数式编程学习笔记
  8. html打开显示脚本错误,IE浏览器显示脚本错误怎么办 IE浏览器脚本错误解决方法图文教程...
  9. Django怎么配置mysql数据库_Django如何配置mysql数据库
  10. k8s nod rc service 使用
  11. EasyUI DataGrid undefined处理
  12. 如何解决logcat TAG过长时Android studio提示错误的问题
  13. 用Python执行SQL、Excel常见任务?10个方法全搞定!
  14. 如何用c语言编码判断质数,如何用C语言筛选法判断质数
  15. oracle报03113,【案例】Oracle报错ORA-03113 ORA-15064产生原因和解决办法
  16. 微服务,软件应用开发的新纪元
  17. 中国矿业大学本科毕业设计Latex模板cumtthesis
  18. PR连接蓝牙后无声音
  19. linux下usb 驱动
  20. 甲骨文公司总裁Larry Ellison在耶鲁大学的演讲

热门文章

  1. linux服务器中JDK的安装和配置
  2. vae 实现_使用tensorflow 2和tensorflow概率实现vae的6种不同方式
  3. oracle 10046
  4. Laravel 框架调试模式开启 漏洞修复
  5. micropython做产品开发_Micropython开发实例之TPYBoard制作简易超声波测距仪
  6. OSEA视频认证,技能强国,筑梦未来技能人才培养
  7. 二、动画- animation动画
  8. oracle 建一个自增序列,Oracle中如何创建使用SEQUENCES自增序列
  9. 虹科案例|奔驰GLS车型LIN氛围灯测试
  10. 算法:递归启蒙-汉诺塔