2010-03-03 2 views
2

매우 큰 데이터 세트에서 I/O 집중적 인 빠른 정렬 (C++ qsort)을 구현하려고합니다. 속도의 이익을 위해 한 번에 데이터 덩어리를 버퍼로 읽은 다음 qsort를 사용하여 버퍼 내부에서 정렬하고 싶습니다. (현재 텍스트 파일로 작업하고 있지만 곧 바이너리로 이동하려고합니다.) 그러나 데이터는 가변 길이 레코드로 구성되며 정렬을 위해 qsort에 레코드의 길이를 알려야합니다. 이것을 표준화 할 방법이 있습니까? 내가 생각할 수있는 유일한 방법은 다소 복잡하다 : 내 프로그램은 현재 줄 바꿈 문자 (ascii로 '10')에 도달 할 때까지 버퍼에서 읽으며 각 문자를 다른 배열로 전송한다. 줄 바꿈 (입력 파일의 구분 기호)을 찾으면 해당 레코드의 버퍼에 남아있는 공백 수를 채 웁니다 (레코드 크기는 30으로 설정 됨). 이렇게하면 qsort를 제공하기 위해 고정 된 크기의 레코드로 가득 찬 버퍼로 끝나야합니다.버퍼에서 가변 길이 레코드 읽기 이상한 메모리 문제

필자의 접근 방식에는 몇 가지 문제점이 있다는 것을 알고 있는데, 그 중 하나는 단지 서툴고 다른 하나는 레코드 크기가 30보다 클 수 있지만 일반적으로 훨씬 적다는 것입니다. 이 작업을 수행하는 더 좋은 방법이 있습니까?

마찬가지로 현재 코드도 작동하지 않습니다. 디버깅 할 때 한 버퍼에서 다른 버퍼로 문자를 전송하는 것처럼 보이지만 버퍼를 인쇄하려고하면 첫 번째 레코드 만 포함됩니다.

FILE *fp; 
unsigned char *buff; 
unsigned char *realbuff; 
FILE *inputFiles[NUM_INPUT_FILES]; 
buff = (unsigned char *) malloc(2048); 
realbuff = (unsigned char *) malloc(NUM_RECORDS * RECORD_SIZE); 

fp = fopen("postings0.txt", "r"); 
if(fp) 
{ 
    fread(buff, 1, 2048, fp); 


    /*for(int i=0; i <30; i++) 
    cout << buff[i] <<endl;*/ 

    int y=0; 
    int recordcounter = 0; 

    //cout << buff; 
    for(int i=0;i <100; i++) 
    { 
     if(buff[i] != char(10)) 
     { 
      realbuff[y] = buff[i]; 
      y++; 
      recordcounter++; 
     }   
     else 
     { 
      if(recordcounter < RECORD_SIZE) 
       for(int j=recordcounter; j < RECORD_SIZE;j++) 
       { 
        realbuff[y] = char(0); 
        y++; 
       } 
      recordcounter = 0; 
     } 
    } 

    cout << realbuff <<endl; 
    cout << buff; 
} 
else 
    cout << "sorry"; 

가 대단히 감사합니다, BSG

+1

사람들이 당신을 도우려는 경우 다음 번에 코드를 읽을 수 있도록주의하십시오. –

+1

'qsort '는 어디에 있습니까? (왜냐하면 당신은 이미 C++을 사용하고 있기 때문에 왜'std :: sort'를 쓰지 않을까요?) – kennytm

+0

"y"가 결코 리셋되지 않기 때문에 "realbuff"에 바인딩을 쓰고있을 수도 있습니다. – YeenFei

답변

1

만 (말처럼) 고정 길이 레코드에서 작동 할 수있는 qsort가 기능 :

여기 내 코드입니다. 가변 길이 레코드를 정렬하려면 포인터 배열을 필요로하고 qsort에 포인터 배열을 정렬하십시오. 포인터가 데이터의 큰 덩어리보다 훨씬 더 빨리 움직이기 때문에 이것은 더 효율적일 수도 있습니다.

std :: sort에서도 마찬가지입니다. 이는 유형 안전성 때문에 권장됩니다. 세 번째 매개 변수로서 포인터를 인수로 사용하는 비교 술어 (함수보다 작음)를 제공해야합니다.

+0

제안 해 주셔서 감사합니다. 나는 포인터의 배열을 만들고 각 레코드의 시작 부분을 가리켰다. 그러나 문자의 배열에 있기 때문에 각 포인터는 포인터가 가리키는 곳부터 시작하여 전체 배열을 가리킨다. 배열을 인쇄 할 때 배열 전체를 여러 번 인쇄합니다. 각 포인터가 하나의 레코드 만 가리 키도록하려면 어떻게합니까? 다시 말하지만, 각각은 레코드의 시작 부분을 가리키고 있지만 버퍼의 나머지 부분은 그것이 가리키는 문자열의 일부라고 생각합니다. 고마워, bsg. – bsg