2012-09-11 4 views
5

프로그래밍 클래스의 linux에서 head 및 tail 명령을 다시 작성하려고합니다. 방금 ​​C를 사용하기 시작 했으므로 메모리와 포인터를 할당하는 아이디어에 익숙하지 않습니다. 왜 이것이 작동하지 않는지 궁금합니다.C 기본 헤드 명령

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

int main(int argc,char **argv){ 

    /* Checks if correct amount of arguements */ 

    if(argc != 2 || argc != 4){ 
     printf("Usage: %s head <file> \n Or: head <file> -n <number of characters>", argv[0]); 
     exit(-1); 
    } 

    if(strcmp(argv[1], "-n" != 0)){ 
     char fileName[strlen(argv[1])] = argv[1]; 
    } 
} 

//Compile error on char fileName[strlen(argv[1])] = argv[1]; 

추가적인 통찰력이 도움이 될 것입니다.

+1

'fileName'은 또한 그 둘러싸는 블럭 안에서만 볼 수 있습니다.이 경우에는'if' 문의 긍정 분기입니다. – gcbenison

+2

'argc'가 2이면 4와 같지 않으며 4와 같지 않으면 2가 아니므로 사용법 메시지 만 보게됩니다. 2, 4, then ... –

+0

GCC 커맨드 라인에서'-std = c99'를 지정 했습니까? VLA (가변 길이 배열)를 허용하도록 컴파일러를 얻으려면 여전히해야합니다. –

답변

2

우선 가장 먼저 사용하는 것이 인수 검사와 일치하지 않습니다. 용도에 따라, 당신이 중 하나를 사용합니다 argv[1]항상 파일 이름이다, 즉

head <filename> 
head <filename> -n <count> 

argv[2] 두 개 이상의 인자가있는 경우 -n로 설정해야 할 것입니다. 당신은 그것을 변경할 필요가 없습니다

char *fileName = argv[1]; 

: 당신이 블라스 (가변 길이 배열)를 사용하지 않으려면

둘째, 당신은 아마 같은과 파일 이름 인수에 대한 포인터를 설정해야합니다 모두 (아마도 fopen으로 전달할 예정이므로) 다른 복사본을 만들려고 노력하는 것은 낭비입니다.

또한 if 문은 or으로 잘못되었으므로 and이어야합니다. argc은 2가 아니거나 4가 아니어야 함을 보증합니다. 동시에 둘 다 같을 수 없기 때문입니다.

char fileName[strlen(argv[1])+1]; 
strcpy(fileName, argv[1]); 

또는 (당신이 문자열의 복사본을 만들 whant하지 않는 경우) : 내가 작성하는 것이 좋습니다 생각

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

static int usage (void) { 
    printf ("Usage: head <file>\n"); 
    printf (" or: head <file> -n <number of characters>\n"); 
    return -1; 
} 

int main (int argc,char *argv[]) { 
    char *fileName; 
    int lineCount; 

    // Checks if correct arguments 

    if ((argc != 2) && (argc != 4)) return usage(); 

    if ((argc == 4) && (strcmp(argv[2], "-n" != 0)) return usage(); 

    // Get file spec and line count 

    fileName = argv[1]; 

    lineCount = (argc == 2) ? 10 : atoi (argv[3]); // or strtol for purists 
    if (linecount < 0) lineCount = 0; 

    // Now go ahead and implement the logic for head. 

} 
+0

그리고이 접근법에서'fileName'은 argv [1]의 딥 카피가 아니라 _not_ argv [1]와 내용을 공유하는 포인터 일뿐입니다. argv []는 대개 할당 해제되지 않기 때문에 이것은 괜찮습니다. 다른 상황에서는 C의 "잡았다"중 하나입니다. – gcbenison

+2

"보통"할당이 해제되지 않았습니까? 적어도 "main"이 반환 될 때까지 (또는 프로그램이 다른 방법으로 종료 할 때까지) "never"라고 말할 것입니다. – paxdiablo

3

:

내가 좋아하는 뭔가를 시작할 것

char* fileName = argv[1]; 
+2

복사본을 수정하지 않는 한 논쟁의 사본을 만드는 것이 중요하지 않으므로 두 번째 제안은 훨씬 더 합리적인 것입니다. –

+0

상황에 따라 다르지 않습니까? 저자는 어떤 이유로 사본을 만들려고 했으므로 의도적으로 작성했을 수 있으며이 문자열을 어딘가에 수정하려고합니다. – Tutankhamen

+0

'head'의 코드에서 파일 이름에 가장 적합한 방법은 파일을 여는 것입니다 그것, 그리고 그것을 위해, 당신은 사본이 필요하지 않습니다 (원본은해야합니다). 어떤 경우에는 이름을 복사하고 편집해야 할 필요가 있습니다. 예를 들어, 일종의 '컴파일러'가 있다면 입력 파일의 확장자를 변경하여 출력 파일을 지정할 수 있습니다.그렇다면 전체 문자열의 사본을 만들고 사본을 편집하는 것이 좋습니다. 왜냐하면 공개 호출 및 오류보고와 같은 항목의 입력 파일 이름이 여전히 필요하기 때문입니다. –