如何在C中反转文件中的文本?

时间:2016-12-09 23:49:44

标签: c file reverse

我试着让我的文字被回读到前面并在该文件中以相反的顺序打印,但我的for循环似乎没有工作。另外我的while循环计算999个字符,即使它应该是800和某些东西(不能完全记住),我想这可能是因为两段之间有一条空行,但那时再没有字符。

这是我的两个循环的代码 - :

/*Reversing the file*/
char please;
char work[800];
int r, count, characters3;

characters3 = 0;
count = 0;
r = 0;
fgets(work, 800, outputfile);

while (work[count] != NULL)
{
characters3++;
count++;
}

printf("The number of characters to be copied is-: %d", characters3);

for (characters3; characters3 >= 0; characters3--)
{
please = work[characters3];
work[r] = please;
r++;
}
 fprintf(outputfile, "%s", work);


/*Closing all the file streams*/
fclose(firstfile);
fclose(secondfile);
fclose(outputfile);
/*Message to direct the user to where the files are*/
printf("\n Merged the first and second files into the output file 
and reversed it! \n Check the outputfile text inside the Debug folder!");

2 个答案:

答案 0 :(得分:3)

您的代码中存在一些巨大的概念缺陷。

第一个问题是,你说“似乎没有工作”而没有说出你为什么这么认为。只需运行代码就会发现问题所在:您根本没有任何输出。

这就是原因。你反转你的字符串,所以终止零点出现在新字符串的开头。然后打印该字符串 - 它会立即在第一个字符处结束。

通过减少characters3中的循环开始来解决此问题。

接下来,为什么不打印一些中间结果?这样你就可以发生了什么。

string: [This is a test.
]
The number of characters to be copied is-: 15
result: [
.tset aa test.
]

嘿看,回车似乎有问题(它最终在行的开头),这正是应该发生的事情 - 毕竟,它是字符串的一部分 - 但更可能不是什么你打算做什么。

除此之外,您可以清楚反转本身不正确!

现在的问题是您正在使用相同的字符串进行读写:

please = work[characters3];
work[r] = please;

您将角色最后写入位置#0,减少结束并增加开始,然后重复直到完成。因此,读/写的后半部分开始将结束字符从开始复制到结束一半再次!

两个可能的修复:1。从一个字符串读取并写入一个新字符串,或2.调整循环以便在“一半”完成后停止复制(因为您正在进行两次交换每次迭代,你只需要循环一半字符数。)

您还需要更多地考虑交换的含义。实际上,您的代码会覆盖字符串中的字符。要正确交换两个字符,您需要先将一个字符保存在临时变量中。

void reverse (FILE *f)
{
    char please, why;
    char work[800];
    int r, count, characters3;

    characters3 = 0;
    count = 0;
    r = 0;
    fgets(work, 800, f);

    printf ("string: [%s]\n", work);

    while (work[count] != 0)
    {
        characters3++;
        count++;
    }
    characters3--; /* do not count last zero */
    characters3--; /* do not count the return */

    printf("The number of characters to be copied is-: %d\n", characters3);

    for (characters3; characters3 >= (count>>1); characters3--)
    {
        please = work[characters3];
        why = work[r];
        work[r] = please;
        work[characters3] = why;
        r++;
    }
    printf ("result: [%s]\n", work);
}

作为最后一点:您不需要“手动”计算字符数,有一个功能。所有需要而不是count循环就是这个;

characters3 = strlen(work);

答案 1 :(得分:0)

这是一个完整且大量注释的函数,它将文件名接收到现有文件中,打开它,然后一个字符一个字符地反转文件。一些改进/扩展可能包括:

  1. 添加一个参数来调整允许的最大缓冲区大小。
  2. 随着输入文件超过原始内存,动态增加缓冲区大小。
  3. 添加一个策略,用于在将反转字符写回文件时出现问题时恢复原始内容。
// naming convention of l_ for local variable and p_ for pointers
// Returns 1 on success and 0 on failure 
int reverse_file(char *filename) {
    FILE *p_file = NULL;

    // r+ enables read & write, preserves contents, starts pointer p_file at beginning of file, and will not create a
    // new file if one doesn't exist. Consider a nested fopen(filename, "w+") if creation of a new file is desired.
    p_file = fopen(filename, "r+");
    // Exit with failure value if file was not opened successfully
    if(p_file == NULL) {
        perror("reverse_file() failed to open file.");
        fclose(p_file);
        return 0;
    }

    // Assumes entire file contents can be held in volatile memory using a buffer of size l_buffer_size * sizeof(char)
    uint32_t l_buffer_size = 1024;
    char l_buffer[l_buffer_size]; // buffer type is char to match fgetc() return type of int

    // Cursor for moving within the l_buffer
    int64_t l_buffer_cursor = 0;

    // Temporary storage for current char from file
    // fgetc() returns the character read as an unsigned char cast to an int or EOF on end of file or error.
    int l_temp;

    for (l_buffer_cursor = 0; (l_temp = fgetc(p_file)) != EOF; ++l_buffer_cursor) {
        // Store the current char into our buffer in the original order from the file
        l_buffer[l_buffer_cursor] = (char)l_temp; // explicitly typecast l_temp back down to signed char
        // Verify our assumption that the file can completely fit in volatile memory <= l_buffer_size * sizeof(char)
        // is still valid. Return an error otherwise.
        if (l_buffer_cursor >= l_buffer_size) {
            fprintf(stderr, "reverse_file() in memory buffer size of %u char exceeded. %s is too large.\n",
                    l_buffer_size, filename);
            fclose(p_file);
            return 0;
        }
    }

    // At the conclusion of the for loop, l_buffer contains a copy of the file in memory and l_buffer_cursor points
    // to the index 1 past the final char read in from the file. Thus, ensure the final char in the file is a
    // terminating symbol and decrement l_buffer_cursor by 1 before proceeding.
    fputc('\0', p_file);
    --l_buffer_cursor;

    // To reverse the file contents, reset the p_file cursor to the beginning of the file then write data to the file by
    // reading from l_buffer in reverse order by decrementing l_buffer_cursor.
    // NOTE: A less verbose/safe alternative to fseek is: rewind(p_file);
    if ( fseek(p_file, 0, SEEK_SET) != 0 ) {
       return 0;
    }

    for (l_temp = 0; l_buffer_cursor >= 0; --l_buffer_cursor) {
        l_temp = fputc(l_buffer[l_buffer_cursor], p_file); // write buffered char to the file, advance f_open pointer
        if (l_temp == EOF) {
            fprintf(stderr, "reverse_file() failed to write %c at index %lu back to the file %s.\n",
                    l_buffer[l_buffer_cursor], l_buffer_cursor, filename);
        }
    }
    fclose(p_file);
    return 1;
}