user-0 提问: 急求！重谢！C语言简单小问题！

回复:
user: user-1
content: 到达文件末尾的时候，可以让文件位置指针后退2位，去读取最后一个字符，这样你不就知道最后一个字符是不是‘\n’ 如果是'\n'的话，段落数+1，不是的话，就不用加1了

user: user-2
content: 引用 18 楼 zhao4zhong1 的回复:[quote=引用 17 楼 zhangxiangDavaid 的回复:] [quote=引用 7 楼 zhao4zhong1 的回复:] 仅供参考：#include <stdio.h> #include <string.h> #define MAXLEN 1000 char ln[MAXLEN]; FILE *f; int i,z; int b,n,L; int main(int argc,char **argv) {     if (argc<2) {         printf("Usage:%s fullpathfilename.ext\nget total blank/non-blank/total linenumbers.\n",argv[0]);         return 1;     }     f=fopen(argv[1],"r");     if (NULL==f) {         printf("Can not open file [%s]!\n",argv[1]);         return 2;     }     z=0;     b=0;     n=0;     L=0;     while (1) {         if (NULL==fgets(ln,MAXLEN,f)) break;         L=strlen(ln);         if ('\n'==ln[L-1]) {             if (0==z) {                 for (i=0;i<L-1;i++) {                     if (!(' '==ln[i] || '\t'==ln[i])) break;                 }                 if (i<L-1) z=1;//当前行不是空行             }             if (0==z) b++; else n++;             z=0;         } else {             if (0==z) {                 for (i=0;i<L;i++) {                     if (!(' '==ln[i] || '\t'==ln[i])) break;                 }                 if (i<L) z=1;//当前行不是空行             }         }     }     fclose(f);     if (L>0 && '\n'!=ln[L-1]) {         if (0==z) b++; else n++;//最后一行末尾无'\n'也计算     }     printf("File:[%s] total blank/non-blank/total linenumbers is %d/%d/%d\n",argv[1],b,n,b+n);     return 0; }  变量z的含义是什么？[/quote] 你猜。[/quote] 我猜： z的含义表面上看是标记非空行，但在处理超长行时有特殊用途： 如果z为1，表明当前行非空，则只需读完改行剩下的内容即可。 否则，需要对当前读到的内容进行判断。

user: user-3
content: 引用 17 楼 zhangxiangDavaid 的回复:[quote=引用 7 楼 zhao4zhong1 的回复:] 仅供参考：#include <stdio.h> #include <string.h> #define MAXLEN 1000 char ln[MAXLEN]; FILE *f; int i,z; int b,n,L; int main(int argc,char **argv) {     if (argc<2) {         printf("Usage:%s fullpathfilename.ext\nget total blank/non-blank/total linenumbers.\n",argv[0]);         return 1;     }     f=fopen(argv[1],"r");     if (NULL==f) {         printf("Can not open file [%s]!\n",argv[1]);         return 2;     }     z=0;     b=0;     n=0;     L=0;     while (1) {         if (NULL==fgets(ln,MAXLEN,f)) break;         L=strlen(ln);         if ('\n'==ln[L-1]) {             if (0==z) {                 for (i=0;i<L-1;i++) {                     if (!(' '==ln[i] || '\t'==ln[i])) break;                 }                 if (i<L-1) z=1;//当前行不是空行             }             if (0==z) b++; else n++;             z=0;         } else {             if (0==z) {                 for (i=0;i<L;i++) {                     if (!(' '==ln[i] || '\t'==ln[i])) break;                 }                 if (i<L) z=1;//当前行不是空行             }         }     }     fclose(f);     if (L>0 && '\n'!=ln[L-1]) {         if (0==z) b++; else n++;//最后一行末尾无'\n'也计算     }     printf("File:[%s] total blank/non-blank/total linenumbers is %d/%d/%d\n",argv[1],b,n,b+n);     return 0; }  变量z的含义是什么？[/quote] 你猜。

