2014-05-21 2 views
1

는 기본적으로 나는이 데이터 구조를 가지고 : 그 변수에 내가 파일에서 읽은 문자열을 걸었습니다 (malloc에를 사용하여 str을위한 공간을 할당 할어떻게 반환 할 수 있습니다 - C

typedef struct Data { 
    char *str; 
    int n; 
} TData, *AData; 

솔직히 말해서 제 질문의 주제를 고려하는 것이 중요하지 않습니다.) 따라서, 나는 함수 TData InitData(const char *file_name) 생성 :

int main(int argc, const char * argv[]) { 
    TData data; 
    if(!(data = ReadExpression(argv[1]))) { 
     return 1; 
    } 
    // I do something with my data and the program ends. 
    return 0; 
} 

내가 return 문이 유효 할 수있는 방법 : 내 '주()'함수에서 지금

TData InitData(const char *file_name) { 
    TData data; 

    data.str = malloc(1024); 
    if (!data.str) { 
     printf("Allocation error!\n"); 
     // I have no idea what to return here in order to exit the function. 
     return (...); 
    } 

    return data; 
} 

를,이 같은 통화 뭔가를 만들 것 InitData 함수에? 나 :

나는 다른 방법으로, 아마 권장되는 방법 중 하나는 유형 AData의 매개 변수로 InitDatamain에서 TData data을 보내 int에 함수의 유형을 변경 (int InitData(const char *file_name, AData data) 같은으로 초래)하는 것을 알고 단순히 AData을 사용하십시오.

+0

'return NULL;'아마도? malloc이 그렇듯이. 물론 데이터를'* Tdata'에 대한 포인터로 만들어야합니다. – Evert

+0

함수가'TData' 타입이기 때문에 작동하지 않습니다. 'NULL'을 반환하려면 'void *'또는 포인터 여야합니다. –

+1

자신의 구조에 대한 의미를 직접 정의합니다. 그래서 전리품 가치는 무엇입니까, 아니면 아무 것도 없습니까? 나는'(TData) {0, 0}'을 추측 할 것입니다. 또한 구조체를'typedef struct data {size_t len; char data []} data;'로 정의하고 항상 힙에 할당하는 것을 고려하십시오. 어쨌든 typedef 뒤에 poiners를 사용하지 않는 것은 위험합니다. – Deduplicator

답변

3
  • 일반적으로 구조체를 값이 아닌 포인터 매개 변수로 전달하십시오.
  • 일반적으로 복잡한 함수를 작성할 때 오류에 대한 반환 값을 예약하십시오.

그래서 귀하의 경우, 같은 기능을 다시 다음 부울 더 자세한 오류 코드에 대한 열거로 대체 될 수

bool InitData (TData* data, const char *file_name); 

. 현재 함수 결과는 "ok"또는 "error"입니다.

1

C는 그래서 일반적으로 당신이 무엇 InitData의 반환 값은 다음 오류/성공 플래그이며, TData 구조는 포인터를 통해 반환

int InitData(const char *file_name, TData *returnedData) { ... } 

입니다 붙박이 여러 값 반환이 없습니다.

+0

오류 반환 신호를 보낼 수 없다는 사실을 알게된 직후 바로 그 생각을 사용하는 것이 좋습니다. 또한 같은 질문에 말했다. –

1

C에 많이하지 않았지만 많은 기능은 다음과 같습니다 : 개체를 할당하고 함수 내에서 작성되는 참조로 전달하는 것이

int foo(intargs, outargs); 

이 뒤의 일입니다.

함수의 반환 값은 enum 또는 이와 비슷한 값으로 비교할 수 있습니다.

0

그냥 정상으로 data를 반환하지만, 읽을 main()에 코드를 변경 :

data = ReadExpression(argv[1]); 
if (!data.str) { 
    return 1; 
} 

당신은 struct 대신 스칼라 값을 반환 할 수 없으며, 귀하의 질문에 당신은 이미 당신이 사용할 수있는 알고 제안 포인터가 아니지만 선택하지 않으므로 가장 간단한 대체 방법입니다.

+0

