2015-01-27 2 views
-2

어떤 이유로 while 루프를 종료 한 후에 배열의 값이 변경되지만 그 이유는 아닙니다. 루프 안에서는 값이 정확하며 배열 (a) 내부에 값을 저장합니다. 이것은 c 다!루프를 종료 한 후 배열의 값이 변경되는 이유는 무엇입니까?

int * readFile() 
{ 
    char file_name[50]; 
    printf("Enter the name of the file to open:\n"); 
    scanf("%s",file_name); 
    FILE *fp; 
    fp = fopen(file_name,"r"); 

    if(fp == NULL) 
    { 
      printf("Sorry but the File you entered cannot be opened\n"); 
      int *b; 
      b[0] = -1; 
      return b; 
    } 

      int *a; 
      int j=0; 
      long int value=0; 
      while (fscanf(fp,"%d",&value)!=EOF) { 
        if((a =malloc(sizeof(long int))) == NULL) 
          printf("not enough memory\n"); 
        a[j]=value; 
        j++; 
      } 
      printf("%d %d %d\n",a[0],a[1],a[2]); 
      int i=0; 
      for(i=0; i<j;i++) 
      { 
        printf("array[%d] = %d\n",i,a[i]); 
      } 
      fclose(fp); 
      return a; 
} 

모든 도움을 주시면 감사하겠습니다.

+0

언어는 유익한 정보입니다. –

+0

이것은 c입니다! 죄송합니다 깜박 했어요 – Jeremy

+0

'if ((a = malloc (size int)) == NULL)'은 정수 크기의 새로운 메모리 블록을 할당합니다. 그런 다음'j> 0 '에 존재하지 않는'j' 번째 슬롯에 씁니다. –

답변

0

if((a =malloc(sizeof(long int))) == NULL)을 수행 할 때 하나의 long int (32 비트 크기)에 대해서만 충분한 메모리를 할당하지만 저장하려는 각 int에 대해 메모리를 할당해야합니다. malloc은 하나의 메모리 블럭을 할당하기 때문에, 얼마나 많은 int를 미리 저장해야 하는지를 알아야합니다. 오버 헤드에 신경 쓸 필요가 없다면 읽을 파일을 통해 예비 실행을하고 읽을 int의 수를 계산하면됩니다 (기본적으로 j 변수).

a =malloc(intCounter * sizeof(long int))) == NULL 여기서 intCounter는 파일 내의 정수의 총수 (j)

또 다른 옵션은 링크 된 목록을 사용하는 것입니다 (즉, 수행하려는 작업에 가깝습니다). 즉, 각 int에 대한 메모리를 할당 할 수 있지만 포인터 정보를 다음 노드에 저장해야합니다. 배열

while 루프의 malloc 호출은 Int의 단일 할당에 저장된 데이터를 덮어 씁니다. 예를 들어 텍스트 파일에서 1 2 3을 읽으면 a에 1을 저장하고, malloc에 ​​다른 메모리 주소를 저장하고, 2를 저장하고, malloc을 사용하고 다른 메모리 주소와 저장소를 만듭니다. 결과는 0, 0, 3입니다.

0

코드 전체에 intlong int의 혼합을 사용했습니다. 당신은 일관된 유형에 정착해야합니다. 내 대답은 int으로 갔다. (fscanf 형식 문자열을 %ld으로 변경 한 경우에도 int의 모든 항목을 long으로 쉽게 변경할 수 있습니다.

현재 루프 주위에 매번 long int의 새 블록을 할당합니다. 이전 루프 반복에서 메모리를 누출하는 것 외에도이 범위를 벗어나 액세스 할 수 있습니다. 또한, malloc이 실패하면 메시지를 출력하고 계속 진행합니다!

대신 여러 개의 정수를 포함 할 단일 블록을 할당해야합니다. 이를 수행하는 한 가지 방법은 realloc 함수를 사용하여 기존 할당을 더 크게 만드는 것입니다.

또한 fscanf의 반환 값을 검사 할 때는 == 1을 확인해야합니다. 일부 문자를 입력했지만 EOF 조건을 트리거하지 않으면 0을 반환하므로 프로그램이 영원히 계속됩니다. 우리는 프로그램 수와 작업을 계속할 수 있습니다 (메모리 부족 조건에서 복구 할 수 있습니다 새로운 할당에 대해 별도의 변수 ptr을 사용하여

int *a = NULL; 
size_t j = 0; 

while (fscanf(fp,"%d",&value) == 1) 
{ 
    int *ptr = realloc(a, (j+1) * sizeof *a); 
    if (!ptr) 
    { 
     printf("not enough memory\n"); 
     break; 
    } 

    a = ptr; 
    a[j]=value; 
    j++; 
} 

: 여기

은 루프 모양을 수있는 방법입니다 지금까지 입력 된 int 중).

당신이 메모리 부족 즉시 예를 들어, 대신 break;exit(EXIT_FAILURE);를 호출하여 (프로그램을 종료하여 처리하려는 경우

는 대신 ptr의 등 a = realloc(a,를 사용하여 비트 코드를 단축 할 수있다.


초기의 코드 int *b; b[0] = -1; 문제가 있습니다 b 어디를 가리하지 않습니다하지만 당신은 그것을 통해 물품.

이 함수는 호출자가 j이 무엇인지 알 수없는 디자인 문제가 있습니다. 이에 대한 한 가지 해결책은 항상 입력 끝 부분에 -1을 입력하는 것입니다 (이 개념을 "센티넬 값"이라고하며 공간을 할당해야 함). 다른 옵션은 함수에 "out"매개 변수를 갖는 것입니다.