user: user-2
content: 引用 7 楼 zhao4zhong1 的回复:仅供参考：#include <stdio.h> #include <string.h> #define MAXLEN 1000 char ln[MAXLEN]; FILE *f; int i,z; int b,n,L; int main(int argc,char **argv) {     if (argc<2) {         printf("Usage:%s fullpathfilename.ext\nget total blank/non-blank/total linenumbers.\n",argv[0]);         return 1;     }     f=fopen(argv[1],"r");     if (NULL==f) {         printf("Can not open file [%s]!\n",argv[1]);         return 2;     }     z=0;     b=0;     n=0;     L=0;     while (1) {         if (NULL==fgets(ln,MAXLEN,f)) break;         L=strlen(ln);         if ('\n'==ln[L-1]) {             if (0==z) {                 for (i=0;i<L-1;i++) {                     if (!(' '==ln[i] || '\t'==ln[i])) break;                 }                 if (i<L-1) z=1;//当前行不是空行             }             if (0==z) b++; else n++;             z=0;         } else {             if (0==z) {                 for (i=0;i<L;i++) {                     if (!(' '==ln[i] || '\t'==ln[i])) break;                 }                 if (i<L) z=1;//当前行不是空行             }         }     }     fclose(f);     if (L>0 && '\n'!=ln[L-1]) {         if (0==z) b++; else n++;//最后一行末尾无'\n'也计算     }     printf("File:[%s] total blank/non-blank/total linenumbers is %d/%d/%d\n",argv[1],b,n,b+n);     return 0; }  变量z的含义是什么？

user: user-4
content: 这样理解是对的，你把错误的地方修改一下看看

user: user-0
content: 引用 14 楼 user-4的回复:1)ch 必须改为 int 类型， 因为 (ch=fgetc(fp1)) 同样是 ch类型的 和 EOF 比较是有问题的 2)多定义一个 字符类型，不如直接计算最后一行的长度简单明了 3）   ch++; //这个++ 是不对的 ch 是从文件读到的数据 不用++，这个++ 造成 ch,ch2 通常不会 ‘\n'     ch2=ch; // 这是做什么用的？ 首先谢谢指正前面的错误。ch2=ch是想保存跳出while之前的最后一个字符，我觉得是ch==EOF之前的字符也就是文本中最后一个字符。如果ch2是\n，那段落数就少加一个。不谈前面的错误，这样的理解哪里有问题？为什么实现不了段落数的正确获取？

user: user-4
content: 1)ch 必须改为 int 类型， 因为 (ch=fgetc(fp1)) 同样是 ch类型的 和 EOF 比较是有问题的 2)多定义一个 字符类型，不如直接计算最后一行的长度简单明了 3）   ch++; //这个++ 是不对的 ch 是从文件读到的数据 不用++，这个++ 造成 ch,ch2 通常不会 ‘\n'     ch2=ch; // 这是做什么用的？

user: user-0
content: 引用 11 楼 user-4 的回复:这个 读到文件结束，在上一个段落和文件结束前，有文字那就添加一个段落 如果，换行后（段落后）紧接着就是文件结束了，那就不用添加这个段落。 这是个+1 ，-1 的问题，处理一下就好。我试了一下，在程序上加了这么一小段，（printf单纯为了测试这个if语句能不能运行），可是当测试文本末尾有\n，if语句也没有运行，是不是EOF不能作为文件最后一个字符用？		else 		{ 			character++; 			word++; 		}          /*遇到其他字符时字符个数+1*/ 		ch++; 		ch2=ch; 	} 	if(ch2=='\n') 	{ 		printf("a"); 		character++; 	}

