2015-01-29 6 views
-1

c에서 wc 명령을 다시 생성하고 컴퓨터 코드 (코어 파일 또는 컴파일 된 c)가 포함 된 파일에서 적절한 수의 단어를 가져 오는 데 문제가 있습니다. 로그 된 단어의 수는 wc가 리턴 한 양보다 항상 90 % 정도 부족합니다.기계 코드를 반복하는 데 문제가 있음

135  742 360448 /home/cpmcgrat/53/labs/lab-2/core.22321 
    231 1189 192512 /home/cpmcgrat/53/labs/lab-2/core.26554 
    5372 40960 365441 /home/cpmcgrat/53/labs/lab-2/file 
    24  224 12494 /home/cpmcgrat/53/labs/lab-2/frequency 
    45  116  869 /home/cpmcgrat/53/labs/lab-2/frequency.c 
    5372 40960 365441 /home/cpmcgrat/53/labs/lab-2/lineIn 
    12  50 1013 /home/cpmcgrat/53/labs/lab-2/lineIn2 
     0  0  0 /home/cpmcgrat/53/labs/lab-2/lineOut 
    39  247 11225 /home/cpmcgrat/53/labs/lab-2/parseURL 
    138  318 2151 /home/cpmcgrat/53/labs/lab-2/parseURL.c 
    41  230 10942 /home/cpmcgrat/53/labs/lab-2/roman 
    66  162 1164 /home/cpmcgrat/53/labs/lab-2/roman.c 
    13  13  83 /home/cpmcgrat/53/labs/lab-2/romanIn 
    13  39  169 /home/cpmcgrat/53/labs/lab-2/romanOut 
     7  6  287 /home/cpmcgrat/53/labs/lab-2/URLs 
    11508 85256 1324239 total 