이것은 잘못된 프로그램 디자인입니다. 호출자가 구조체의 멤버에 대해 알고 있으면 호출자가 할당을 시작하는 이유는 무엇입니까? 개인 캡슐화를 사용하도록 노력해야합니다. – Lundin

+0

@ Lundin : 그건 내 프로그램이 아니야. OP는 이런 식으로하는 방법을 묻습니다. 캡슐화 이외의 기능을 더 많이 사용하기 때문에 "호출자가 할당을 시작할 수없는 이유는 무엇입니까?" 할당을 별도의 함수로 옮기면'main()'을 좀더 읽기 쉽도록 만들 수 있고, 같은 연산을 다른 곳에서 수행해야하거나'main()'에서 두 번 이상 수행해야한다면 중복을 피할 수 있습니다. –

+0

그는 TData가 무엇인지를 아는 코드 모듈 안에 malloc을 캡슐화하여 적절한 객체 지향 디자인을 시도하고 있습니다. 코드 모듈에서 자세한 검사를 제거하면 캡슐화가 완전히 중단되고 OO 프로그램 디자인을 배우는 데 도움이되지 않습니다. – Lundin

1

나는 마이크로 바이러스가 제안한 방식을 좋아합니다. 데이터를 매개 변수로 받아들이는 것도 다중 스레드 코드 안전을 위해 사용됩니다.또한 호출 코드를 체크인하기 위해 조작 결과를 리턴 할 수 있습니다. TData는 포인터가 아니므로 NULL로 설정할 수 없습니다. 이는 내가 생각하는 잘못된 케이스를 말하는 한 방법입니다. 그러나 여기에도 또 다른 문제가 있습니다! InitData의 TData 데이터는 지역 변수이므로 함수가 반환 될 때 복사해야합니다. 필자가 생각하는 성능 문제는 좋은 습관이 아닙니다. 필자는 객체를 매개 변수 (예 : 포인터)로 받아 들여 함수의 결과를 호출 코드에 반환하고 데이터의 유효성을 검사합니다. 데이터 NULL을 설정하거나 설정할 수는 없지만 결과 값을 반환하면 데이터 객체 자체를 확인하지 않고 모든 항목이 삭제됩니다.

+0

최적화 컴파일러는 객체 복사를 생략하고 포인터로 효율적으로 스택 내에서 스택을 생성하도록 할 수 있어야합니다. – MicroVirus

+0

ROV (http://en.wikipedia.org/wiki/Return_value_optimization)에 대해 이야기하고 있다면 맞습니다. 그러나 이것이 C의 경우인지 확실하지 않습니다. – Deniz

+0

인정합니다. C가 갖고 있다고 생각합니다. 비슷한 최적화이지만 빠른 Google 검색은 아무 것도 찾지 않습니다. 그것은 C++ 관련 기사로 흩어져 있습니다. 그래서 어쩌면 내가 틀렸어. C는 그렇게하지 않았어. – MicroVirus

0

if (!data.str) 결과에 따라 데이터 구조체에 플래그를 설정할 수 있으며 항상 data을 반환 할 수 있습니다. 그런 다음 어떤 일이 발생했는지 알고 싶을 때마다 플래그를 확인하십시오. 당신은이 같은 또는 유사한 작성할 수 :

그냥 명확하게

`typedef struct Data 
{ 
    char *str; 
    int n; 
    char myflag; 
    const char *file_name; 
} TData, *AData;` 

`void InitData(TData *data) 
{ 
    data.str = malloc(1024); 
    if (!data.str) 
    { 
     printf("Allocation error!\n"); 
     myflag=0; 
    } 
    else 
    { 
     myflag=1; 
    } 
    return data; 
}` 

을뿐만 아니라 주석을 참조하십시오. 다른 관점을주고 싶었습니다.

+0

객체 지향적 인 것들을 좋아한다면 ... – jakz

+1

메모리 할당 오류가 구조체의 데이터와 관련이 없으므로 거기에 없어야합니다. – Lundin

+0

데이터와 관련이있는 경우 스스로 결정하십시오. 데이터가 원본 데이터이거나 원래 데이터와 일종의 할당 정보가 더해진 것입니다. 두 대안 모두 유효합니다. – jakz

관련 문제