2011-09-06 114 views
0

该程序想要从文件读取。该文件中的内容是字符串“Hello,world”。然后判断字符串的每个字符,以查看字符是否大于或等于常量字符'e',如果字符符合条件,则按字母顺序将字符更改为其前一个字符(例如,'b'更改到'一','E'改为'D')。最后,将更改的文件内容输出到屏幕上。同时在一个流中使用fread和fwrite导致问题

问题是,fwrite和fread是如何工作的?为什么我不能摆脱变量pos2来简化表达式。如果有人能帮忙,非常感谢!

#include <stdio.h> 

int main() 

{ 
    FILE *fp; 
    char s[20]; 
    char t[20]; 
    char transfer; 
    int i; 
    int pos; // storing the position of the file before reading from the file 
    int pos1; // check the position of the file 
    int pos2; // storing the position of the file after reading from the file 
#pragma region create a file named "Hello", write "Hello, world" into the file, close it 
    if ((fp = fopen("Hello", "wb"))== NULL) 
    { 
     printf("can't open file\n"); 
     exit(0); 
    } 
    strcpy(s, "Hello, world"); 
    fwrite(s, sizeof(char)*20, 1, fp); 
    fseek(fp, 0, SEEK_SET); 
    fclose(fp); 
#pragma endregion create a file named "Hello", write "Hello, world" into the file, close it 
#pragma region read from the file named "Hello", deal with its current, write the change into the file. 
    if ((fp = fopen("Hello", "rb+")) == NULL) 
    { 
      printf("can't open file\n"); 
      exit(1); 
    } 
    i = 0; 
    while(i < 20) 
    { 
      // 提问,该处为何不能利用fwrite的自动定位免去注释掉的语句行(即使用了pos2的语句行)。 
      // Here is the problem. since the fread and fwrite function can move the position of the 
      // file, I think I can get rid off the following commented two sentences with the 
      // variable pos2 in it 
      pos = ftell(fp);  // storing the position before reading from file 
      fread(&transfer, sizeof(char), 1, fp); // the position of the file moved to the next char 
      // pos2 = ftell(fp); // storing the position after reading from file 
      pos1 = ftell(fp); 
      if (transfer >= 'e') // if the character greater or equal to 'e' minus 1. 
      { 
       transfer -= 1; 
      } 
      fseek(fp, pos, SEEK_SET); // back to the position where the character is read to change the char 
      fwrite(&transfer, sizeof(char), 1, fp);// the position of the file moved to the next char 
      // fseek(fp, pos2, SEEK_SET); // 
      pos1 = ftell(fp); 
      i++; 
    } 
    fseek(fp, 0, SEEK_SET); 
    fclose(fp); 
#pragma endregion read from the file named "Hello", deal with its current, write the change into the file. 
#pragma region read from the file named "Hello", output the changed string 
    if((fp = fopen("Hello", "rb")) == NULL) 
    { 
      printf("Can't open file\n"); 
      exit(2); 
    } 
    fread(t, sizeof(char)*20, 1, fp); 
    printf("The output is: %s \n", t); 
// the right output is (the two sentences above with pos2 in it is commented) : 
// The output is: Hdkkn,vnqkd 
// the wrong output is (the two sentences above with pos2 in it isn't commented): 
// The output is: Hddddddddddddddddddd烫烫烫烫Hello, world 
    fseek(fp, 0, SEEK_SET); 
    fclose(fp); 
#pragma endregion read from the file named "Hello", output the changed string 
    system("pause"); 
} 
+0

您最初将20个字节写入文件,但's'变量仅用13个字符进行初始化。其他7个垃圾 - 应该考虑的东西。由于书写也提高了文件的位置,所以你需要存储pos2的标记(但是你可以完成'fseek(fp,pos1,SEEK_SET)'而不是'fseek(fp,pos2,SEEK_SET)') – nos

+0

是的,你是对。我只希望人们可以轻松阅读代码。变量pos1的使用是显示文件位置。从文件读取后,pos2用于存储文件的位置,以便我可以返回到该位置。结果证明我认为在从文件中读取时可能有一个指针来推进文件,并且在写入文件时有另一个指针来推进它。我没有经验,我静态分配了字符串的长度来存储文件的内容。 – toolchainX

+0

@Vicky感谢您的格式化。既然这是我第一次使用这个网站,我会在这里做的更好。 – toolchainX

回答

0

我并没有真正明白为什么你想要评论这两条线。因为无论你评论他们还是评论他们,什么都不会改变。你已经摆脱了你的代码中的pos2(这是你问的)。

所以,如果你使用下面的代码为while循环

pos = ftell(fp);  // storing the position before reading from file 
fread(&transfer, sizeof(char), 1, fp); 
pos1 = ftell(fp); 
if (transfer >= 'e') // if the character greater or equal to 'e' minus 1. 
{ 
    transfer -= 1; 
} 
fseek(fp, pos, SEEK_SET); 
fwrite(&transfer, sizeof(char), 1, fp); 
i++; 

然后你拿“的输出是:Hdkkn,vnqkd”,这是预期的结果。

你也可以从文件中的每一行读取数组并对其进行操作,然后将其写回到文件中。通过这种方式,它可以是更通用的,你不必使用像“20”这样的幻数。

编辑:

我用gcc 4.5.2在我的Linux平台。我不想在其他平台上发表评论,但正如我之前提到的,您可以将该行放入缓冲区,然后在操作后将其写回。你可以尝试用你的while循环替换下面的代码:

char line[20] = {0}; 

fread(line, sizeof(char), 20, fp); 

for(i = 0; i < strlen(line); i++) 
{ 
    if(line[i] >= 'e') 
     line[i] -= 1; 
} 

fseek(fp, 0, SEEK_SET); 
fwrite(line, sizeof(char), strlen(line), fp); 

通过这种方式,你可以摆脱许多变量。这是你的选择。

+0

感谢您的帮助。在我的编译器(vs 2008)中,如果我没有像上面那样使用变量pos2,我得到的结果是Hdddddddddddddddddddd烫烫烫烫你好,世界。然后我改变了一个编译器(MinGW中的gcc)。比我得到这样的结果:Hddddddddddddddddddd你好,世界。最后我想在linux(cc编译器)中试用它。我得到了正确的答案(不使用变量pos2):Hdkkn,vnqkd。我不知道它是否是编译器中的错误。我想知道你使用的是什么编译器? – toolchainX

+0

您也可以在Windows平台上实际失败的地方调试程序。请分享它我不知道为什么。 –

+0

您对代码的更改有效。但是我只是想知道为什么我的代码没有变量'pos2'无法工作,当我调试代码时,发生了一些事情:变量'transfer'首先得到一个值'H',因为'H'小于'e'什么都没有改变。然后'transfer'得到一个等于'e'的值'e',然后转移的值变成'd'。在下面的迭代中,在负运算之前'transfer'的值总是'e',然后在操作之后它变为'd'。在文件位置的操纵中一定有错误。但我无法弄清楚。 – toolchainX