샘플 (출력을 재 구축 참고로

여기

컴파일 문

gcc -ggdb wordCount.c -o wordCount -std=c99 

wordCount.c

/* 
* Author(s) - Colin McGrath 
* Description - Lab 3 - WC LINUX 
* Date  - January 28, 2015 
*/ 

#include<stdio.h> 
#include<string.h> 
#include<dirent.h> 
#include<sys/stat.h> 
#include<ctype.h> 

struct counterStruct { 
    int newlines; 
    int words; 
    int bt; 
}; 

typedef struct counterStruct ct; 

ct totals = {0}; 

struct stat st; 

void wc(ct counter, char *arg) 
{ 
    printf("%6lu %6lu %6lu %s\n", counter.newlines, counter.words, counter.bt, arg); 
} 

void process(char *arg) 
{ 
    lstat(arg, &st); 
    if (S_ISDIR(st.st_mode)) 
    { 
     char message[4056] = "wc: "; 
     strcat(message, arg); 
     strcat(message, ": Is a directory\n"); 
     printf(message); 
     ct counter = {0}; 
     wc(counter, arg); 
    } 
    else if (S_ISREG(st.st_mode)) 
    { 
     FILE *file; 
     file = fopen(arg, "r"); 
     ct currentCount = {0}; 
     if (file != NULL) 
     { 
      char holder[65536]; 
      while (fgets(holder, 65536, file) != NULL) 
      { 
       totals.newlines++; 
       currentCount.newlines++; 
       int c = 0; 
       for (int i=0; i<strlen(holder); i++) 
       { 
        if (isspace(holder[i])) 
        { 
         if (c != 0) 
         { 
          totals.words++; 
          currentCount.words++; 
          c = 0; 
         } 
        } 
        else 
         c = 1; 
       } 
      } 
     } 
     currentCount.bt = st.st_size; 
     totals.bt = totals.bt + st.st_size; 
     wc(currentCount, arg); 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    if (argc > 1) 
    { 
     for (int i=1; i<argc; i++) 
     { 
      //printf("%s\n", argv[i]); 
      process(argv[i]); 
     } 
    } 

    wc(totals, "total"); 

    return 0; 
} 

샘플 화장실 출력 프로젝트 정보를합니다. /워드) 개수 :

139  76 360448 /home/cpmcgrat/53/labs/lab-2/core.22321 
    233 493 192512 /home/cpmcgrat/53/labs/lab-2/core.26554 
    5372 40960 365441 /home/cpmcgrat/53/labs/lab-2/file 
    25  3 12494 /home/cpmcgrat/53/labs/lab-2/frequency 
    45 116 869 /home/cpmcgrat/53/labs/lab-2/frequency.c 
    5372 40960 365441 /home/cpmcgrat/53/labs/lab-2/lineIn 
    12  50 1013 /home/cpmcgrat/53/labs/lab-2/lineIn2 
    0  0  0 /home/cpmcgrat/53/labs/lab-2/lineOut 
    40  6 11225 /home/cpmcgrat/53/labs/lab-2/parseURL 
    138 318 2151 /home/cpmcgrat/53/labs/lab-2/parseURL.c 
    42  3 10942 /home/cpmcgrat/53/labs/lab-2/roman 
    66 162 1164 /home/cpmcgrat/53/labs/lab-2/roman.c 
    13  13  83 /home/cpmcgrat/53/labs/lab-2/romanIn 
    13  39 169 /home/cpmcgrat/53/labs/lab-2/romanOut 
    7  6 287 /home/cpmcgrat/53/labs/lab-2/URLs 
11517 83205 1324239 total 

공지 사항 처음 두 파일 (코어 파일)뿐만 아니라 로마 파일 parseURL 파일에서 단어 수의 차이 (초 INT) (기계 코드, 확장자).

+0

'file core.22321'은 무엇을 반환합니까? –

답변

2

C 문자열은 길이를 저장하지 않습니다. 그들은 단일 NUL (0) 바이트로 종료됩니다.

결과적으로 strlenNUL에 도달 할 때까지 전체 문자열을 문자 단위로 스캔해야합니다. 즉,이한다 :

for (int i=0; i<strlen(holder); i++) 

필사적으로 비효율적 : holder의 모든 문자에 대해, 그것은 i 범위에 아직 있는지 여부를 테스트하기 위해 holder의 모든 문자를 계산해야합니다. 그러면 간단한 선형 Θ(N) 알고리즘이 Θ(N2) 사이클 버너로 변환됩니다.

그러나이 경우 이진 파일에는 대개 NUL 개의 문자가 포함되므로 잘못된 결과도 생성됩니다. strlen은 "line"의 길이가 아니라 처음으로 NUL이 어디에 있는지 알려주므로 파일에서 많은 바이트를 건너 뛰게됩니다. (밝은면에서는 스캔 속도가 2 배 빨라지지만 잘못된 결과를 더 빠르게 계산하는 것은 실제로 좋은 결과가 아닙니다.) fgets 인터페이스는 얼마나 많은 정보를 알려주지 않기 때문에 fgets을 사용하여 이진 파일을 읽을 수 없습니다 그것은 읽었다. 대신 PosX 2008 getline 인터페이스를 사용하거나 fread으로 이진 입력을 할 수 있습니다.이 방법은 더 효율적이지만 개행을 직접 계산해야합니다. (세상에서 가장 나쁜 것은 아니며 그 숫자도 잘못 나온 것 같습니다.)

또는 물론 한 번에 한 문자 씩 fgetc으로 읽을 수 있습니다. 학교 운동을 위해서는 나쁜 해결책이 아닙니다. 결과 코드는 작성하고 이해하기 쉽고, fgetc의 일반적인 구현은 FUD가 나타내는 것보다 더 효율적입니다.

+0

인터넷이 시작된 지 얼마되지 않아 (80 년대 후반, 90 년대 초반 거의 인터넷이 있기 전까지) 루프 상태에서 strlen()이 들어있는 SunOS'strstr()'버그가 발생했습니다. 장난감에 대해서는 괜찮 았지만 20 KiB 버퍼로 작업을 시작했을 때 프로그램 성능이 떨어졌습니다.나는 SunOS에서'strstr()'의 커스텀 구현을 사용했다. 고객이 사용했던 HP-UX 머신에는 문제가 없었으며, SunOS의 후속 버전을 추가하지는 않았다. –

+0

@JonathanLeffler : 정말 영리한 컴파일러는 strlen 호출을 최적화 할 수 있지만, 인수가'const'로 선언되지 않은 경우 실제로 그렇게 영리해야합니다. 오히려 최근에 나는'str :: find (word) == 0'이'str'이'word'로 시작 하는지를 검사하는 일반적인 관용구라고 생각한 중요한 함수의 퍼포먼스를 엄청나게 향상 시켰습니다 (다른 생각할만한 최적화). 최적화가 중요하지만 교육은 더 중요합니다. – rici

관련 문제