我正在为学校编写一个程序,要求从文件中读取文本,将所有内容都大写,并删除标点符号和空格。文件" Congress.txt"包含
(国会不得制定任何关于宗教信仰或禁止自由行使的法律;或者剥夺言论自由或新闻自由;或者人民和平集会的权利,以及向政府请愿对申诉的补救。)
它正确读入但我到目前为止删除标点符号,空格和大小写会导致垃圾字符的一些主要问题。到目前为止我的代码是:
void processFile(char line[]) {
FILE *fp;
int i = 0;
char c;
if (!(fp = fopen("congress.txt", "r"))) {
printf("File could not be opened for input.\n");
exit(1);
}
line[i] = '\0';
fseek(fp, 0, SEEK_END);
fseek(fp, 0, SEEK_SET);
for (i = 0; i < MAX; ++i) {
fscanf(fp, "%c", &line[i]);
if (line[i] == ' ')
i++;
else if (ispunct((unsigned char)line[i]))
i++;
else if (islower((unsigned char)line[i])) {
line[i] = toupper((unsigned char)line[i]);
i++;
}
printf("%c", line[i]);
fprintf(csis, "%c", line[i]);
}
fclose(fp);
}
我不知道这是否是一个问题,但我将MAX定义为272,因为该文本文件包含标点符号和空格。
我得到的输出是:
C╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠Press any key to continue . . .
答案 0 :(得分:6)
基本算法需要遵循:
while next character is not EOF
if it is alphabetic
save the upper case version of it in the string
null terminate the string
将C转换为:
int c;
int i = 0;
while ((c = getc(fp)) != EOF)
{
if (isalpha(c))
line[i++] = toupper(c);
}
line[i] = '\0';
此代码不需要使用(unsigned char)
中的函数进行<ctype.h>
强制转换,因为c
保证包含EOF(在这种情况下它不会进入正文无论如何,转换为unsigned char
的字符的值。使用char c
时(例如问题中的代码中)并尝试编写toupper(c)
或isalpha(c)
时,您只需担心演员表。问题是普通char
可以是签名类型,因此一些字符,众所周知ÿ(y-umlaut,U + 00FF,带有DIAERESIS的LATIN SMALL LETTER),将显示为负值,并打破了对<ctype.h>
函数输入的要求。此代码将尝试对已经大写的字符进行大小写转换,但这可能比第二次测试便宜。
你在打印等方面做了什么,取决于你。 csis
文件流是全局范围变量;那有点(tr)icky。您应该使用换行符终止输出打印。
显示的代码容易受到缓冲区溢出的影响。如果line
的长度为MAX
,则可以将循环条件修改为:
while (i < MAX - 1 && (c = getc(fp)) != EOF)
如果是更好的设计,则将功能签名更改为:
void processFile(int size, char line[]) {
并声称尺寸严格为正:
assert(size > 0);
然后循环条件变为:
while (i < size - 1 && (c = getc(fp)) != EOF)
显然,你也改变了电话:
char line[4096];
processFile(sizeof(line), line);
答案 1 :(得分:1)
在发布的代码中,没有中间处理, 所以下面的代码忽略了&#39;行[]&#39;输入参数
void processFile()
{
FILE *fp = NULL;
if (!(fp = fopen("congress.txt", "r")))
{
printf("File could not be opened for input.\n");
exit(1);
}
// implied else, fopen successful
unsigned int c; // must be integer so EOF (-1) can be recognized
while( EOF != (c =(unsigned)fgetc(fp) ) )
{
if( (isalpha(c) || isblank(c) ) && !ispunct(c) ) // a...z or A...Z or space
{
// note toupper has no effect on upper case characters
// note toupper has no effect on a space
printf("%c", toupper(c));
fprintf(csis, "%c", toupper(c));
}
}
printf( "\n" );
fclose(fp);
} // end function: processFile
答案 2 :(得分:0)
好的,我所做的就是创建了第二个字符数组。我的第一个数组读入整个文件。我创建了第二个数组,它只接受第一个数组中的字母字符,然后将它们设为大写。我的作业部分的正确和完整功能如下:
void processFile(char line[], char newline[]) {
FILE *fp;
int i = 0;
int j = 0;
if (!(fp = fopen("congress.txt", "r"))) { //checks file open
printf("File could not be opened for input.\n");
exit(1);
}
line[i] = '\0';
fseek(fp, 0, SEEK_END); //idk what they do but they make it not crash
fseek(fp, 0, SEEK_SET);
for (i = 0; i < MAX; ++i) { //reads the file into the first array
fscanf(fp, "%c", &line[i]);
}
for (i = 0; i < MAX; ++i) {
if (isalpha(line[i])){ //if it's an alphabetical character
newline[j] = line[i]; //read into new array
newline[j] = toupper(newline[j]); //makes that letter capitalized
j++;
}
}
fclose(fp);
}
确保在创建新数组后,它将小于您定义的MAX。为了方便起见,我只计算了现在丢失的标点符号和空格(这是50)所以对于将来的“for”循环它是:
for (i = 0; i < MAX - 50; ++i)