2017-12-03 14 views
1

승무원이 "s"값의 전체 공간을 파고 값 "T"로 변경하고 매번 for 루프를 사용하는 대신지도 구조 인쇄 기능을 만드는 데 도움이 될 수 있다면 출력이 이렇게 출력되어야합니다 우리는 크게 너무! : 당신이 승무원 일을 보내려고 2 차원 배열 구조의 값을 다른 값으로 대체하고 C의 2 차원 배열 구조에 대한 함수를 어떻게 인쇄합니까?

Crew Dig Carry
1 3 1
2 2 5
3 4 1
4 1 3

을 이해할 수있을 것이다?
4s 1s 3s
1s 2s 3s
1s 5s 1s

1 3

은이 섹션에서 모든 모래를 제거했습니다!

승무원 2를 어디로 보내시겠습니까?
4s 1s 1T
1s 2s 3s
1s 5s 1s

2

내가 지금까지 가지고 :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NUMCREW 4  
#define MAXHOUR 8  
#define MINHOUR 1  
#define ROW 3  
#define COL 3  


struct pirate { 
    int dig; 
    int carry; 
}; 

struct map { 
    int sand; 
    int treasure; 
}; 

void printcrew(struct pirate * pirate_data); 
void print(struct map * map_data);  


int main() { 
char filename[20]; 
int hour=8; 
int crew=0; 
int i, j, x, y; 
int space; 
struct map map_data[ROW][COL]; 
struct pirate pirate_data[NUMCREW]; 
FILE * ifp; 

printf("You have arrived at Treasure Island!\n"); 
printf("What is the name of your map?\n"); 
scanf("%s", filename); 

ifp = fopen(filename, "r"); 



for (i=0; i<ROW; i++){ 
    for (j=0; j<COL; j++) { 
     fscanf(ifp, "%d %d", &map_data[i][j].sand, &map_data[i][j].treasure); 
    } 
} 


for (i=0; i<NUMCREW; i++) { 
    fscanf(ifp, "%d", &pirate_data[i].dig); 
    fscanf(ifp, "%d", &pirate_data[i].carry); 
} 

fclose(ifp); 
for (hour=8; hour >= MINHOUR; hour--) { 
    printf("\nYou have %d hours left to dig up the treasure.\n", hour); 
    printcrew(pirate_data); 
    printf("\n"); 

    for (crew=0; crew<NUMCREW; crew++){ 
     printf("Where would you like to send crew member %d?\n", crew+1); 

     for(i=0; i<ROW; i++) { 
      for (j=0; j<COL; j++) { 
      printf("%ds\t", map_data[i][j].sand); 
       if (map_data[i][j].sand == 0) { 
        printf("%dT\t", map_data[i][j].treasure); 
      } 
     } 
      printf("\n"); 
      } 
      scanf("%d %d", &x, &y); 
      map_data[x-1][y-1].sand = map_data[x-1][y-1].sand - pirate_data[crew].dig; 
     } 
    } 

return 0; 
} 

