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

How to reverse text in a file in C?

我试图让我的文本在该文件中从后往前阅读并以相反的顺序打印,但我的 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!");

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

第一个是你声明它 "doesn't seem to [be] working" 但没有说明你为什么这么认为。 运行 你的代码揭示了问题所在:你根本没有得到 any 输出。

原因如下。您反转字符串,因此终止零出现在新字符串的开头。然后打印该字符串——它在第一个字符处立即结束。

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

接下来,为什么不打印几个中间结果呢?这样你就可以看到发生了什么。

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

嘿,看,回车 return 似乎有问题(它在行的开头结束),这正是应该发生的事情——毕竟它是字符串的一部分– 但更有可能不是您打算做的。

除此之外,你可以清楚地看到反转本身是不正确的!

现在的问题是你正在从同一个字符串:

读取和写入
please = work[characters3];
work[r] = please;

你将末尾的字符写入位置#0,减少末尾并增加开始,重复直到完成。因此,reading/writing 的后半部分开始将 end 字符从开头复制回 end 一半!

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

你还需要多想想交换是什么意思。实际上,您的代码 覆盖了 字符串中的一个字符。要正确交换两个字符,您需要先将一个字符保存在临时变量中。

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);
}

最后一点:您不需要 'manually' 计算字符数,有一个函数可以计算字符数。代替 count 循环所需要的就是这个;

characters3 = strlen(work);

这是一个完整且注释很多的函数,它会将文件名输入现有文件,打开它,然后逐个字符地反转文件。几个 improvements/extensions 可能包括:

  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('[=10=]', 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;
}