문제

다음 코드를 사용하면 매우 이상한 결과를 얻습니다. 마지막 요소의 값이 이전의 모든 배열 요소를 덮어 쓰는 이유는 무엇입니까? 이 Immmediate 문제보다 더 큰 문제가 있다고 생각합니다.

#include <stdio.h>

main()
{
    int i, cases;
    char num[1000000];

    scanf("%d", &cases);
    char* array[cases];

    //store inputs in array
    for(i=0; i<cases; i++)
    {
        scanf("%s", &num);
        array[i] = &num;
    }

    //print out array items and their memory addresses
    for(i=0; i<cases; i++)
    {
        printf("%d %s\n", i, array[i]);  //print (array index) (array value) 
        printf("%d %p\n", i, &array[i]); //print (array index) (array address) 
    }
}

Inputs:
3 <-- number of lines to follow
0   <-- put in array[0]
1   <-- put in array[1]
2   <-- put in array[2]

Outputs
0 3         <-- why is this being overwritten with the last element?
0 0013BCD0
1 3         <-- why is this being overwritten with the last element?
1 0013BCD4
2 3
2 0013BCD8

올바른 솔루션이 없습니다

다른 팁

여기의 상향은 선입니다 array[i] = &num; 당신은 값을 설정합니다 array[i] 주소의 요소 num 정렬; ~부터 array 숯불 배열, 나는 그것이 당신의 num 배열 주소, 저차 바이트는 3입니다.

하지만. 즉, 당신의 Char Num [1000000]은 끔찍한 형태이며, 그렇게해서는 안됩니다. 힙에 할당하고 하늘을 위해 더 적은 숫자를 선택하십시오. 또한 Scanf ( "%S", & num)는 실제로 원하는 것을 제공하지 않습니다. 여기에 힌트가 있습니다. getc () 루프를 사용하여 숫자를 읽습니다. 이것은 scanf ()에 대한 배열의 preallocation을 수행 할 필요가 없습니다.

배열의 모든 색인을 동일한 주소 (char num [10000000];)에 넣기 때문입니다.

동적 할당 (Calloc, Malloc, New 등)으로 이어지는 오류입니다.

건배!

첫 번째 루프 내부에서는 각 입력을 NUM 배열의 다른 요소로 작성해야합니다. 대신 당신은 항상 같은 장소에 글을 쓰고 있습니다. &num.

char* 배열 [cases];

이것은 런타임이 아닌 컴파일 타임에 할당됩니다. 그리고 사례는 초기화되지 않았지만 (어쨌든 역동적으로 작동하기를 원한다고 생각하지만) 메모리를 사전화하거나 Malloc 라이브러리 기능에 익숙해 져야합니다.

바꾸다

//store inputs in array
for(i=0; i<cases; i++)
{
    scanf("%s", &num);
    array[i] = &num;
}

~와 함께

array[0] = num;
//store inputs in array
for(i=0; i<cases; i++)
{
    scanf("%s", array[i]);
    array[i+1] = array[i] + strlen(array[i]) + 1;
}

각 문자열이 사용 가능한 첫 번째 공간으로 스캔하려면 num[], 다음 요소를 설정하십시오 array[] 다음 공간을 가리키기 위해. 이제 당신의 printf() 문자열의 작동이 작동합니다. 원본은 모든 문자열을 시작으로 스캔했습니다. num[].

메모: scanf() 도로와 함께 %s 만큼 나쁘다 gets(), 그것은 때려지는 데이터의 양을 제한하지 않기 때문에. 실제 코드에서 사용하지 마십시오.

바꾸다

    printf("%d %p\n", i, &array[i]); //print (array index) (array address) 

~와 함께

    printf("%d %p\n", i, (void*)(array[i])); //print (array index) (array address) 

저장된 주소를 실제로 인쇄합니다 a[], 요소의 주소보다는 a[]. 캐스트는 필요합니다 %p 포인터로 기대합니다void 따라서 하나를 제공해야합니다.

