memchr 함수가 반환하는값이

jjjjrr의 이미지

안녕하세요
byte* pStr;
byte* pPos;
............................
while(pPos = (byte*)memchr(pStr,'\n',1024) != NULL)
{
memcpy(line,pStr,pPos-pStr);
pStr = pPos + 1;
}
위코드가 잘못된건가여
memchr 함수가 반환하는값이 찿은문자의 번지를 리턴하든지
못찿으면 NULL 을리턴한다고해서
NULL로 비교했는데 에러가 납니다
이럴경우 어떻게루프를 돌려야되나요
이런에러가 ....
error C2440: '=' : cannot convert from 'bool' to 'unsigned char *'

doldori의 이미지

연산자 우선순위 문제입니다.

while((pPos = (byte*)memchr(pStr,'\n',1024)) != NULL)

괄호에 주의.

jjjjrr의 이미지

답변감사합니다
한번더....
while((pPos = (byte*)memchr(pStr,'\n',1024)) != NULL)
{
char line[pPos-pStr];
memcpy(line,pStr,pPos-pStr);
pStr = pPos + 1;
}

여기서도 에러가 나는군요 char line[pPos-pStr];

error C2057: expected constant expression
error C2466: cannot allocate an array of constant size 0
error C2133: 'line' : unknown size
부탁합니다

cdpark의 이미지

char line[pPos-pStr];

이 부분이 문제입니다. C 언어의 예전 표준에서는 배열 선언 시에 상수식이 아닌 수식을 넣을 수 없습니다. malloc 함수를 써서 동적 할당을 해야합니다.

jjjjrr의 이미지

또문제가있읍니다
미안합니다
while((pPos = (char*)memchr(pStr,'\n',1024)) != NULL)
{
char* line;
line = new char[pPos-pStr];
memcpy(line,pStr,pPos-pStr);
pStr = pPos + 1;
strLine = line;
delete line;
}
여기서 line = new char[pPos-pStr]; 메모리가할당되는양이 memchr 로찿은 크기보다 크게 할당됩니다
그래서memcpy(line,pStr,pPos-pStr);
에서 line에들어가는값이 실제값외에 쓰레가값이 더추가되어서 들어갑니다
왜이런현상이 일어날까요
시작번지와 찿은번지의 차이만큼만 메모리가 할당되고
복사되어야되는데 왜 더많이 메모리가 할당이 될까요
조언부탁드립니다

jjjjrr의 이미지

while((pPos = (char*)memchr(pStr,'\n',1024)) != NULL)
{
char* line;
int i = pPos-pStr;
line = new char[pPos-pStr];
memcpy(line,pStr,pPos-pStr);
pStr = pPos + 1;
strLine = line;
int j = strlen(line);
delete line;
}
위코드에서 i의값과 j 의값이 같아야되는것같은데 틀리게나옵니다
i 의값이 43이나오구여
j 의값이 57 이나옵니다
왜이렇게나올까요
line에할당된값이 43인데 왜 line 의길이가 57이되는지....
그차이만큼 쓰레기값이 들어가있읍니다
조언부탁합니다

doldori의 이미지

이런 말씀을 드리면 서운하게 들릴지도 모르겠지만, 지금같은 형태의 질문/답변은
jjjjrr님을 위해 거의 도움이 되지 않습니다. C나 C++에 대한 좋은 책을 하나
장만해서 정독을 하시는 게 장기적으로 볼 때 훨씬 좋습니다.

The C Programming Language, Kernighan & Ritchie
Accelerated C++, Koenig & Moo

은 많은 사람들이 추천하는 책입니다.

jjjjrr의 이미지

답변감사합니다
저에게 여러권의 책이 있읍니다
c c++ visual c++ java 등등 이것외에도 많읍니다
어느부분을 보면 해결될수있을까요
코딩하는것도 책도보고 관련사이트도 여러군데들어가면서
검색도하고 질문도하고해서 만들어가고있읍니다
아무것도아닌문제를 몇달식 시간을 허비한적도있었구여
해결되고보면 너무허망한....
그래서 자주질문드립니다
질문하고나서도 나름대로도 노력하고있구여
혹시 아는사항이라면 부탁드립니다
아는분에게는 간단한문제지만
모르는사람입장에서는 무지시간이 걸릴수도있을것같읍니다

