C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[51500] Re:재질문
열씸! [cappuccino] 1212 읽음    2007-12-05 23:20
[문자열|문자열|문자열|4바이트정수|4바이트정수]
라고 하셨으니 당연히 숫자 읽는 부분이 두 번 나와야 된다고 생각하는거죠.
그리고 파일을 문자열 처리하면서 길이가 달라지는 문제는 흔히
fopen("파일명", "rb"); 처럼 binary모드로 읽지 않고, 디폴트인 ascii로 읽어서 그렇습니다.
바이너리 데이타가 들어 있는 것을 설마 TStringList *strlist = new TStringList(); strlist->LoadFromFile
하진 않으셨을테니 fopen으로 가정했습니다.
아스키모드로 읽든지, TStringList에서와 같은 같은 스트링 파일처리 기능을 사용한 경우에는
일반 문자를 처리할 때엔 큰 문제가 없지만, 개행문자나 파일의 종료에 해당하는 코드가 파일의 중간에
등장한다면 길이가 엉뚱하게 됩니다. 즉 반드시 바이너리로 읽으셔야 합니다.
오히려 문자열을 처리할때도 바이너리가 편한 부분이 많습니다.
고로 화일을 어떻게 열었는지 확인해 보시죠.

또한, 이미 str에 읽어 놓은 문자열을 다시한번 그리로 복사하는것은 성능도 나쁘거니와
문제를 야기할 소지가 있습니다. 4바이트 정도 끌어당기는건 큰 문제가 안될지 모르지만,
몇 몇 속도 빠른(64bit이상 최적화된) memcpy 나 strcpy가 4바이트 이상 단위의 복사를 수행할 지도 모르니까요.
즉,
unsigned char *ptr = str; 이렇게 임시 변수를 하나 선언하고 버퍼스트링의 시작주소를 복사해 놓고,
거기서 값들을 읽어은 후, 주소를 증가시켜야 할 때
ptr += sizeof(int); 이걸로 족했던거죠.

intothefree 님이 쓰신 글 :
: 저의 질문에 관심을 가져주시고 답변해주셔서 감사합니다.
: 소스의개선사항 감사드립니다.. 하지만 제가 궁금해하는 부분은 아직 해결이되질 않는군요
: 질문의 소스를 좀더 추가했습니다. 다음과 같은 구조입니다.
:
:        String cut_string() // 이상없음
:        {...} 
:        // 스트링값을 읽고 버퍼를 잘라내고 다음토큰으로 시작포인터를 옮김
:        
:        문제의 정수자르는 함수부분
:        int cut_int(unsigned char * str)
:        {
:              int value;
:             
:              memcpy(&value,str,4); <- 4byte를 잘라 int로 값치환  (*** 이부분이 쓰레기값 발생 ***)
:              strcpy(str, str+4); <- str 버퍼에서 읽은 부분(4byte)은 잘라내고 다음으로 시작포인터를 옮김
:              return value;
:        }
:
:        void load_values()
:        {
:               unsigned char * buffer;
:              
:               //test.txt 파일에서 읽어 buffer 버퍼에 넣는부분 생략
:
:               Edit1->Text = cut_string(buffer);
:               Edit2->Text = cut_string(buffer);
:               Edit3->Text = cut_string(buffer);
:               Edit4->Text = IntToStr(cut_int(buffer));
:               Edit5->Text = IntToStr(cut_int(buffer));
:        }