user: user-4
content: #include <stdio.h> #include <stdlib.h> int main() {     FILE *fp1, *fp2; /*定义两个指向FILE类型结构体的指针变量*/    int ch;// 定义整型，用来读取字符    long paraglen =0;//定义段长     char filename1[100],filename2[100] ; /*定义数组变量为字符型*/     long character,word,sentence,paragraph; /*定义变量为长整型*/     character=word=sentence=paragraph=0; /*长整型变量的初值均为0*/     printf("Enter file name \n");     scanf("%s", filename1); /*输入要进行统计的文件的路径及名称*/     if((fp1=fopen(filename1, "r"))==NULL) /*以只读方式打开指定文件*/     {         printf("cannot open file.\n");         exit(1);     }     printf ( "Enter file name for write data:\n");     scanf("%s",filename2); /*输入文件名即将统计结果放到那个文件中*/     if((fp2=fopen(filename2, "w"))==NULL) /*已可写方式要存放统计结果的文件*/     {         printf("cannot open file \n");         exit(1);     }     while((ch=fgetc(fp1))!=EOF) /*知道文件内容结束处停止while循环*/     {         paraglen++;//每读取一个字符，段长加一         if(ch>='A' && ch<'Z'||ch>='a' && ch<='z')         {             character++;         }          /*当遇到字母时字符个数+1*/         else if(ch==' ')         {             character++;             word++;         }          /*当遇到空格时字符数+1*/         else if(ch>='0' && ch<='9')         {         character++;         }          /*当遇到数字时数字个数+1*/         else if(ch=='.'||ch=='!'||ch=='?')         {             sentence++;             character++;         }          /*当遇到.!?时句子数+1，字符数+1*/         else  if ((ch=='\r')||(ch=='\n'))         {    paragraph++;              paraglen = 0;//段长，实际上是行长，每当换行就清零         }                /*当遇到换行符时段落数+1*/         else         {             character++;             word++;         }          /*遇到其他字符时字符个数+1*/         ch =0;     }         if(paraglen)                paragraph++;  /*遇到段长非零，表示读到 文件结束，最后一个段（行），没有计算所以，段(行)数加一*/                /* （或者读出错，这里不考虑读文件出错），需要的话，使用ferror 函数，读取文件错误码 */          fclose(fp1);      /*关闭fp1指向的文件*/         fprintf(fp2,"character:%ld word:%ld sentence:%ld paragraph:%ld\n", character, word, sentence,paragraph);/*将统计结果写入fp指向的磁盘文件中*/         fclose(fp2);         while(getchar()!='q'); }  这是修改后的代码 ch ++ 是不必要的，因为ch 是从文件里读出来的，需要的话，重置为 0

user: user-4
content: 这个 读到文件结束，在上一个段落和文件结束前，有文字那就添加一个段落 如果，换行后（段落后）紧接着就是文件结束了，那就不用添加这个段落。 这是个+1 ，-1 的问题，处理一下就好。

user: user-0
content: 引用 9 楼 user-4 的回复:谢谢详解，我想再问个问题，我之前考虑的优化方案是再定义一个ch2，用来存放从文件读取的ch上一个值，大概想法是如果ch=EOF，ch2!=\n时，段落数++，请问把EOF作为从文件中读到的最后一个字符，这样的做法合理吗？可行吗？或者有什么能够定义文本文件最后一个字符的？（因为想在源程序的基础上进行较少的改动，对于之前楼层提出的建议会采纳再写一个程序）  不是合不合理的问题，而是取舍的问题， 当时这么定义的读写文件的函数，自然有他的考量。[/quote]那请问一下我可不可以做较小程度的修改来实现段落数的正确统计，因为段落数是以回车为标志的，如果最后一段没有回车就少统计一个。能不能帮忙看一下我对修改段落数统计的想法，谢谢。

user: user-4
content: 引用 8 楼 D_CHRIS 的回复:[quote=引用 6 楼 赵4老师的回复:]char ch;//会导致无法区分到底是读到了0xFF字符还是到了文件末尾。 谢谢详解，我想再问个问题，我之前考虑的优化方案是再定义一个ch2，用来存放从文件读取的ch上一个值，大概想法是如果ch=EOF，ch2!=\n时，段落数++，请问把EOF作为从文件中读到的最后一个字符，这样的做法合理吗？可行吗？或者有什么能够定义文本文件最后一个字符的？（因为想在源程序的基础上进行较少的改动，对于之前楼层提出的建议会采纳再写一个程序）[/quote]  不是合不合理的问题，而是取舍的问题， 当时这么定义的读写文件的函数，自然有他的考量。

user: user-0
content: 引用 6 楼 赵4老师的回复:char ch;//会导致无法区分到底是读到了0xFF字符还是到了文件末尾。 谢谢详解，我想再问个问题，我之前考虑的优化方案是再定义一个ch2，用来存放从文件读取的ch上一个值，大概想法是如果ch=EOF，ch2!=\n时，段落数++，请问把EOF作为从文件中读到的最后一个字符，这样的做法合理吗？可行吗？或者有什么能够定义文本文件最后一个字符的？（因为想在源程序的基础上进行较少的改动，对于之前楼层提出的建议会采纳再写一个程序）