yielding의 이미지

여러 권이 있는게 좋은건 아닙니다. (언어를 처음 베울 때 보통 마음이 앞서서 책을 많이 사는 경우가 많죠.)
개인적으로는 doldori님께서 추천 하신책이 제일 좋다고 생각이 됩니다만 굳이 구입을 하지 않으실 경우 가지고 계신 책중 제일 얇은 책 하나를 빨리 한번 보시고 프로그램을 하시면서 문제가 생기면 다시 리뷰를 하거나 더 잘 설명이 되어있는 책에서 모르는 부분을 찾아보는 방식이 좋을 거 같군요

Life rushes on, we are distracted

mach의 이미지

jjjjrr wrote:

while((pPos = (char*)memchr(pStr,'\n',1024)) != NULL)
{
char* line;
int i = pPos-pStr;
line = new char[pPos-pStr];
memcpy(line,pStr,pPos-pStr);
pStr = pPos + 1;
strLine = line;
int j = strlen(line);
delete line;
}
위코드에서 i의값과 j 의값이 같아야되는것같은데 틀리게나옵니다
i 의값이 43이나오구여
j 의값이 57 이나옵니다
왜이렇게나올까요
line에할당된값이 43인데 왜 line 의길이가 57이되는지....
그차이만큼 쓰레기값이 들어가있읍니다

* 오류에 대한 설명(예제)
memchr()을 사용해서 특정 순차 메모리에서 특정문자(예에서는 \n문자)를
검색했다.
예) "abc\ndef\0\nghi\0"라는 문자열이 주어졌을때, memchr()수행결과는 첫번째 나온 \n문자를 가리키게 될것이다.(예에서 \n은 두번 나타난다)
그러나, 이 문자열을 strlen()에 넣는다면 abc\ndef까지 카운트한다. 즉, 7을 리턴할 것이다.
왜냐하면, strlen()은 null을 기준으로 연산하기 때문이다.

* 이 질문을 하신분에 대한 조언
C/C++에서 스트링(null terminated string)의 의미를 파악한다.
- null terminated string : \0 즉, ASCII 코드 0까지를 문자열로 인식.
이 경우, strlen()등 str*()계열 함수들은 모두 \0을 기준으로 동작한다.
- memchr()등 mem으로 시작되는 이름을 가진, 즉, mem*()함수들은
\0과 무관하게 동작한다.

- 즉, 메모리관련 처리와, 스트링관련처리는 같지 않다!. 를 명심하자.

* C언어의 문자열을 이해하고 처리 방법을 연습해야 한다. 현재 이해못하고 있는것으로 보이며,
대충의 로직(+-*/및 루프 if()등)만을 가지고 C언어를 안다고 생각하면 안된다.
* 이해에 도움이되는 프로그래밍으로는 파서(parser)를 만들어 보는것이다.
복잡하지 않아도 좋다. 바이너리와 ascii 혼용 파일에 대해 처리하는 방법론을 터득하도록 노력한다.
(지금 코딩하시는 루틴은 특정 입력스트림에서 일정한 패턴;줄단위?;으로 입력을 자르는
부분을 하시는것으로 보이는데요, 이것도 그러한 유형이기도 합니다만,
연습코딩으로는 적절해 보이지 않아 보입니다.)
* 저는 개인적으로 C프로그래밍 잘하는 사람의 기준을 문자열프로세싱 잘하는
사람으로 봅니다. 그외 시스템에 따른 특성 프로그램은 이후의 일이 되겠습니다.
이를테면 VC++/MFC, UNiX 시스템프로그래밍등이 되겠지요.
노력하셔서 대성하시길~

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

mach의 이미지

jjjjrr wrote:

i 의값이 43이나오구여
j 의값이 57 이나옵니다
왜이렇게나올까요
line에할당된값이 43인데 왜 line 의길이가 57이되는지....
그차이만큼 쓰레기값이 들어가있읍니다

입력 문자열이 다음과 같은 형태라서 그렇습니다.
"abcd.........efg\nhijk...oxoxi\0........"
.0................43...........57번째.......

즉, 43번째 \n이 나오고 뒤에 57번째 \0이 있다는 얘기지요.
물론 0~57 중간에는 \0은 하나도 없고요!
또한, 위에서 제가 예시한 문자열에서 hij,,,,oxoxi를 질문하신 분은 쓰레기값(?)이라는
묘한 발상도 하셨습니다.

