如何反转 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 可能包括:
- 添加参数以调整允许的最大缓冲区大小。
- 当输入文件超出原始内存时,动态增加缓冲区大小。
- 添加将反转字符写回文件时出现错误时恢复原始内容的策略。
// 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;
}
我试图让我的文本在该文件中从后往前阅读并以相反的顺序打印,但我的 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 可能包括:
- 添加参数以调整允许的最大缓冲区大小。
- 当输入文件超出原始内存时,动态增加缓冲区大小。
- 添加将反转字符写回文件时出现错误时恢复原始内容的策略。
// 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;
}