2016-06-10 4 views
-3

다음 연결된 목록 코드에 문제가 있습니다. 그러나 무엇인지 모르겠습니다. 누군가가 올바른 방향으로 나를 가리킬 수 있을까요? 나는이 코드를 레코드를 업데이트하는 좀 더 큰 코드에서 사용하지만 "새 레코드 만들기"섹션에는 도달하지 못합니다. 마치 주 코드가 헤드 포인터를 업데이트하는 것처럼 보이므로 항상 유리한 비교가됩니다.연결된 목록이 제대로 작동하지 않습니다. 머리가 대신 업데이트됩니다.

미리 감사드립니다. 나는 문제가 무엇인지 파악하려고 노력하면서 내 머리를 깎아 내고 있었다. 내가 함께 메인에서이 전화 드렸습니다

struct l_list *find_name(const char *name) 
{ 
    struct l_list *tmp=0; 
    if(records==0) { // First record 
     head=new l_list; 
     head->name=name; 
     head->next=0; 
     tail=head; 
     records++; 
     return head; 
    } 
    else { 
     tmp=head; 
     while(tmp!=0) 
     { 
     if(!std::strcmp(tmp->name,name)) 
     { 
      cout << "Returning existing record with value: " << tmp->number << " name:" <<  tmp->name << endl; 
      return tmp; 
     } 
     tmp=tmp->next; 
    } 
    // No first and no existing records 
    cout << "Creating new record" << endl; 
    tail->next=new l_list; 
    tail=tail->next; 
    tail->name=name; 
    tail->next=0; 
    records++; 
    return tail; 
} 

: 구조체 기록 * TMP = find_name ("최대");

다음 :

tmp->number=1; 

을 심지어 이름 업데이트 : 내가 구조체를 일단

tmp=find_name("Eva"); 

내가 지금처럼 업데이트에 문자열을 전달하여 그래서

tmp->name="Peter"; 

을 이 함수는 새 레코드를 만들어 반환하거나 기존 레코드를 제공하고 반환합니다. 문제는 출력에서 ​​분명하지 않을 수도 있지만 메인 (for;) 루프에 넣으면 이 엉망이됩니다. 다음과 같이

구조체는 다음과 같습니다

struct records { 
     const char *name; 
     struct records *next; 
} 

관련 프로그램 코드는 다음과 같습니다

struct record { 
     const char *name; 
     struct record *next; 
}; 
struct record *head; 
struct record *tail; 

struct record *find_name(const char *name) 
{ 
     struct record *tmp=0; 

