为什么这个C代码比这个C++;密码?获取文件中最大的行 我有两个版本的程序,基本上是相同的,得到一个文件中最大的一行,我有一个大约8000行的文件,C中的代码比C++中的代码要稍微原始一些。C程序运行大约2秒,而C++程序运行10秒(对于两种情况,我都在测试同一文件)。但是为什么呢?我期待它需要同样的时间或多一点,但不是8秒慢

为什么这个C代码比这个C++;密码?获取文件中最大的行 我有两个版本的程序,基本上是相同的,得到一个文件中最大的一行,我有一个大约8000行的文件,C中的代码比C++中的代码要稍微原始一些。C程序运行大约2秒,而C++程序运行10秒(对于两种情况,我都在测试同一文件)。但是为什么呢?我期待它需要同样的时间或多一点,但不是8秒慢,c++,c,performance,count,lines,C++,C,Performance,Count,Lines,我的C代码: #include <stdio.h> #include <stdlib.h> #include <string.h> #if _DEBUG #define DEBUG_PATH "../Debug/" #else #define DEBUG_PATH "" #endif const char FILE_NAME[] = DEBUG_PATH "data.noun"; int main() { int sPos

我的C代码:

#include <stdio.h>
#include <stdlib.h> 
#include <string.h>

#if _DEBUG
    #define DEBUG_PATH "../Debug/"
#else
    #define DEBUG_PATH ""
#endif

const char FILE_NAME[] = DEBUG_PATH "data.noun";

int main()
{   
    int sPos = 0;
    int maxCount = 0;
    int cPos = 0;
    int ch;
    FILE *in_file;              

    in_file = fopen(FILE_NAME, "r");
    if (in_file == NULL) 
    {
        printf("Cannot open %s\n", FILE_NAME);
        exit(8);
    }       

    while (1) 
    {
        ch = fgetc(in_file);
        if(ch == 0x0A || ch == EOF) // \n or \r or \r\n or end of file
        {           
            if ((cPos - sPos) > maxCount)
                maxCount = (cPos - sPos);

            if(ch == EOF)
                break;

            sPos = cPos;
        }
        else
            cPos++;
    }

    fclose(in_file);

    printf("Max line length: %i\n",  maxCount); 

    getch();
    return (0);
}
#包括
#包括
#包括
#如果调试
#定义调试路径“./DEBUG/”
#否则
#定义调试路径“”
#恩迪夫
const char FILE_NAME[]=调试路径“data.noon”;
int main()
{   
int sPos=0;
int maxCount=0;
int cPos=0;
int-ch;
文件*在_文件中;
in_file=fopen(文件名,“r”);
if(in_file==NULL)
{
printf(“无法打开%s\n”,文件名);
出口(8);
}       
而(1)
{
ch=fgetc(在文件中);
如果(ch==0x0A | | ch==EOF)/\n或\r或\r\n或文件结尾
{           
如果((cPos-sPos)>最大计数)
最大计数=(cPos-SPO);
如果(ch==EOF)
打破
sPos=cPos;
}
其他的
cPos++;
}
fclose(在_文件中);
printf(“最大行长度:%i\n”,最大计数);
getch();
返回(0);
}
我的C++代码:

#include <iostream>
#include <fstream>
#include <stdio.h>
#include <string>

using namespace std;

#ifdef _DEBUG
    #define FILE_PATH "../Debug/data.noun"
#else
    #define FILE_PATH "data.noun"
#endif

