2013-03-26 6 views
-1

UNIX wc 명령의 간단한 구현을 수행하고 있으며 매우 이상한 문제가 있습니다. 49 행에서 printf를 제거하면 프로그램이 제대로 작동하지 않습니다. 나는 많은 일을 시도했지만 그들 중 누구도 일하지 않았습니다. 프로그램은 작동하지만 출력물은 내가 원하는 것이 아니라 원하는 것입니다.printf의 C 프로그램의 비정상적인 동작

#include<stdio.h> 
#include<stdlib.h> 
#include<fcntl.h> 
#include <string.h> 
#include<errno.h> 
#include<sys/stat.h> 

int *counter(FILE* file) { 

    // Function counter - counts the number of lines, words and symbols 
    int nsymbols = 0, nwords = 0, nlines = 0; 
    char c; 
    while (EOF != (c = fgetc(file))) { 
     nsymbols++; 
     if(c == ' '){ 
      nwords++; 
     } 
     if(c == '\n'){ 
      nlines++; 
      nwords++; 
     } 
    } 
    int count[] = {nlines, nwords, nsymbols}; 
    return count; 
} 

int main(int argc,char* argv[]) { 
    if(argc == 1) { 
     int *counted; 
     counted = counter(stdin); 
     printf("\t%d \t%d \t%d\n", counted[0], counted[1], counted[2]); 
    } 
    else{ 
     int i,k, bool = 0; 
     int total[] = {0,0,0}; 
     char c = ' ', w = ' ', l = ' '; 

     for(i = 1; i < argc; i++) { 

      // Cheking if there are some options activated 
      if(strchr(argv[i], '-')){ 
       if(strcmp(argv[i], "-")==0){ 
        continue; 
       } 
       if(strchr(argv[i], 'l')) { 
        l = 'l'; 
       } 
       if(strchr(argv[i], 'w')) { 
        w = 'w'; 
       } 
       if(strchr(argv[i], 'c')){ 
        c = 'c'; 
       } 
       bool = 1; 
      } 
     } 
     if(!bool) { 
      // If none of them are activated from the user, automatically activates all of them 
      l = 'l'; 
      w = 'w'; 
      c = 'c'; 
     } 
     printf("%c %c %c", l,w,c); 

     for(i = 1; i<argc; i++){ 

      if(strcmp(argv[i], "-") == 0){ 
       int *counted; 
       counted = counter(stdin); 
       for(k = 0; k < 3; k++){ 
        total[k] += counted[k]; 
       } 
       if(l == 'l') 
        printf("\t%d", counted[0]); 
       if(w == 'w') 
        printf("\t%d", counted[1]); 
       if(c == 'c') { 
        printf("\t%d", counted[2]); 
       } 
       printf(" %s\n", "-"); 
      } 
      else{ 
       if(strchr(argv[i], '-')) 
        continue; 
       FILE* file = fopen(argv[i], "r"); 
       if(file == NULL) { 
        fprintf(stderr, "%s : %s\n", argv[i], strerror(errno)); 
        return 1; 
       } 
       struct stat checker; 

       if(stat(argv[i], &checker) < 0) { 
        return 2; 
       } 

       if(checker.st_mode & S_IRUSR) { 
       } 
       else{ 
        fprintf(stderr, "%s : %s\n", argv[i],strerror(EACCES)); 
        return 3; 
       } 

       int *counted; 
       counted = counter(file); 

       for(k = 0; k < 3; k++){ 
        total[k] += counted[k]; 
       } 

       if(l == 'l') 
        printf("\t%d", counted[0]); 
       if(w == 'w') 
        printf("\t%d", counted[1]); 
       if(c == 'c') { 
        printf("\t%d", counted[2]); 
       } 
       printf(" %s\n", argv[i]); 
      } 
     } 
     if(l == 'l') 
      printf("\t%d", total[0]); 
     if(w == 'w') 
      printf("\t%d", total[1]); 
     if(c == 'c') { 
      printf("\t%d", total[2]); 
     } 
     printf(" total\n"); 
    } 
    return 0; 
} 
+2

프로그램이 끝날 때까지 유지하고 있기 때문에 ...의 malloc 또는은 calloc을 통해 동적 메모리 할당을 사용하여 작성 'counter'의 _local_ 배열. 이것은 정의되지 않은 동작입니다. –

+5

49 호가 어느 것입니까? –

답변

1

가 제자리에 printf와 함께 작동하는 이유는 우연의 일치 : 당신이 지역에 대한 포인터를 반환하기 때문에 당신의 프로그램이 동작을 정의되지 않은있다. 지역 변수에 할당 된 메모리는 함수에서 반환 될 때 재사용되므로 함수 외부의 해당 메모리를 참조하면 가비지 값에 액세스하게됩니다. 그러나 호출자가 스택을 사용하는 방식 때문에 특정 지점이 재사용되지 않는 경우가 있습니다. 이 경우 프로그램은 작동하는 것처럼 보이지만 코드를 조금만 변경해도 잘못된 결과가 나오거나 충돌이 발생할 수 있습니다. 이런 식으로이 기능을

void counter(FILE* file, int count[]) { 
    int nsymbols = 0, nwords = 0, nlines = 0; 
    char c; 
    while (EOF != (c = fgetc(file))) { 
     nsymbols++; 
     if(c == ' '){ 
      nwords++; 
     } 
     if(c == '\n'){ 
      nlines++; 
      nwords++; 
     } 
     } 
     count[0] = nlines; 
     count[1] = nwords; 
     count[2] = nsymbols; 
} 

및 전화 :

다음과 같이 코드를 변경

int counted[3]; 
counter(file, counted); 

이 문제가 해결됩니다.

+0

대단히 감사합니다 !!! 너는 나에게서 맥주를 ​​마셨다 !!! : D – user2211599

+0

고마워요! 내 프로젝트가 완료되었습니다. 덕분에! 하지만 이런 종류의 일들 때문에 나는 C를 좋아하지 않으며 학교에서만 이것을하고 있습니다. Java는 항상! :디 – user2211599

0

여기

int count[] = {nlines, nwords, nsymbols}; 
    return count; 

count 배열 범위를 벗어나 그 수명 함수가 리턴 한 후 종료한다. 메모리를 정적 또는 malloc으로 만들면 둘 다 함수의 실행 시간을 초과하는 메모리의 수명을 연장 할 수 있습니다.

0

문제는 로컬 배열 인 배열 count을 반환한다는 것입니다. 너는 그렇게 할 수 없다. 나는 정의되지 않은 행동이 될 것이다. 모든 일이 일어날 수 있습니다!

배열의 크기가 고정되어 있으므로이를 선언하고 인수로 함수 counter()에 전달해야합니다.

0

정적 배열을 만들거나 힙에서 만든 배열이 포인터를 사용하여 다음 당신은 반환하고