     if(record_count==0) { // First record 
     cout << "Creating first record" << endl; 
     head=new record; 
     head->name=name; 
     head->next=0; 
     tail=head; 
     record_count++; 
     return head; 
     } else { 
     tmp=head; 
     while(tmp!=0) { 
     if(!std::strcmp(tmp->name,name)) { 
     cout << "Returning existing record with value: " << "name: " << name << "tmp->name: " << tmp->name << endl; 
     return tmp;} 
     tmp=tmp->next; 
     } 

     // No first and no existing records 
     cout << "Creating new record" << endl; 

     tail->next=new record; 
     tail=tail->next; 
     tail->name=name; 
     tail->next=0; 
     record_count++; 
     return tail; 
     } 

} 

int main(int argc, const char *argv[]) 
{ 
struct record *tmp=0; 

      if(something is true) { 
      //Return or create a new user 
      tmp=find_name("Peter"); 

      } else { 
      tmp=find_name("Unknown"); // Hold 1 unknown person in database 
      } 
} 

나는 그대로하지만 난 큰 부분에서 추출했다가 컴파일 가능한 아니다 알고있다.

+3

디버거를 사용하여 코드를 단계별로 실행하는 방법을 배워야 할 수도 있습니다. 좋은 디버거를 사용하면 한 줄씩 프로그램을 실행하고 예상 한 곳에서 벗어난 곳을 볼 수 있습니다. 프로그래밍을 할 때 필수적인 도구입니다. 추가 읽기 : ** [작은 프로그램을 디버깅하는 방법] (http://ericlippert.com/2014/03/05/how-to-debug-small-programs/) ** – NathanOliver

+1

std :: list ? 아니면 허용되지 않습니까? – stefaanv

+0

당신이 언급 한 문제를 보여주는 방식으로 이것을 사용하는 코드를 게시하십시오. – molbdnilo

답변

0

records 구조가 무엇인지 알려주지 않았으므로 누구나 정답을 줄 수있는 방법이 없습니다. 함수가 잘못 작동하게하는 코드 예제를 제공하지 않으면 더 이상 불가능 해졌습니다.

name 요소가 char * 포인터 인 경우이 동작을 쉽게 얻을 수 있습니다. 예를 들어 :

  1. 호출 코드는 버퍼에 이름을두고, 및 find_name를 호출합니다.
  2. find_name은 개체의 name 요소에 버퍼의 주소을 저장합니다. 따라서 name은 버퍼가 현재 그리고 미래에 포함되는 모든 것을 가리 킵니다.
  3. 호출 코드는 동일한 이름의 버퍼에 새로운 이름을 넣습니다. 이것은 자동으로 name 요소가 버퍼를 가리키고 있기 때문에 새로운 이름을 가리킨다는 것을 의미합니다.
  4. 호출 코드가 find_name을 다시 호출합니다.
  5. find_name은 버퍼 내용을 첫 번째 records 개체의 name 요소가 가리키는 문자열과 비교합니다. name 요소에는 호출자가 전달한 버퍼의 주소 (2 단계에서)가 포함되어 있으므로 버퍼를 자체와 비교하고 있음을 의미합니다.결과는 항상 "동등"합니다.

그러나 name은 포인터가 아닙니다.이 경우 전체 답변은 부적절 할 수 있습니다. 모든

+0

그럼 제 대답이 맞을 것 같습니다. 'name'에 문자열을 저장하는 것이 아니라, 호출자가 채워서 함수에 넘겨 준 버퍼에 대한 포인터를 저장합니다. – nugae

+0

struct 형식 및 관련 코드로 업데이트되었습니다. 당신의 대답은 이것이 사실일지도 모르는 것처럼 들린다. main에서 호출하여 문자열 (예 : "Ted")을 find_name에 전달하면 멤버 tmp-> name이 업데이트되어 포인터가 어느 지점에서 느슨해집니다. 그것은 일어나는 것 같습니다. 그렇다면 어떻게 이름을 저장해야합니까? 실제 값을 역 참조 (dereference)하여 복사하여 구성원 tmp-> 이름으로 복사해야합니까? – ATv

+0

사실, find_name()을 채우기 위해 사용하는 함수는 문자열 (std :: string 클래스라고 가정)을 반환합니다. 그게 작동하지 않아야합니까? 다른 방법으로 const char을 처음으로 채울 수 있습니까? – ATv

0

우선은 코드를 읽는 것은 어려운

if(record_count==0) { // First record 
    cout << "Creating first record" << endl; 
    //... 
    } else { 
    tmp=head; 
    //... 

서식을 다음 코드를 사용하지 마십시오. 그것은 프로그래밍 스타일이 아닙니다.

기능 자체가

struct l_list * find_name(const char *name) 
{ 
    struct l_list *tmp = head; 

    wjile (tmp != nullptr && std::strcmp(tmp->name, name) != 0) tmp = tmp->next; 

    if (tmp == nullptr) 
    { 
     cout << "Creating new record" << endl; 
     tmp = new l_list; 
     tmp->name = name;    
     tmp->next = nullptr; 

     if (tail == nullptr) 
     { 
      head = tail = tmp; 
     } 
     else 
     { 
      tail = tail->next = tmp; 
     } 

     records++; 
    } 

    return tmp; 
} 

는 노드가 문자열에 대한 포인터를 포함 할 수 있음을 고려 다음과 같은 방법을 볼 수 있습니다 예를 들어, 문자열 리터럴 또는 힙에서 할당과 같은 정적 저장 기간이.

+0

고마워, 네, 그걸 깨닫기 시작했습니다. 내가 이름을 얻는 데 사용하는 함수는 find_name (function_that_returns_name)이라는 문자열을 반환합니다. 그래서 위와 같이 전달 된 문자열 리터럴을 할당한다면, 그 일을해야합니까? – ATv

관련 문제