user: user-3
content: 仅供参考：#include <stdio.h> #include <string.h> #define MAXLEN 1000 char ln[MAXLEN]; FILE *f; int i,z; int b,n,L; int main(int argc,char **argv) {     if (argc<2) {         printf("Usage:%s fullpathfilename.ext\nget total blank/non-blank/total linenumbers.\n",argv[0]);         return 1;     }     f=fopen(argv[1],"r");     if (NULL==f) {         printf("Can not open file [%s]!\n",argv[1]);         return 2;     }     z=0;     b=0;     n=0;     L=0;     while (1) {         if (NULL==fgets(ln,MAXLEN,f)) break;         L=strlen(ln);         if ('\n'==ln[L-1]) {             if (0==z) {                 for (i=0;i<L-1;i++) {                     if (!(' '==ln[i] || '\t'==ln[i])) break;                 }                 if (i<L-1) z=1;//当前行不是空行             }             if (0==z) b++; else n++;             z=0;         } else {             if (0==z) {                 for (i=0;i<L;i++) {                     if (!(' '==ln[i] || '\t'==ln[i])) break;                 }                 if (i<L) z=1;//当前行不是空行             }         }     }     fclose(f);     if (L>0 && '\n'!=ln[L-1]) {         if (0==z) b++; else n++;//最后一行末尾无'\n'也计算     }     printf("File:[%s] total blank/non-blank/total linenumbers is %d/%d/%d\n",argv[1],b,n,b+n);     return 0; }

user: user-3
content: char ch;//会导致无法区分到底是读到了0xFF字符还是到了文件末尾。

user: user-0
content: 引用 3 楼 赵4老师的回复:char ch; 应改为 int ch; 定义为char的目的就是为了读取文件中的字符，如果改为int类型是否也能实现同样的功能呢？

user: user-3
content: 将while语句中的条件判断挪到while循环的第一句或中间某句或最后一句视具体情况而定。

user: user-3
content: char ch; 应改为 int ch;

user: user-0
content: 引用 1 楼 赵4老师的回复:不要使用 while (条件) 更不要使用 while (组合条件) 要使用 while (1) {  if (条件1) break;  //...  if (条件2) continue;  //...  if (条件3) return;  //... } 因为前两种写法在语言表达意思的层面上有二义性，只有第三种才忠实反映了程序流的实际情况。 典型如： 下面两段的语义都是当文件未结束时读字符 while (!feof(f)) {  a=fgetc(f);  //...  b=fgetc(f);//可能此时已经feof了！  //... } 而这样写就没有问题： while (1) {  a=fgetc(f);  if (feof(f)) break;  //...  b=fgetc(f);  if (feof(f)) break;  //... } 类似的例子还可以举很多。  不要使用 while (条件) 更不要使用 while (组合条件) 要使用 while (1) {  if (条件1) break;  //...  if (条件2) continue;  //...  if (条件3) return;  //... } 因为前两种写法在语言表达意思的层面上有二义性，只有第三种才忠实反映了程序流的实际情况。 典型如： 下面两段的语义都是当文件未结束时读字符 while (!feof(f)) {  a=fgetc(f);  //...  b=fgetc(f);//可能此时已经feof了！  //... } 而这样写就没有问题： while (1) {  a=fgetc(f);  if (feof(f)) break;  //...  b=fgetc(f);  if (feof(f)) break;  //... } 类似的例子还可以举很多。 [/quote] 那请问基于我的程序怎么改呢

user: user-3
content: 不要使用 while (条件) 更不要使用 while (组合条件) 要使用 while (1) {  if (条件1) break;  //...  if (条件2) continue;  //...  if (条件3) return;  //... } 因为前两种写法在语言表达意思的层面上有二义性，只有第三种才忠实反映了程序流的实际情况。 典型如： 下面两段的语义都是当文件未结束时读字符 while (!feof(f)) {  a=fgetc(f);  //...  b=fgetc(f);//可能此时已经feof了！  //... } 而这样写就没有问题： while (1) {  a=fgetc(f);  if (feof(f)) break;  //...  b=fgetc(f);  if (feof(f)) break;  //... } 类似的例子还可以举很多。