急求!重谢!C语言简单小问题!

时间:2022-06-07 17:36:39
这是统计字母,空格,段落等的小程序,但是由于段落的标志是回车键也就是\n,现在情况是文本文件最后一段如果没有回车键的话就少一段,求优化方案。重谢!


#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp1, *fp2; /*定义两个指向FILE类型结构体的指针变量*/
char filename1[100],filename2[100],ch;   /*定义数组变量为字符型*/
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循环*/
{
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++;
}                /*当遇到换行符时段落数+1*/
    else
{
character++;
word++;
}          /*遇到其他字符时字符个数+1*/
ch++;
}
             
fclose(fp1);      /*关闭fp1指向的文件*/
fprintf(fp2,"character:%ld word:%ld sentence:%ld paragraph:%ld\n", character, word, sentence,paragraph);/*将统计结果写入fp指向的磁盘文件中*/
fclose(fp2);
}

20 个解决方案

#1


不要使用
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;
 //...
}
类似的例子还可以举很多。

#2


引用 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;
 //...
}
类似的例子还可以举很多。

那请问基于我的程序怎么改呢

#3


char ch;
应改为
int ch;

#4


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

#5


引用 3 楼 赵4老师的回复:
char ch;
应改为
int ch;

定义为char的目的就是为了读取文件中的字符,如果改为int类型是否也能实现同样的功能呢?

#6


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

#7


仅供参考:
#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;
}

#8


引用 6 楼 赵4老师的回复:
char ch;//会导致无法区分到底是读到了0xFF字符还是到了文件末尾。

谢谢详解,我想再问个问题,我之前考虑的优化方案是再定义一个ch2,用来存放从文件读取的ch上一个值,大概想法是如果ch=EOF,ch2!=\n时,段落数++,请问把EOF作为从文件中读到的最后一个字符,这样的做法合理吗?可行吗?或者有什么能够定义文本文件最后一个字符的?(因为想在源程序的基础上进行较少的改动,对于之前楼层提出的建议会采纳再写一个程序)

#9


引用 8 楼 D_CHRIS 的回复:
Quote: 引用 6 楼 赵4老师的回复:
char ch;//会导致无法区分到底是读到了0xFF字符还是到了文件末尾。

谢谢详解,我想再问个问题,我之前考虑的优化方案是再定义一个ch2,用来存放从文件读取的ch上一个值,大概想法是如果ch=EOF,ch2!=\n时,段落数++,请问把EOF作为从文件中读到的最后一个字符,这样的做法合理吗?可行吗?或者有什么能够定义文本文件最后一个字符的?(因为想在源程序的基础上进行较少的改动,对于之前楼层提出的建议会采纳再写一个程序)


不是合不合理的问题,而是取舍的问题,
当时这么定义的读写文件的函数,自然有他的考量。

#10


引用 9 楼 lm_whales 的回复:
谢谢详解,我想再问个问题,我之前考虑的优化方案是再定义一个ch2,用来存放从文件读取的ch上一个值,大概想法是如果ch=EOF,ch2!=\n时,段落数++,请问把EOF作为从文件中读到的最后一个字符,这样的做法合理吗?可行吗?或者有什么能够定义文本文件最后一个字符的?(因为想在源程序的基础上进行较少的改动,对于之前楼层提出的建议会采纳再写一个程序)


不是合不合理的问题,而是取舍的问题,
当时这么定义的读写文件的函数,自然有他的考量。那请问一下我可不可以做较小程度的修改来实现段落数的正确统计,因为段落数是以回车为标志的,如果最后一段没有回车就少统计一个。能不能帮忙看一下我对修改段落数统计的想法,谢谢。

#11


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


#12


#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 

#13


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

#14


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

#15


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

首先谢谢指正前面的错误。ch2=ch是想保存跳出while之前的最后一个字符,我觉得是ch==EOF之前的字符也就是文本中最后一个字符。如果ch2是\n,那段落数就少加一个。不谈前面的错误,这样的理解哪里有问题?为什么实现不了段落数的正确获取?

#16


这样理解是对的,你把错误的地方修改一下看看