void printcrew(struct pirate * pirate_data) { 
int i;` 

printf("Crew \t Dig \t Carry \n"); 
for (i=0; i<NUMCREW; i++) 
    printf("%d \t %d \t %d \n", i+1, pirate_data[i].dig, pirate_data[i].carry); 

return; 

} 

void print(struct map * map_data) { 
int i, j; 

for(i=0; i<ROW; i++) { 
    for (j=0; j<COL; j++) { 
     printf("%ds\t", map_data[i][j].sand); 
    } 
    printf("\n"); 
} 

return; 

}

내 결과물이 나오고 계속 :
승무원 1을 어디로 보내시겠습니까?
4s 1s 3s
1s 2s 3s
1s 5s 1s

어디에서 승무원 2를 보내시겠습니까?
4s 1s 0s 1T
1s 2s 3s
1s 5s 1s

어디에서 승무원 3을 보내시겠습니까? 기능 '인쇄'에서
: (가) 나는 다음과 같은 오류가 계속 구조체지도 기능을 인쇄로
4s 1s 0s 1T
1s 0s 1T 3s
1s 5s 1s

|
오류 : 첨자 값이 배열도 포인터도 벡터도 아닌 |

답변

0

게시 된 코드에 오타가있는 것 같습니다. printcrew() 함수에 길잃은`문자가 있습니다. 컴파일러 경고가 표시되어야하며 모든 컴파일러 경고가 수정되어야합니다.

int i;` 

print() 함수의 문제에 대해서는 함수 프로토 타입이 잘못되었습니다. 대부분의 표현식에서 함수 호출이 포함되어 있습니다. 배열은 첫 번째 요소에 대한 포인터로 부패합니다. 이제 struct map map_data[ROW][COL]과 같은 2 차원 배열은 실제로 ROW 개의 배열 COL 요소의 배열입니다. 즉,이 배열의 각 행은 struct map map_data[COL] 유형입니다. 포인터 감쇠가 발생하면 결과는 배열에 대한 포인터 인 첫 번째 요소에 대한 포인터가됩니다 (mapstruct에 대한 포인터가 아님). 배열에 대한 포인터를 표현하는 구문은 struct map (*ptr)[COL]입니다.그래서, 함수 프로토 타입이 있어야한다 :

void print(struct map (*map_data)[COL]); 

발견 보물을 표시하는 디스플레이를 업데이트하여이 문제를 해결하려면 보물이 인쇄 모래 전에 를 발견 있는지 확인, 만 인쇄 모래 보물을 찾을 수 없습니다 경우 :

for(i=0; i<ROW; i++) { 
    for (j=0; j<COL; j++) { 
     int sand = map_data[i][j].sand; 
     if (sand > 0) { 
      printf("%ds\t", sand); 
     } else { 
      printf("%dT\t", map_data[i][j].treasure); 
     } 
    } 
    printf("\n"); 
} 

입력 유효성 확인에 대한 의견은 순서에 있습니다. scanf() 패밀리 함수가있는 %s 또는 %[] 지정 문을 사용하여 문자열 입력을 읽을 때 항상 최대 너비를 지정하십시오. 이렇게하지 않으면 버퍼 오버플로 및 정의되지 않은 동작이 발생할 수 있습니다.

scanf()과 패밀리는 성공적인 할당 횟수를 반환합니다. 이 값은 입력이 예상대로 이루어 졌는지 확인해야합니다. 게시 된 코드에서 사용자가 교활하게 키보드의 파일 끝을 알리는 경우 지정하지 않고 scanf()이 반환됩니다. filename[]은 초기화되지 않기 때문에 filename을 사용하면 정의되지 않은 동작이 발생합니다. 대신 다음과 같이 시도하십시오.

if (scanf("%19s", filename) < 1) { 
    fprintf(stderr, "Input error\n"); 
    exit(EXIT_FAILURE); 
} 

파일 열기 시도가 성공했는지 확인하는 것이 중요합니다. 코드가 성공적으로 열리는 것처럼 코드가 계속 진행되는 동안 파일을 열지 못하면 정의되지 않은 동작이 발생합니다. fopen() 반환, 실패하면 널 포인터 :이 이야기에

ifp = fopen(filename, "r"); 
if (ifp == NULL) { 
    fprintf(stderr, "Unable to open file %s\n", filename); 
    exit(EXIT_FAILURE); 
} 

도덕적 당신이 값을 확인해야한다는 것입니다 의미있는 값을 반환하는 모든 함수에서 반환.

scanf("%d %d", &x, &y); 
map_data[x-1][y-1].sand = map_data[x-1][y-1].sand - pirate_data[crew].dig; 

사용자가 아닌 숫자 입력을 입력하면

은 값이 관련 변수에 저장되지 않는다 :

때문에 여기 입력을 검증 실패 문제에 대한 또 다른 가능성이있다. 기껏해야 이것은 이전에 저장된 값의 사용으로 인해 놀라운 결과를 초래합니다. 최악의 경우, 관련 변수의 값이 불확실 (예 : 초기화되지 않음) 일 때 정의되지 않은 동작을 초래합니다. 또한 사용자는 여기에 양수가 아닌 숫자를 입력하여 음의 배열 인덱스와 정의되지 않은 동작을 유도 할 수 있습니다. 또는 사용자가 너무 큰 값을 입력하여 범위를 벗어난 어레이 액세스 및 정의되지 않은 동작을 시도 할 수 있습니다. 또한 sand 구성원은 음수 일 때도 감소합니다. 이것은 바람직하지 않을 수도 있지만 근면 한 해적과 악의적 인 사용자의 조합에 대해서는 부호가없는 정수 오버플로가 정의되지 않은 동작을 일으킬 수 있습니다.

항상 신뢰할 수없고 항상 악의적이라고 간주되는 모든 입력, 특히 사용자 입력의 유효성을 검사합니다. scanf()에 의해 반환 된 값을 확인하여 입력 값이 예상 한 값 이상인지 확인하고 입력 값이 수용 가능한 범위 내에 있는지 확인하십시오. 나쁜 입력을 처리하는 방법은 프로그래머에게 달려 있습니다. 한 가지 옵션은 올바른 입력을 다시 묻는 것입니다.

while (scanf("%d %d", &x, &y) < 2 
     || x < 1 
     || x > COL 
     || y < 1 
     || y > ROW) { 
    printf("Please enter numbers in the ranges [1, %d] [1, %d]\n", 
      ROW, COL); 
} 
map_data[x-1][y-1].sand = map_data[x-1][y-1].sand - pirate_data[crew].dig;