傻瓜题,送分~
admin 发表于 2010-04-21 | 来源:互联网 | 阅读:
大家好,我是一个C语言自学者,使用的是谭浩强《C程序设计》第三版教材,今天终于看完这本书了!唯一一点遗憾的就是我在做书上最后一道习题的时候感觉还有点不够完美。特来向大家请教。
题目:从键盘输入若干行字符(每行长度不等),输入后把它们存储到一磁盘文件中。再从该文件中读入这些数据,将其中小写字母转换成大写字母后在显示屏上输出。
书上标准答案是这样的:(注释都是我自己写的)
- C/C++ code
-
#include<stdio.h> void main() { int i,flag; // flag用来控制输入结束 char str[80],c; FILE *fp; fp=fopen("text","w"); // 以"w"方式打开text文件 flag=1; while(flag==1) { printf("input string:\n"); gets(str); // 获取str fprintf(fp,"%s",str); // 把获取的str输入到fp指向的文件 printf("continue?"); c=getchar(); if((c=='N')||(c=='n')) //如果输入N或者n,则结束获取str flag=0; getchar(); } fclose(fp); fp=fopen("text","r"); //以"r"方式打开text文件 while(fscanf(fp,"%s",str)!=EOF) { for(i=0;str[i]!='';i++) if((str[i]>='a') && (str[i]<='z')) str[i]-=32; printf("%s\n",str); } fclose(fp); }
但是答案后面提出一个问题:用fscanf函数从文件读入字符串是,把空格作为一个字符串结束的标志,如果输入的字符串包含了空格,就会发生一些问题,例如输入“I am a student”,结果将会是4行,而不是一行。
这是我自己写的代码,用了一个tlen[]数组来存放str的长度,虽然要求达到了,但是感觉程序写得不是很好,不知道大家对于这个问题是怎么处理的,怎样写的代码会更好呢?
这是我写的:
- C/C++ code
-
#include<stdio.h> #include<string.h> void main() { int i,j,flag; int tlen[10]; // tlen[]数组来存放str的长度 char str[80],c; FILE *fp; fp=fopen("text","w"); flag=1; i=0; while(flag==1) { printf("input string:\n"); gets(str); tlen[i++]=strlen(str); fprintf(fp,"%s",str); printf("continue?"); c=getchar(); if((c=='N')||(c=='n')) flag=0; getchar(); } fclose(fp); fp=fopen("text","r"); j=0; while(fgets(str,(tlen[j++]+1),fp)!=NULL) { for(i=0;str[i]!='';i++) if((str[i]>='a') && (str[i]<='z')) str[i]-=32; printf("%s\n",str); } fclose(fp); }
以上代码在VC++6.0中调试通过。

C/C++ code
#include<stdio.h>
void main()
{
int i,flag; // flag用来控制输入结束
char str[80],c;
FILE *fp;
fp=fopen("text","w"); // 以"w"方式打开text文件
flag=1;
while(flag==1)
{
printf("input string:\n");
gets(str); // 获取str
fprintf(fp,"%s",str); // 把获取的str输入到fp指向的文件
printf("continue?");
c=getchar();
if((c==’N')||(c==’n')) //如果输入N或者n,则结束获取str
flag=0;
getchar();
}
fclose(fp);
fp=fopen("text","r"); //以"r"方式打开text文件
while(fgets(str,100,fp)!=NULL)// *************整行读入*************
{
for(i=0;str[i]!=”;i++)
if((str[i]>=’a') && (str[i]<=’z'))
str[i]-=32;
printf("%s\n",str);
}
fclose(fp);
}
不必保存str的长度,fgets遇到回车的时候会自动结束的.while(fgets(str,80,fp)!=NULL)楼主最好再用记事本打开text文件看看,是不是每行都有回车。我觉得应该是有的。
大小写转换可以用库函数 toupperstr[i] = toupper(str[i]);或者这样写 str[i] = str[i]-’a'+’A';
大小写之类的尽量用库函数。
这样写 str[i] = str[i]-’a'+’A';为什么要这样写呢?if((str[i]>=’a') && (str[i]<=’z')) str[i]-=32;我这样子写不好吗?
不必保存str的长度,fgets遇到回车的时候会自动结束的.while(fgets(str,80,fp)!=NULL)楼主最好再用记事本打开text文件看看,是不是每行都有回车。我觉得应该是有的。标准答案有问题,每行都有回车我觉得应该这样改:C/C++ code
#include<stdio.h>
#include<string.h>
void main()
{
int i,j,flag;
char str[80],c;
FILE *fp;
fp=fopen("text","w");
flag=1;
i=0;
while(flag==1)
{
printf("input string:\n");
gets(str);
fprintf(fp,"%s",str);
fputc(‘\n’,fp); // 这里加一个换行
printf("continue?");
c=getchar();
if((c==’N')||(c==’n'))
flag=0;
getchar();
}
fclose(fp);
fp=fopen("text","r");
j=0;
while(fgets(str,100,fp)!=NULL)
{
for(i=0;str[i]!=”;i++)
if((str[i]>=’a') && (str[i]<=’z'))
str[i]-=32;
printf("%s\n",str);
}
fclose(fp);
}
这样写 str[i] = str[i]-’a'+’A';为什么要这样写呢?if((str[i]>=’a') && (str[i]<=’z'))str[i]-=32;我这样子写不好吗?你这里的32不就是硬编码了吗?
if((str[i]>=’a') &amp;&amp; (str[i]<=’z'))str[i]-=32;我这样子写不好吗?你这里的32不就是硬编码了吗?多谢指教~
学习了
大小写转换可以用库函数 toupperstr[i] = toupper(str[i]);或者这样写 str[i] = str[i]-’a'+’A';学习了,这样写感觉很奇怪啊
这样写 str[i] = str[i]-’a'+’A';为什么要这样写呢?if((str[i]>=’a') && (str[i]<=’z'))str[i]-=32;我这样子写不好吗?这两个写法,产生的汇编代码是完全一样的,编译器会把-’a'+’A'换算成-32。str[i]-’a'+’A'可读性好一点,谁一看都能明白是什么意思。而且也不用自己做算术把那个32算出来,让编译器代劳多好。
学习了
不要用fscanf函数读取,用fgets。