#17


引用 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的含义是什么?

#18


引用 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的含义是什么?

你猜。 急求!重谢!C语言简单小问题!

#19


引用 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的含义是什么?

你猜。 急求!重谢!C语言简单小问题!

我猜:
z的含义表面上看是标记非空行,但在处理超长行时有特殊用途:
如果z为1,表明当前行非空,则只需读完改行剩下的内容即可。
否则,需要对当前读到的内容进行判断。

#20


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

#1


不要使用
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;
 //...
}
类似的例子还可以举很多。

#2


引用 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;
 //...
}
类似的例子还可以举很多。

那请问基于我的程序怎么改呢

#3


char ch;
应改为
int ch;

#4


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

#5


引用 3 楼 赵4老师的回复:
char ch;
应改为
int ch;

定义为char的目的就是为了读取文件中的字符,如果改为int类型是否也能实现同样的功能呢?

#6


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

#7


仅供参考:
#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;
}

#8


引用 6 楼 赵4老师的回复:
char ch;//会导致无法区分到底是读到了0xFF字符还是到了文件末尾。

谢谢详解,我想再问个问题,我之前考虑的优化方案是再定义一个ch2,用来存放从文件读取的ch上一个值,大概想法是如果ch=EOF,ch2!=\n时,段落数++,请问把EOF作为从文件中读到的最后一个字符,这样的做法合理吗?可行吗?或者有什么能够定义文本文件最后一个字符的?(因为想在源程序的基础上进行较少的改动,对于之前楼层提出的建议会采纳再写一个程序)

#9


引用 8 楼 D_CHRIS 的回复:
Quote: 引用 6 楼 赵4老师的回复:
char ch;//会导致无法区分到底是读到了0xFF字符还是到了文件末尾。

谢谢详解,我想再问个问题,我之前考虑的优化方案是再定义一个ch2,用来存放从文件读取的ch上一个值,大概想法是如果ch=EOF,ch2!=\n时,段落数++,请问把EOF作为从文件中读到的最后一个字符,这样的做法合理吗?可行吗?或者有什么能够定义文本文件最后一个字符的?(因为想在源程序的基础上进行较少的改动,对于之前楼层提出的建议会采纳再写一个程序)


不是合不合理的问题,而是取舍的问题,
当时这么定义的读写文件的函数,自然有他的考量。

#10


引用 9 楼 lm_whales 的回复:
谢谢详解,我想再问个问题,我之前考虑的优化方案是再定义一个ch2,用来存放从文件读取的ch上一个值,大概想法是如果ch=EOF,ch2!=\n时,段落数++,请问把EOF作为从文件中读到的最后一个字符,这样的做法合理吗?可行吗?或者有什么能够定义文本文件最后一个字符的?(因为想在源程序的基础上进行较少的改动,对于之前楼层提出的建议会采纳再写一个程序)


不是合不合理的问题,而是取舍的问题,
当时这么定义的读写文件的函数,自然有他的考量。那请问一下我可不可以做较小程度的修改来实现段落数的正确统计,因为段落数是以回车为标志的,如果最后一段没有回车就少统计一个。能不能帮忙看一下我对修改段落数统计的想法,谢谢。

#11


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


#12


#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 

#13


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

#14


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

#15


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

首先谢谢指正前面的错误。ch2=ch是想保存跳出while之前的最后一个字符,我觉得是ch==EOF之前的字符也就是文本中最后一个字符。如果ch2是\n,那段落数就少加一个。不谈前面的错误,这样的理解哪里有问题?为什么实现不了段落数的正确获取?

#16


这样理解是对的,你把错误的地方修改一下看看

#17


引用 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的含义是什么?

#18


引用 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的含义是什么?

你猜。 急求!重谢!C语言简单小问题!

#19


引用 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的含义是什么?

你猜。 急求!重谢!C语言简单小问题!

我猜:
z的含义表面上看是标记非空行,但在处理超长行时有特殊用途:
如果z为1,表明当前行非空,则只需读完改行剩下的内容即可。
否则,需要对当前读到的内容进行判断。

#20


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

#21