:     --------------------------------------------
:     : memcpy(&value,str,4); // 여기까진 말이 됩니다.
:     : strcpy(str, str+4); 이건 말이 안되네요.
:     : strcpy는 NULL문자를 만날때 까지 복사합니다.
:     : 이 부분이 memcpy(value2, str + 4, 4) 였다면 말이 되겠지요.
:     :
:     : 어쨌든 이 부분도
:     : 실은 이렇게 해 버리면 그만이었던 겁니다.
:     : value   = *(int *)str;
:     : value2 = *(int *)(str + sizeof(int));
:     ---------------------------------------------
: 제가 소스가 지저분하고 길어서 다 안올려 생긴 오해같습니다. 로딩부에서 바로 두번 값을 읽는게아니고
: 그 자체가 int값 하나를 읽는 함수입니다.
: 그래서 int값 하나를 읽고 포인터를 증가해 시작점을 다음 토큰으로 바꾼것입니다.
:
: 답변해주신 부분중
: : memcpy(&value,str,4); // 여기까진 말이 됩니다. 
: 이부분에서 쓰레기값이 들어갑니다.   <<<*************   문제의 부분
: 어떻게 수정하면 좋을지 난감합니다.
:
: **새로운 궁금증
: test.txt (17Byte)파일을 읽어 strlen(buffer) 해보면 17이 아니고 11로 나옵니다.
: 바이트길이대로 잘라서 처리하는데 길이가 맞지 않아서 생기는문제인거같기도 한데
: 왜 파일크기랑 strlen 길이가 다른건지 이해가 가질 않습니다.
:
: 장황하고 질문이 많구요..
: 죄송하고 좋은하루 되십시요 ..
:
:
:
:
: 열씸! 님이 쓰신 글 :
: : 문득 지나치다, 질문이 가지런한게 마음에 들어 글을 남깁니다.
: : 우선,
: : 파일 저장부분에서 눈에 띄는 부분을 짚어드리죠.
: : 저장은 문제 없다고 하셨지만 다소 먼 길을 돌아가시는듯 합니다.
: : AnsiString temp = Edit1->Text + "|" + Memo1->Text + "|" + Memo2->Text + "|";
: : fwrite(temp.c_str(), temp.Length(), 1, in);
: : 이면 문자열 저장이 끝날테고,
: :
: : int temp = 123456789;
: : fwrite(&temp, sizeof(int), 1, in);
: : 처럼 하면 memcpy 없이도 단순히 주소 연산자를 이용해 저장할 수 있습니다.
: : 파일구조에는 [문자열|문자열|문자열|4바이트정수|4바이트정수]
: : 이라 하셨지만, 뒤의 정수와 정수부 사이엔 파이프 문자(|) 가 보이지 않는군요.
: : 어차피 고정길이 부분이니 이부분은 굳이 파이프가 필요없기도 하겠죠.
: :
: : 다음,
: : 파일의 로딩부에서
: : int value;
: : unsigned char * str; // 현재 숫자가 시작하는 부분의 버퍼주소를 가리키고 있다고 생각합시다.
: : memcpy(&value,str,4); // 여기까진 말이 됩니다.
: : strcpy(str, str+4); 이건 말이 안되네요.
: : strcpy는 NULL문자를 만날때 까지 복사합니다.
: : 이 부분이 memcpy(value2, str + 4, 4) 였다면 말이 되겠지요.
: :
: : 어쨌든 이 부분도
: : 실은 이렇게 해 버리면 그만이었던 겁니다.
: : value   = *(int *)str;
: : value2 = *(int *)(str + sizeof(int));
: :
: : intothefree 님이 쓰신 글 :
: : : 파일을 읽어 데이터를 처리하는 과정에서 궁금한것이 있습니다.
: : :
: : : ----------------------------------------------------------------
: : : 파일구조
: : : [문자열|문자열|문자열|4바이트정수|4바이트정수]
: : : ----------------------------------------------------------------
: : : 데이터저장부
: : :         str.sprintf("%s|","가");
: : :         fwrite(str.c_str(),Edit1->Text.Length()+1,1,in); // 문자열1
: : :
: : :         str.sprintf("%s|","나");
: : :         fwrite(str.c_str(),Memo1->Text.Length()+1,1,in); // 문자열2
: : :
: : :         str.sprintf("%s|","다");
: : :         fwrite(str.c_str(),Memo2->Text.Length()+1,1,in); // 문자열3
: : :
: : :         tmp = 123456789;
: : :         memcpy(strtemp,&tmp,4);
: : :         fwrite(strtemp,sizeof(int),1,in); // 정수1
: : :
: : :         tmp = 666;
: : :         memcpy(strtemp2,&tmp,4);
: : :         fwrite(strtemp2,sizeof(int),1,in); // 정수2
: : :
: : : 파일크기 17바이트 정상
: : : ----------------------------------------------------------------------------
: : : 데이터로딩부
: : :
: : :        문자열자르는 함수
: : :        스트링은 잘됩니다. |를 만날때까지 읽다가 |를 만나면 문자열로 바꾸어 저장하고 포인터를 증가시켰습니다.
: : :
: : :        문제의 정수자르는 함수부분
: : :        int value;
: : :        unsigned char * str : 함수 파라미터로 파일을 읽은 버퍼입니다.
: : :
: : :        memcpy(&value,str,4);
: : :        strcpy(str, str+4);
: : : ----------------------------------------------------------------------------
: : :
: : : **** 문제는 4바이트 정수를 읽어서 int로 바꾸는건데 요부분이 잘 안됩니다.
: : :
: : : 문자열의 길이를 알아서 그 만큼 건너뛰고 fread()를 하면 별문제가 없습니다.
: : : 문자열의 길이는 가변적입니다. 그러나 [|] 를 구분자로 사용하였고 연산을 하기위해 파일을 읽어 str 변수에담아 처리하려고 하는데 이상한 쓰레기값이 결과가 나옵니다.
: : :
: : : 요점정리 : 문자열길이가 유동적이라 파일에서 직접 읽지않고 함수에서 str 변수에 파일을 전부 읽어들여서 버퍼에서 잘라 사용하고자 하는데 위의방법으로는 작동이 안됩니다.
: : :
: : : 문제가 무엇인지요.. 텍스트파일을 만들어 첨부했습니다.
: : :
: : : 가
: : : 나
: : : 다
: : : 123456789
: : : 666 
: : :
: : : 이렇게 나누고싶은데 방법이 없을까요

+ -

관련 글 리스트
51475 문자열잘라 4byte 정수만들기 intothefree 1525 2007/12/05
51491     Re:문자열잘라 4byte 정수만들기 라스코니 1602 2007/12/05
51476     Re:문자열잘라 4byte 정수만들기 열씸! 1920 2007/12/05
51484         재질문 intothefree 1103 2007/12/05
51500             Re:재질문 열씸! 1212 2007/12/05
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.