그게 고정 된 코드 :

#include <stdio.h>

main(void)
{
    int i, cases;

    scanf("%d", &cases);
    char* array[cases];

    //store inputs in array
    for(i=0; i<cases; i++)
    {
        char *num = malloc(100000);
        scanf("%s", num);
        array[i] = num;
    }

    //print out array items and their memory addresses
    for(i=0; i<cases; i++)
    {
        printf("%d %s\n", i, array[i]);  //print (array index) (array value)
        printf("%d %p\n", i, (void*)&array[i]); //print (array index) (array address)
    }
    return 1;
}

당신은 또한 사용할 수 있습니다

char *num = calloc(100000, sizeof(char));

조금 방어 적입니다. 왜 100000이 필요한지 모르겠습니다. Malloc을 사용하여 동적으로 수행 할 수 있습니다. 여기에는 더 많은 작업이 포함되지만 매우 강력합니다.

코드에서 모호한 것은 문자열 %s를 변경하지 않는 NUM의 주소에 저장 한 다음 해당 주소에 배열 [i] 요소를 할당한다는 것입니다. C로 할당하는 것은 참조를 저장하는 것이 아닙니다. 요소 자체를 저장하지 않습니다. 이것은 공간 낭비입니다. 따라서 모든 배열 요소가 주소를 가리키면 (참조 만 저장), 참조의 값은 참조도 변경되므로 모두 2로 변경되는 이유 (게시물에 명시된대로 3이 아님).

C ++가 만들어지는 것 같습니다. 사용자 입력 구문 분석 및 동적 할당은보다 안전하고 산들 바람으로 이루어집니다. C ++로 전환 할 수없는 사용자 인터페이스가있는 시스템을 생각할 수 없습니다.

물론, 이것이 문제로 고통받는 다른 코드에서 발췌 한 테스트 일 뿐이라면 물론 ...


귀하의 코드는 C 초보자에 대한 몇 가지 일반적인 실수와 요즘 그렇게해서는 안되는 일로 고통 받고 있습니다.

내가 올바르게 이해하면 Sereval 사용자 입력 문자열을 저장하려고합니다 (예제 출력은 숫자 만 표시하기 때문에 약간 오도됩니다).

당신은 모든 (케이스 카운트) 포인터를 문자열에 고정시키기 위해 배열을 준비하고 있지만, 하나의 문자열에 대한 메모리 만 예약하고 있습니다. 모든 문자열에 대해 그렇게해야하므로 케이스가 필요합니다. "동적 메모리 할당"레슨 측면에서 물건을 간단하게 유지하려면 그렇게하는 것이 좋습니다. char* array[cases][10000]; 그것은 당신에게 10k 문자의 문자열을 제공합니다.

당신은 아마 배열 요소에 별도의 포인터를 갖고 싶지 않을 것입니다. 해당 요소가 포인터 자체보다 큰 경우 배열의 요소를 정렬하려면 이는 의미가 있습니다. 이 경우 성능의 이득은 큰 덩어리를 이동 (복사)하는 것이 아니라 포인터 (보통 4 바이트) 만 이동해야합니다. 귀하의 경우 int는 4 바이트 길이입니다. 그리고 당신은 어쨌든 정렬하지 않습니다 :)

scanf() 가장 말하는 것은 위험합니다. 두 번째 응용 프로그램에서는 배열 주소에 문자열을 쓰도록 지시합니다. 이것은 단순한 실수 인 것처럼 보이지만 많은 문제를 일으킬 수 있습니다. 당신은 아마 그렇게하고 싶을 것입니다 : scanf("%d", &array[i]); (불행히도, 나는 컴파일러가 없으므로 100% 확실하지 않습니다). 다음 줄을 떨어 뜨립니다 :)


Markdown 전문가에게 질문 : 코드 블록과 목록을 결합하는 것이 왜 그렇게 불가능합니까?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top