위와같은 str*()및 mem*()를 혼용하여 코딩할때, 주의하지 않으면,
특정 데이터를 입력하면 잘~ 돌다가, 특정데이터가 입력되면 죽거나, 이상한
결과를 출력하는 괴물을 만들게 됩니다.
다시 강조하지만, 문자열프로세싱은 C프로그래밍의 기본입니다!

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

jjjjrr의 이미지

친절한답변감사합니다
같은주제를 놓고 이방법 저방법 여러가지수단을 동원해서
해결하려구노력하고있읍니다
벌써 보름이넘은것같구여
char* line;
line = new char[pPos-pStr];
int i = pPos-pStr;
int k = strlen(line);
memcpy(line,pStr,pPos-pStr);
pStr = pPos + 1;
strLine = line;
int j = strlen(line);
delete line;
아래부분이
line = new char[pPos-pStr]; 메모리할당했을때의 디버깅창에서의 상태입니다
여기서 pPos-pStr 의값 i 가 43 이나옵니다
근데 strlen(line); 의값인 k 는 57 이나오구여
아래가 할당시의 line 의메모리블럭모양입니다
0x00a24a20 "袴袴袴袴袴袴袴袴袴袴袴袴袴袴袴袴袴袴袴袴袴羲羲硼硼硼硼硼a"
그리구 memcpy(line,pStr,pPos-pStr); 에의해복사된 line 의모습입니다
0x00a24a20 "-----------------------------7d437f6307d2
羲羲硼硼硼硼硼a"
제가 쓰레기값이라고한것이
羲羲硼硼硼硼硼a" 이부분때문입니다
정상적으로는 "-----------------------------7d437f6307d2
만 복사가 되어야 정상입니다 이끝이 '\n'입니다
애초 메모리할당시부터 이값이 할당수치보다 많게 들어가있는겁니다
char* line;
line = new char[pPos-pStr];
int i = pPos-pStr; //i 는 43
int k = strlen(line); //k 는 57
이코드의 할당에서부터 line의값이 할당값보다 많이 할당되었다는겁니다

문자열부분에대해서 다시공부하도록하겠읍니다

mach의 이미지

눈가리고 아웅코드를 쓰면 다음과 같이 되겠습니다만,.....

Quote:

char* line;
line = new char[pPos-pStr+1]; // \0(널;NULL)문자 영역이 부족하다 +1 해준다
int i = pPos-pStr+1; // +1 해준다.
memset(line, 0, i); // 메모리 새로할당하면 무조건 초기화하는 습관을 갖자!
int k = strlen(line); // 널로 끝나는 문자열이라고 가정하고 쓴다. memchr하고는 궁합이 안맞는다. 위험해 보인다. 당연히 0이 k에 들어가겠지.
memcpy(line,pStr,pPos-pStr); // +1 더하기 안한다. \n부터 그 이후는 복사 안할거다.
pStr = pPos + 1; // \n 다음 문자를 가리키게 한다.
strLine = line; // 새로 만들어진 문자열의 포인터를 가리키게 함
int j = strlen(line);//복사된 문자열 길이
delete line; //할당된 메모리 해제, strLine은 dangling reference를 하게됨;위험

스무고개중 이제 한고개를 넘은듯합니다. 위 코드는 너무 위태위태해 보입니다.
학생이시라면 부지런히 공부하셔야겠습니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

yielding의 이미지

Quote:

char* line;
line = new char[pPos-pStr];
int i = pPos-pStr;
int k = strlen(line);

위 코드에서 동적할당한 line의 strlen은 undefined이겠죠?

Quote:

memcpy(line,pStr,pPos-pStr);
pStr = pPos + 1;
strLine = line;
int j = strlen(line);
delete line;

여기서도 pPos와 pStr사이에 NULL이 있더라도
memcopy는 길이만큼 (예를 들어 길이가 100이면) 다 복사를 합니다만 이 100바이트 중간에 (50의 위치에) NULL이 있다면 strlen(line) == 50이 될겁니다..
mach님의 답변을 잘 생각하시고 공부하시길..

아 그리고 디버깅 꼭 성공하세요..~ 엄청 느실겁니다. ^^;

Life rushes on, we are distracted

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.