附加fwrite()而不是写入C.

时间:2015-07-11 13:14:44

标签: c fwrite

我必须编写一个程序,从一个行接收的文件读取,然后用读取的单词uppercased覆盖它。 这是我的代码

$key1 = 'a';
$key2 = 'b';
$key3 = 'c';
$array[$key1][$key2][$key3] = 'new value';

但是此程序会附加void toUpperCase(char* string) { int i=0; while(string[i]) { string[i]=toupper(string[i]); i++; } } int main(int argc, char** argv) { if(argc==1) { puts("Error: INSERT PATH"); exit(0); } char* file=argv[1]; FILE* fd=fopen(file,"r+"); if(fd<0) { perror("Error opening file: "); exit(0); } char buffer[30][30]; int i=0; while(!feof(fd)) { fscanf(fd,"%s",buffer[i]); i++; } int j=0; for(j=0; j<i; j++) { toUpperCase(buffer[j]); fwrite(buffer[j],strlen(buffer[j]),1,fd); } fclose(fd); return 0; } 中包含的单词,而不是覆盖该文件。 如果文件包含类似buffer[][]的内容,那么在执行后pippo pluto foo而不是pippo pluto fooPIPPOPLUTOFOO。 我哪里错了?谢谢

4 个答案:

答案 0 :(得分:3)

您必须使用fseek重置文件位置指示器,因为fscanf会使其前进。像

这样的东西
fseek(fd, length_of_read_string, SEEK_CUR);

这允许您以块的形式读取文件,但要做到正确将会很棘手。或者当然将其重置为文件启动,因为您在1 go中读取所有内容:

fseek(fd, 0L, SEEK_SET);

我强烈建议将修改后的数据写入新文件,然后在程序运行后删除初始文件并重命名新文件。这也将解决您的程序的另一个问题,您在处理之前将整个文件读入内存。

答案 1 :(得分:2)

如果您想进行不会改变长度的就地翻译,可以在两个流中打开源文件,然后以锁步方式执行read-chunk,write-chunk。这样做的好处是可以非常容易地转换为非就地版本,也可以使用不可搜索的文件(stdin / stdout,管道和套接字)。

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h> //toupper

inline void upcaseStr(char* str){
  for(;*str;str++) { *str=toupper(*str); }
}
int upcaseStream(FILE* in, FILE* out){
  char buf[BUFSIZ]; //BUFSIZ is an implementation-defined constant for an optimal buffer size
  while(fgets(buf, BUFSIZ, in)){
    upcaseStr(buf);
    if(fputs(buf, out) == EOF){ return 1; } 
  }
  if(!feof){ return 1; }
  return 0;
}
int main(int argc, char **argv)
{
  //default in and out
  FILE* in = stdin;
  FILE* out = stdout;

  if(argc == 2) {
    in = fopen(argv[1], "r");     //for reading
    out = fopen(argv[1], "r+");   //for writing (and reading) starting at the beginning

    if(!(in && out)){
      fprintf(stderr, "Error opening file %s for reading and writing: %s\n", argv[1], strerror(errno));
    }
  }
  return upcaseStream(in, out);
}

如果您确实使用就地版本,那么在if(fputs(buf, out) == EOF){ return 1; }行应该返回的不太可能的情况下,除非您拥有该文件的备份副本,否则您将被搞砸。 :)

注意: 你不应该为你的FILE指针fd命名,因为C会倾向于认为你的意思是&#34;文件描述符&#34;。 FILE是文件描述符周围的struct。文件描述符只是int,您可以使用原始系统调用进行FILE访问。 FILE 是文件描述符之上的抽象层 - 它们不是文件描述符。

答案 2 :(得分:0)

当您从文件中读取时,其内部位置指示器会被移动。一旦你开始写作,你就开始从那个位置开始写,这恰好在文件的末尾。因此,您可以有效地将数据附加到文件中。

在写入文件之前,回放手柄以重置位置指示器:

rewind(fp);

在旁注中,您正在错误地读取文件:

while(!feof(fd))
{
    fscanf(fd,"%s",buffer[i]);
    i++;
}

当你到达文件的末尾时,fscanf将返回错误而不会读取任何内容,但仍然会增加变量i,就像读取成功一样。然后 你检查feof()是否有文件结尾,但是i已经增加了。

在调用fscanf()后立即检查feof()返回fscanf():

while(1)
{
    int read = fscanf(fd,"%s",buffer[i]);
    if( read != 1 )
       //handle invalid read

    if( feof(fd) )
         break;
    i++;
}

考虑如果字符串长度超过29个字符和/或文件包含超过30个字符串会发生什么。 char buffer[30][30];

答案 3 :(得分:-2)

欢迎使用StackOverflow!

使用带有“w”参数的fopen重新打开流:

fd=fopen(file, "w");

它打开文件,如果文件中有任何内容,则清除它们。