int main()
{
    string fileName = FILE_PATH;
    string s = "";
    ifstream file;
    int size = 0;

    file.open(fileName.c_str());
    if(!file)
    {
        printf("could not open file!");
        return 0;
    }

    while(getline(file, s) )
            size = (s.length() > size) ? s.length() : size;
    file.close();

    printf("biggest line in file: %i", size);   

    getchar();
    return 0;
}
#包括
#包括
#包括
#包括
使用名称空间std;
#ifdef_调试
#定义文件路径“./Debug/data.noon”
#否则
#定义文件路径“data.noun”
#恩迪夫
int main()
{
字符串文件名=文件路径;
字符串s=“”;
ifstream文件;
int size=0;
打开(fileName.c_str());
如果(!文件)
{
printf(“无法打开文件!”);
返回0;
}
while(getline(文件)
大小=(s.length()>大小)?s.length():大小;
file.close();
printf(“文件中最大的行:%i”,大小);
getchar();
返回0;
}

<代码> > p> C++程序构建线条的字符串对象,而C程序只读取字符并查看字符。

编辑:


谢谢你的支持,但经过讨论,我现在认为这个答案是错误的。这是一个合理的第一猜测,但是在这种情况下,似乎不同的(和非常缓慢的)执行时间是由其他事情引起的。

< P> C++版本不断分配和释放STD::String实例。内存分配是一项代价高昂的操作。除此之外,还会执行构造函数/析构函数


然而,C版本使用的是恒定内存,这是必要的:读取单个字符,如果行长计数器更高,则为每一行设置新值,仅此而已。

您不是在对苹果进行比较。C程序不会将数据从
文件*
缓冲区复制到程序内存中。它还对原始文件进行操作

< >你的C++程序需要多次遍历每个字符串的长度——一次在流代码中知道何时终止它返回给你的字符串,一次在<代码>的构造函数:STD::String < /C>中,并且在你的代码调用到<代码> s长度()/<代码> < /P> 您可以通过使用
getc_unlocked
提高C程序的性能。但最大的胜利来自不必复制数据


编辑:根据bames53的评论进行编辑

2秒,只需8000行?我不知道你的队伍有多长,但很可能你做错了什么

从古腾堡项目下载El Quijote(40006行,2.2MB)后,这个微不足道的Python程序几乎立即执行:

时间安排:

~/test$ time python maxlen.py < pg996.txt
76

real    0m0.034s
user    0m0.020s
sys     0m0.010s
~/test$time python maxlen.py
您可以通过缓冲输入而不是逐字符读取来改进C代码


<>为什么C++比C慢,它应该与构建字符串对象然后调用长度方法有关。在C语言中,您只是在计算字符。

我的猜测是,您使用的编译器选项、编译器本身或文件系统都有问题。我刚刚编译了这两个版本(启用了优化),并针对92000行文本文件运行了它们:

c++ version:  113 ms
c version:    179 ms

<>我怀疑C++版本更快的原因是因为FGEC最有可能慢。code>fgetc
确实使用缓冲I/O,但它正在进行函数调用以检索每个字符。我以前已经测试过了,并且<>代码> FGECC < /C> >没有一个调用中读取整个行的调用速度(例如,与 FGES >相比)。

< P>我尝试编译和运行程序,以40K的C++源代码行,它们都在大约25Ms左右完成。我只能得出结论,您的输入文件有非常长的行,每行可能有10K-100K个字符。在这种情况下,C版本从长线长度上没有任何负面性能,而C++版本必须不断增加字符串的大小并将旧数据复制到新的缓冲区中。如果它必须在大小上增加足够的次数,这可以解释过度的性能差异

这里的关键是这两个程序做的事情不一样,所以你不能真正比较它们的结果。如果您能够提供输入文件,我们可能能够提供其他详细信息


你可能可以使用C++代码> Telg < /C>和忽略< /C> >在C++中更快地执行。

< P>所以,在一些评论中,我回应了人们的回答:问题可能是C++版本所做的额外复制,在那里,它将字符串复制到字符串中的内存中。但我想测试一下

首先,我实现了fgetc
c++ version:  113 ms
c version:    179 ms
fgetc time is: 48150 microseconds
snextc time is: 6019 microseconds
get time is: 79600 microseconds
getline time is: 19881 microseconds
fgetc time is: 59593 microseconds
snextc time is: 24915 microseconds
get time is: 228643 microseconds
getline time is: 130807 microseconds
{
    auto begin = boost::chrono::high_resolution_clock::now();
    FILE *cin = fopen("D:/bames/automata/pg35390.txt","rb");
    assert(cin);
    unsigned maxLength = 0;
    unsigned i = 0;
    int ch;
    while(1) {
        ch = fgetc(cin);
        if(ch == 0x0A || ch == EOF) {
            maxLength = std::max(i,maxLength);
            i = 0;
            if(ch==EOF)
                break;
        } else {
            ++i;
        }
    }
    fclose(cin);
    auto end = boost::chrono::high_resolution_clock::now();
    std::cout << "max line is: " << maxLength << '\n';
    std::cout << "fgetc time is: " << boost::chrono::duration_cast<boost::chrono::microseconds>(end-begin) << '\n';
}
{
    auto begin = boost::chrono::high_resolution_clock::now();
    std::ifstream fin("D:/bames/automata/pg35390.txt",std::ios::binary);
    unsigned maxLength = 0;
    std::string line;
    while(std::getline(fin,line)) {
        maxLength = std::max(line.size(),maxLength);
    }
    auto end = boost::chrono::high_resolution_clock::now();
    std::cout << "max line is: " << maxLength << '\n';
    std::cout << "getline time is: " << boost::chrono::duration_cast<boost::chrono::microseconds>(end-begin) << '\n';
}
{
    auto begin = boost::chrono::high_resolution_clock::now();
    std::ifstream fin("D:/bames/automata/pg35390.txt",std::ios::binary);
    unsigned maxLength = 0;
    unsigned i = 0;
    while(1) {
        int ch = fin.get();
        if(fin.good() && ch == 0x0A || fin.eof()) {
            maxLength = std::max(i,maxLength);
            i = 0;
            if(fin.eof())
                break;
        } else {
            ++i;
        }
    }
    auto end = boost::chrono::high_resolution_clock::now();
    std::cout << "max line is: " << maxLength << '\n';
    std::cout << "get time is: " << boost::chrono::duration_cast<boost::chrono::microseconds>(end-begin) << '\n';
}
{
    auto begin = boost::chrono::high_resolution_clock::now();
    std::ifstream fin("D:/bames/automata/pg35390.txt",std::ios::binary);
    std::filebuf &buf = *fin.rdbuf();
    unsigned maxLength = 0;
    unsigned i = 0;
    while(1) {
        int ch = buf.snextc();
        if(ch == 0x0A || ch == std::char_traits<char>::eof()) {
            maxLength = std::max(i,maxLength);
            i = 0;
            if(ch == std::char_traits<char>::eof())
                break;
        } else {
            ++i;
        }
    }
    auto end = boost::chrono::high_resolution_clock::now();
    std::cout << "max line is: " << maxLength << '\n';
    std::cout << "snextc time is: " << boost::chrono::duration_cast<boost::chrono::microseconds>(end-begin) << '\n';
}
fgetc time is: 39004 microseconds
snextc time is: 19374 microseconds
get time is: 145233 microseconds
getline time is: 67316 microseconds
fgetc time is: 44061 microseconds
snextc time is: 92894 microseconds
get time is: 184967 microseconds
getline time is: 209529 microseconds
fgetc time is: 39356 microseconds
snextc time is: 21324 microseconds
get time is: 149048 microseconds
getline time is: 63983 microseconds
fgetc time is: 37527 microseconds
snextc time is: 22863 microseconds
get time is: 145176 microseconds
getline time is: 67899 microseconds
~$ for i in {0..1000}; do cat /etc/* | strings; done &> huge.txt
#include <iostream>
#include <stdio.h>

using namespace std;

int main(void)
{
    string s = "";
    int size = 0;

    while (cin) {
        getline(cin, s);
        size = (s.length() > size) ? s.length() : size;
    }
    printf("Biggest line in file: %i\n", size);

    return 0;
}
~$ time ./cplusplus < huge.txt
real    1m53.122s
user    1m29.254s
sys     0m0.544s
#include <stdio.h>
int main(void)
{
    char *line = NULL;
    int read, max = 0, len = 0;

    while ((read = getline(&line, &len, stdin)) != -1)
        if (max < read)
            max = read -1;
    printf("Biggest line in file %d\n", max);

    return 0;
}
~$ time ./ansic < huge.txt
real    0m4.015s
user    0m3.432s
sys     0m0.328s