This is my code. read a line and change it.
char buf[SIZE];
while (fgets(buf,SIZE,fp) != NULL)
{
to_upper(buf);
fseek(fp,-1L,SEEK_CUR);
fputs(buf,fp);
fseek(fp,1L,SEEK_CUR);
}
I know that I can create another file to implement, I want to konw why the code doesn't work?
As I noted in a comment, you need to capture the current read position before calling fgets()
; then you reset that position and write the revised data, and you need a seek of some sort after the write so that you can read again.
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void to_upper(char *buffer)
{
unsigned char u;
while ((u = *buffer) != '\0')
*buffer++ = toupper(u);
}
int main(int argc, char **argv)
{
const char *fname = "input.txt";
if (argc > 2)
{
fprintf(stderr, "Usage: %s [file]\n", argv[0]);
exit(EXIT_FAILURE);
}
if (argc == 2)
fname = argv[1];
FILE *fp = fopen(fname, "r+");
if (fp == NULL)
{
fprintf(stderr, "%s: failed to open file '%s' for read/write: %d %s\n",
argv[0], fname, errno, strerror(errno));
exit(EXIT_FAILURE);
}
char buffer[1024];
long pos = ftell(fp);
while (fgets(buffer, sizeof(buffer), fp) != 0)
{
to_upper(buffer);
fseek(fp, pos, SEEK_SET);
fputs(buffer, fp);
fseek(fp, 0, SEEK_CUR);
pos = ftell(fp);
}
fclose(fp);
return 0;
}
The error checking after the open succeeds is non-existent, but the checking before that is crucial to safe operation.
The C standard §7.21.5.3 The fopen
function ¶7 says:
When a file is opened with update mode ('
+
' as the second or third character in the above list of mode argument values), both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to thefflush
function or to a file positioning function (fseek
,fsetpos
, orrewind
), and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file.
The code shown is careful to use the 'no-op' fseek(fp, 0, SEEK_CUR)
call after the write and before the next read.