83.8 질문입니다
, 박 수용님이 작성#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
typedef enum _TOKEN_TPYE {
TOKEN_STRING,
TOKEN_NUMBER,
} TOKEN_TPYE;
typedef struct _TOKEN {
TOKEN_TPYE type;
union {
char *string;
double number;
};
bool isArray;
} TOKEN;
#define TOKEN_COUNT 20
typedef struct _JSON {
TOKEN tokens[TOKEN_COUNT];
} JSON;
char *readFile(char *filename, int *readSize)
{
FILE *fp=fopen(filename,"rb");
if(fp==NULL)
return NULL;
int size;
char *buffer;
fseek(fp,0,SEEK_END);
size=ftell(fp);
fseek(fp,0,SEEK_SET);
buffer=malloc(size+1);
memset(buffer,0,size+1);
if(fread(buffer,size,1,fp)<1)
{
*readSize=0;
free(buffer);
fclose(fp);
return NULL;
}
*readSize=size;
fclose(fp);
return buffer;
}
void parseJSON(char *doc, int size, JSON *json)
{
int tokenIndex=0;
int pos=0;
if(doc[pos]!='{')
return;
pos++;
while(pos<size)
{
switch(doc[pos])
{
case'"':
{
char *begin = doc + pos + 1;
char *end = strchr(begin,'"');
if(end==NULL)
break;
int stringLength=end - begin;
json->tokens[tokenIndex].type = TOKEN_STRING;
json->tokens[tokenIndex].string=malloc(stringLength+1);
memset(json->tokens[tokenIndex].string,0,stringLength+1);
memcpy(json->tokens[tokenIndex].string,begin,stringLength);
tokenIndex++;
pos = pos + stringLength+1;
}
case'[':
{
pos ++;
while(doc[pos] != ']')
{
if(doc[pos] == '"')
{
char *begin = doc +pos +1;
char *end = strchr(begin,'"');
if(end==NULL)
break;
int stringLength = end-begin;
json->tokens[tokenIndex].type=TOKEN_STRING;
json->tokens[tokenIndex].string=malloc(stringLength+1);
json->tokens[tokenIndex].isArray=true;
memset(json->tokens[tokenIndex].string,0,stringLength+1);
memcpy(json->tokens[tokenIndex].string,begin,stringLength);
tokenIndex++;
pos=pos+stringLength+1;
}
pos++;
}
}
case '0': case '1': case '2': case '3': case '4': case'5':
case '6': case '7': case '8': case '9': case '-':
{
char *begin = doc+pos;
char *end;
char *buffer;
end=strchr(doc+pos,',');
if(end==NULL)
{
end=strchr(doc+pos,'}');
if(end==NULL)
break;
}
int stringLength=end-begin;
buffer = malloc(sizeof(stringLength+1));
memset(buffer,0,stringLength+1);
memcpy(buffer,begin,stringLength);
json->tokens[tokenIndex].type=TOKEN_NUMBER;
json->tokens[tokenIndex].number=atof(buffer);
free(buffer);
tokenIndex++;
pos=pos+stringLength+1;
}
break;
}
pos++;
}
}
char *getString(JSON *json, char *key)
{
for(int i=0; i<TOKEN_COUNT; i++)
{
if(json->tokens[i].type==TOKEN_STRING && strcmp(json->tokens[i].string,key)==0)
{
if(json->tokens[i+1].type==TOKEN_STRING)
return json->tokens[i+1].string;
}
}
return NULL;
}
char *getArrayString(JSON *json, char *key, int index)
{
for(int i=0; i<TOKEN_COUNT; i++)
{
if(json->tokens[i].type==TOKEN_STRING && strcmp(json->tokens[i].string,key)==0)
{
if(json->tokens[i+1+index].type==TOKEN_STRING &&
json->tokens[i+1+index].isArray==true )
return json->tokens[i+1+index].string;
}
}
return NULL;
}
int getArrayCount(JSON *json, char *key)
{
for(int i=0; i<TOKEN_COUNT; i++)
{
if(json->tokens[i].type==TOKEN_STRING && strcmp(json->tokens[i].string,key)==0)
{
int j=0;
while(json->tokens[i+1+j].isArray==true)
j++;
return j;
}
}
return 0;
}
double getNumber(JSON *json, char *key)
{
for(int i=0; i<TOKEN_COUNT; i++)
{
if(json->tokens[i].type==TOKEN_STRING && strcmp(json->tokens[i].string,key)==0)
{
if(json->tokens[i+1].type==TOKEN_NUMBER)
return json->tokens[i+1].number;
}
}
return 0.0;
}
void freeJSON(JSON *json)
{
for(int i=0;i<TOKEN_COUNT; i++)
{
if(json->tokens[i].type == TOKEN_STRING)
free(json->tokens[i].string);
}
}
int main()
{
int size;
char *doc = readFile("example.json",&size);
if(doc == NULL)
return -1;
JSON json={0,};
parseJSON(doc,size,&json);
printf("Title: %s\n",getString(&json,"Title"));
printf("Year: %d\n",(int)getNumber(&json,"Year"));
printf("Runtime: %d\n",(int)getNumber(&json,"Runtime"));
printf("Genre: %s\n",getString(&json,"Genre"));
printf("Director: %s\n",getString(&json,"Director"));
printf("Actor: \n");
int actors = getArrayCount(&json,"Actor");
for(int i=0; i<actors; i++)
printf(" %s\n",getArrayString(&json,"Actor",i));
printf("imdbRating: %f\n",getNumber(&json,"imdbRating"));
freeJSON(&json);
free(doc);
return 0;
}
어디가 틀린지 모르겠습니다..
Re: 83.8 질문입니다
, 도장_ 관리자님이 작성parseJSON 함수 호출 후에 중단점을 확인해보면
하단 자동 조사창에서 tokens에 값이 제대로 들어와 있지 않다는 것을 알 수 있습니다. Year의 값은 2010이고, double 타입이면 2010.0000...으로 값이 있어야 합니다. 따라서 파싱 단계에서 오류가 있다는 뜻입니다.
디버거 사용법은 UNIT 6을 참조해주세요.
한 단계씩 실행해보는 것도 방법입니다.
doc에 제대로 된 값이 들어오는지 확인하세요.
포럼 상단 오른쪽에서 83.8로 검색하면 이전 질문과 답변을 참조할 수 있습니다.