我有一个包含以下文字的文字文件,没有换行符......
Hello World
我想将小写字符转换为大写字母,反之亦然,以便相同的文本文件最终会显示以下文字......
hELLOW wORLD
不幸的是,当我运行我的代码时,它会进入无限循环。当我逐步执行代码时,我看到fseek()返回第一个循环的一个字节,正如预期的那样,但它会返回第二个和后续循环的两个字节。我不明白为什么它会返回两个字节而不是一个字节。为什么会这样?有人可以帮忙吗?
这是我的代码......
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main()
{
FILE *fp;
int ch;
long offset;
fp = fopen("c:\\users\\domenic\\desktop\\test.txt", "r+");
if (fp == NULL)
{
printf("error: unable to open file\n");
exit(1);
}
offset = ftell(fp);
while (1)
{
ch = fgetc(fp);
if (ch == EOF)
break;
if (isupper(ch))
{
fseek(fp, offset, SEEK_SET);
fputc(tolower(ch), fp);
}
else if (islower(ch))
{
fseek(fp, offset, SEEK_SET);
fputc(toupper(ch), fp);
}
offset = ftell(fp);
}
fclose(fp);
return 0;
}
答案 0 :(得分:1)
如果我了解您只想在整个文件中将 upper 更改为 lower 并将 lower 更改为 upper ,你可能会让自己变得比你需要的更难。
在我们研究一种让事情变得更容易的方法之前,让我们谈谈在代码中避免幻数和硬编码路径。 C为main
提供了一个定义,允许您为代码提供参数以避免硬编码值(例如文件/路径名) - 使用它们。使用参数正确调用main
是:
int main (int argc, char *argv[])
(或者您会看到等效的int main (int argc, char **argv)
)
不带参数的调用是int main (void)
。
现在回答手头的问题。正如我在评论中所提到的,在处理ASCII时,控制案例的位是第6位 - 从讨论中,如果你正在处理EBCDIC,那么* case-bit {{ 1}} A ^ a is the 7th-bit. As @chux pointed out both can be handled seamlessly by determining the appropriate bit
32 for both (the result is
(1 <&lt; 5), e.g.
64 for ASCII, and
(1 <&lt; 6)or
( A-Za-z)for EBCDIC. To toggle any bit on/off you simply XOR the *case-bit* with the current character
'c'. So far any character
A ^ a`,例如
, you wish to toggle the case of, you simply XOR it with
如果if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))
c ^= A ^ a;
为大写,则现在为小写,反之亦然。
为整个文件执行此操作,将文件名转换为程序的第一个参数(如果没有给出参数,则默认从c
读取)并输出生成的case转换为{{ 1}},你可以做一些简单的事情:
stdin
示例输入
stdout
示例使用/输出
#include <stdio.h>
int main (int argc, char **argv) {
int c;
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
while ((c = fgetc(fp)) != EOF) /* read each char */
/* is it a letter ? */
if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))
putchar (c ^ ('A' ^ 'a')); /* toggle case */
else
putchar (c); /* just output */
if (fp != stdin) fclose (fp); /* close file if not stdin */
return 0;
}
如果要将输出写入新文件,只需重定向输出,例如
$ cat dat/captnjack.txt
This is a tale
Of Captain Jack Sparrow
A Pirate So Brave
On the Seven Seas.
将case转换的输出写入$ ./bin/case_toggle < dat/captnjack.txt
tHIS IS A TALE
oF cAPTAIN jACK sPARROW
a pIRATE sO bRAVE
oN THE sEVEN sEAS.
。
仔细看看,如果您有其他问题,请告诉我。
答案 1 :(得分:0)
首先,在使用fseek返回1个字符后,fputc不会删除或更像是“插入”。
在这种情况下,你是:
退出无限循环后,你的文本文件中可能会有很多hEEEEEEEEEEEEEEEEEE?
为了解决这个问题,我会创建一个临时的新文件......就像这样:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main()
{
FILE *fp, *new_f;
int ch;
long offset;
fp = fopen("test.txt", "r+");
new_f = fopen("test2.txt", "w" );
if ( fp == NULL || new_f == NULL )
{
printf("error: unable to open file\n");
exit(1);
}
offset = ftell(fp);
while (1)
{
ch = fgetc(fp);
if (ch == EOF)
break;
if( !isalpha( ch ) )
{
fputc( ch, new_f );
}
else if (isupper(ch))
{
fputc(tolower(ch), new_f );
}
else if (islower(ch))
{
fputc(toupper(ch), new_f);
}
}
fclose( fp );
fclose( new_f );
return 0;
}