c는 포인터가 혼란스러운데 이해했다고 믿고???? 나중에 다시 생각하려고 남긴다.
다음 코드를 만들었고 실패했다. bufToStruct를 실행할 때 포인터로 넘겼어도 buf를 받으면서 임시 공간에 변수를 만든다. 함수 실행을 끝내면서 그 공간도 날아가 도로묵 된다.
#include <stdio.h> #include "module1.h" int main() { struct mysqlStruct oneSqlData; char readbuf[MAX_LEN]; int ret; openfile(readbuf); printf("버퍼는 %s\n",readbuf); do{ ret=bufToStruct(readbuf, &oneSqlData); printf("%p\n", readbuf); sleep(1); }while(ret==-1); //bufToStruct(readbuf, &oneSqlData); return 0; }
int bufToStruct(char* buf, struct mysqlStruct *sqlData){ //buf를 읽어 날자, 시각, 온도로 분리. //,로 분리되어 delimiter로 분리.. //한번 읽을때마다 buf 한 줄 내용을 sqlData로 이동. //성공하면 0, //마지막이면 1, //실패하면 -1을 return. size_t len; char* temp; //시작 위치 len=strlen(buf); char tempbuf[len]; //strtok로 작업할 내용. strtok이 원래 버퍼를 수정함. char *year,*month, *day, *hour, *minute, *temperature; int year2, month2, day2, hour2, minute2, temperature2; //strtok이 원래 버퍼를 잘라 버려. //임시로 카피해서 사용. //원래 포인터는 토큰 크기만큼 넘김. strcpy(tempbuf, buf); //첫줄을 읽을 경우 무시할 방법 필요. //그냥 넣어서 에러, 정상 확인. temp = strtok(tempbuf, "\n"); len=strlen(temp); year=strtok(temp, "-"); //무슨 데이터인지 모르겠지만, 일단 숫자료 변경. year2=atoi(year); //buf 내용 삭제..temp 만큼. //buf 포인터를 temp 만큼 이동. for(int i=0;i<len;i++) buf++; if(year2 < 2000 || year2 > 2100) return -1; //정상대로 진행. sqlData->year = year2; printf("year2 is %d\n",year2); month=strtok(temp,"-"); month=strtok(temp,"-"); month2=atoi(month); sqlData->month = month2; }
위 내용을 gdb로 확인해 보았다.
(gdb) run Starting program: /home/pi/Project/cCode/module1/insertTemperature 버퍼는 날자, 온도 2020-7-9 10:00:00, 24.5 2020-7-9 10:01:00, 24.5 2020-7-9 10:02:00, 24.5 2020-7-9 10:03:00, 24.5 Breakpoint 1, main () at main.c:11 11 ret=bufToStruct(readbuf, &oneSqlData); (gdb) display &readbuf 1: &readbuf = (char (*)[200]) 0xbefff30c (gdb) s bufToStruct ( buf=0xbefff30c "날자, 온도\n2020-7-9 10:00:00, 24.5\n2020-7-9 10:01:00, 24.5\n2020-7-9 10:02:00, 24.5\n2020-7-9 10:03:00, 24.5\n", sqlData=0xbefff3d4) at module1.c:42 42 int bufToStruct(char* buf, struct mysqlStruct *sqlData){ (gdb) l 37 38 // ruturn 성공. 39 return 0; 40 } 41 42 int bufToStruct(char* buf, struct mysqlStruct *sqlData){ 43 44 //buf를 읽어 날자, 시각, 온도로 분리. 45 //,로 분리되어 delimiter로 분리.. 46 //한번 읽을때마다 buf 한 줄 내용을 sqlData로 이동. (gdb) 47 //성공하면 0, 48 //마지막이면 1, 49 //실패하면 -1을 return. 50 51 size_t len; 52 char* temp; //시작 위치 53 len=strlen(buf); 54 char tempbuf[len]; //strtok로 작업할 내용. strtok이 원래 버퍼를 수정함. 55 char *year,*month, *day, *hour, *minute, *temperature; 56 int year2, month2, day2, hour2, minute2, temperature2; (gdb) display &buf 2: &buf = (char **) 0xbefff2cc (gdb) display buf 3: buf = 0xbefff30c "날자, 온도\n2020-7-9 10:00:00, 24.5\n2020-7-9 10:01:00, 24.5\n2020-7-9 10:02:00, 24.5\n2020-7-9 10:03:00, 24.5\n"
bufToStruct로 readbuf를 전달할 때 주소를 전달하는 직접 전달하길 원했다. bufToStruct로 전달하는 0xbefff2cc는 어디에서 나왔을까? 임시 변수로 자기가 만들었다. 임시로 만든(콜 하고 없어질) 주소에 포인터 값을 넣었다. 그러니 함수 내부에서 열심히 포인터를 움직여도 메인 함수 포인터는 변하지 않았다. &buf = 0xbefff30c로 바꿔야 한다. 이중 포인터가 그 역할을 한다.
다음 그림을 참조하면 쉽게?? 이해할 수 있다. 이게 머라고 삽질하고 있는지..
#include <stdio.h> #include "module1.h" int main() { struct mysqlStruct oneSqlData; char readbuf[MAX_LEN]; char* readbufPtr; int ret; openfile(readbuf); readbufPtr = readbuf; //printf("버퍼는 %s\n",readbufPtr); do{ ret=bufToStruct(&readbufPtr, &oneSqlData); printf("%s\n", readbufPtr); sleep(1); }while(ret==-1); //bufToStruct(readbuf, &oneSqlData); return 0; }
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "module1.h" #include <string.h> #include <stdlib.h> int openfile(char* readbuf){ //파일을 열어, //readbuf로 기록. int fd; //char buf[MAX_LEN]; struct stat myfileStat; fd = open("./temperatureRecord.txt", O_RDONLY); if (fd == -1){ perror("error to open file\n"); return -1; } //읽을 파일 크기 확인. fstat(fd, &myfileStat); //최대 버퍼량 대비 파일이 큰지 확인 if(MAX_LEN < myfileStat.st_size){ perror("file is too big\n"); //return 실패 return -1; } read(fd, readbuf, myfileStat.st_size); //printf("버퍼는 %s\n",buf); close(fd); // ruturn 성공. return 0; } int bufToStruct(char** buf, struct mysqlStruct *sqlData){ //buf를 읽어 날자, 시각, 온도로 분리. //,로 분리되어 delimiter로 분리.. //한번 읽을때마다 buf 한 줄 내용을 sqlData로 이동. //성공하면 0, //마지막이면 1, //실패하면 -1을 return. size_t len, len2; char* temp; //시작 위치 len=strlen(*buf); char tempbuf[len]; //strtok로 작업할 내용. strtok이 원래 버퍼를 수정함. char *year,*month, *day, *hour, *minute, *temperature; int year2, month2, day2, hour2, minute2, temperature2; //strtok이 원래 버퍼를 잘라 버려. //임시로 카피해서 사용. //원래 포인터는 토큰 크기만큼 넘김. strcpy(tempbuf, *buf); //첫줄을 읽을 경우 무시할 방법 필요. //그냥 넣어서 에러, 정상 확인. temp = strtok(tempbuf, "\n"); len=strlen(temp); year=strtok(temp, "-"); //무슨 데이터인지 모르겠지만, 일단 숫자로 변경. year2=atoi(year); //buf 내용 삭제..temp 만큼. //buf 포인터를 temp 만큼 이동. //printf("함수 내부:포인터 이동 전\n %s",*buf); *buf=*buf+len+strlen("\n"); //printf("함수 내부:포인터 이동 후\n %s",*buf); if(year2 < 2000 || year2 > 2100) return -1; //정상대로 진행. sqlData->year = year2; printf("year2 is %d\n",year2); month=strtok(temp,"-"); month=strtok(temp,"-"); month2=atoi(month); sqlData->month = month2; }
Breakpoint 1, main () at main.c:13 13 ret=bufToStruct(&readbufPtr, &oneSqlData); 1: readbufPtr = 0xbefff30c "날자, 온도\n2020-7-9 10:00:00, 24.5\n2020-7-9 10:01:00, 24.5\n2020-7-9 10:02:00, 24.5\n2020-7-9 10:03:00, 24.5\n" 2: &readbuf = (char (*)[200]) 0xbefff30c 3: *readbufPtr = 235 '\353' (gdb) s bufToStruct (buf=0xbefff308, sqlData=0xbefff3d4) at module1.c:42 warning: Source file is more recent than executable. 42 int bufToStruct(char** buf, struct mysqlStruct *sqlData){ (gdb) display &buf 4: &buf = (char ***) 0xbefff2d4 (gdb) display buf 5: buf = (char **) 0xbefff308 (gdb) display *buf 6: *buf = 0xbefff30c "날자, 온도\n2020-7-9 10:00:00, 24.5\n2020-7-9 10:01:00, 24.5\n2020-7-9 10:02:00, 24.5\n2020-7-9 10:03:00, 24.5\n" (gdb) l 37 38 // ruturn 성공. 39 return 0; 40 } 41 42 int bufToStruct(char** buf, struct mysqlStruct *sqlData){ 43 44 //buf를 읽어 날자, 시각, 온도로 분리. 45 //,로 분리되어 delimiter로 분리.. 46 //한번 읽을때마다 buf 한 줄 내용을 sqlData로 이동. (gdb) 47 //성공하면 0, 48 //마지막이면 1, 49 //실패하면 -1을 return. 50 51 size_t len, len2; 52 char* temp; //시작 위치 53 len=strlen(*buf); 54 char tempbuf[len]; //strtok로 작업할 내용. strtok이 원래 버퍼를 수정함. 55 char *year,*month, *day, *hour, *minute, *temperature; 56 int year2, month2, day2, hour2, minute2, temperature2; (gdb) 57 //strtok이 원래 버퍼를 잘라 버려. 58 //임시로 카피해서 사용. 59 //원래 포인터는 토큰 크기만큼 넘김. 60 strcpy(tempbuf, *buf); 61 62 //첫줄을 읽을 경우 무시할 방법 필요. 63 //그냥 넣어서 에러, 정상 확인. 64 temp = strtok(tempbuf, "\n"); 65 66 len=strlen(temp); (gdb) 67 year=strtok(temp, "-"); 68 //무슨 데이터인지 모르겠지만, 일단 숫자로 변경. 69 year2=atoi(year); 70 71 //buf 내용 삭제..temp 만큼. 72 //buf 포인터를 temp 만큼 이동. 73 //printf("함수 내부:포인터 이동 전\n %s",*buf); 74 *buf=*buf+len+strlen("\n"); 75 76 //printf("함수 내부:포인터 이동 후\n %s",*buf); (gdb) b 74 Breakpoint 3 at 0x10814: file module1.c, line 74. (gdb) n 53 len=strlen(*buf); 4: &buf = (char ***) 0xbefff2d4 5: buf = (char **) 0xbefff308 6: *buf = 0xbefff30c "날자, 온도\n2020-7-9 10:00:00, 24.5\n2020-7-9 10:01:00, 24.5\n2020-7-9 10:02:00, 24.5\n2020-7-9 10:03:00, 24.5\n" (gdb) c Continuing. Breakpoint 3, bufToStruct (buf=0xbefff308, sqlData=0xbefff3d4) at module1.c:74 74 *buf=*buf+len+strlen("\n"); 4: &buf = (char ***) 0xbefff2d4 5: buf = (char **) 0xbefff308 6: *buf = 0xbefff30c "날자, 온도\n2020-7-9 10:00:00, 24.5\n2020-7-9 10:01:00, 24.5\n2020-7-9 10:02:00, 24.5\n2020-7-9 10:03:00, 24.5\n" (gdb) n 79 if(year2 < 2000 || year2 > 2100) 4: &buf = (char ***) 0xbefff2d4 5: buf = (char **) 0xbefff308 6: *buf = 0xbefff31b "2020-7-9 10:00:00, 24.5\n2020-7-9 10:01:00, 24.5\n2020-7-9 10:02:00, 24.5\n2020-7-9 10:03:00, 24.5\n" (gdb)
아래 사이트를 찾아 봤는데, 잘 이해가 안된다. 디버거로 주소 확인하는게 가장 확실했다. ㅠㅠ. 별 내용도 없는데, 왜케 오래걸리는지…