2

我正在编写计算文件行数和字符数的代码。

#include <fstream>
#include <iostream>
#include <stdlib.h>    
using namespace std;


int main(int argc, char* argv[])
    {
    ifstream read(argv[1]);


    char line[256];
    int nLines=0, nChars=0, nTotalChars=0;
    read.getline(line, 256);

    while(read.good())                      /
        {
        nChars=0;

        int i=0;
        while(line[i]!='\n')
            {

            if ((int)line[i]>32) {nChars++;}
            i++;
            }

        nLines++;
        nTotalChars= nTotalChars + nChars;
        read.getline(line, 256);
        }
    cout << "The number of lines is "<< nLines << endl;
    cout << "The number of characters is "<< nTotalChars << endl;
    }

该行while(line[i]!='\n')似乎是导致以下错误的原因

分段错误(核心转储)

我不知道出了什么问题。互联网告诉我,据我所知,我正在正确检查行尾。

4

5 回答 5

6

您的代码将找不到'\n',因为它已从输入序列中丢弃。从以下文档getline

定界字符是换行符 [...]:当在输入序列中找到时,它会从输入序列中提取出来,但会被丢弃并且不会写入 s。

您应该搜索'\0'

    while(line[i])
        {
        if ((int)line[i]>32) {nChars++;}
        i++;
        }
于 2013-08-08T12:26:58.810 回答
1

因为getline不会存储\n,所以循环:

    while(line[i]!='\n')
        {

        if ((int)line[i]>32) {nChars++;}
        i++;
        }

永远不会结束,直到line[i]超过数组长度并导致分段错误。

于 2013-08-08T12:28:17.817 回答
1

行中没有行尾字符。因此,您应该检查 NULL 字符(字符串结尾)而不是行尾。还要确保在您的情况下不要超过缓冲区的大小(256)。

于 2013-08-08T12:28:29.213 回答
0

我认为 for 循环会更安全:

for ( unsigned int i = 0; i < line.size(); i++ ) {
  //whatever
}
于 2013-08-08T12:32:40.693 回答
0

您的代码有几个问题,但对于初学者来说,您不应该将行读入char[]. 如果您使用 std::string,那么您不必担心读取部分行等。

getline然后是从文件中提取的事实'\n',但不存储它,因此您的代码(甚至修改为使用)将永远不会在缓冲区中std::string看到 a 。'\n'如果您使用的是字符串,则从line.begin()to 迭代line.end();如果您使用的是 a char[],则read.gcount()在调用getline. (char[] 除非你假设世界上没有文本文件包含'\0'.)

最后,如果最后一行不以 a 结尾'\n'(Windows 下的常见情况),您将不会处理它。如果你使用 std::string,你可以简单地写:

std::getline( read, line );
while ( read ) {
    //  ...
    std::getline( read, line );
}

甚至:

while ( std::getline( read, line ) ) {
    ++ nLines;
    for ( std::string::const_iterator current = line.begin();
            current != line.end();
            ++ current ) {
        //  process character *current in line...
    }
}

(后者无处不在,即使它很丑陋。)

使用char[],您必须将其替换为:

while ( read.getline( buffer, sizeof(buffer) ) || read.gcount() != 0 ) {
    int l = read.gcount();
    if ( read ) {
        ++ nLines;
    } else {
        if ( read.eof() ) {
            ++ nLines;  //  Last line did not end with a '\n'
        } else {
            read.clear();   //  Line longer than buffer...
    }
    for ( int i = 0; i != l; ++ i ) {
        //  process character buffer[i] in line...
    }
}

最后一个问题:(int)line[i] > 32应该是什么意思?你想要!isspace( line[i] ) && !iscntrl( line[i] )吗?(当然,这根本不是它的作用。)

于 2013-08-08T14:28:31.270 回答