strtok및 배열에 대해서..

tazanboy의 이미지

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>

int main(void)
{
  char data[255];
  char *rdata;
  FILE *fp;
  int i;

  fp=popen("get_m","r");
  fgets(data,sizeof(data),fp);
  pclose(fp);
  
  puts(data);

  rdata=strtok(data," ");
  while(rdata != NULL) {
    printf("%s\n",rdata);
    rdata=strtok(NULL," ");
  }
  return 0;
}

위에서 popen으로 얻어오게 되는 값은 헥사코드로
0x23 0x34 0x56 0x56 0x76 ....

이런식의 공백으로 구분된 배열입니다.

그런데, 이것을 하나씩 구분해서 다시 배열형태로 만드는 방법을 당췌
모르겠습니다. 이것저것 약간씩 고치면 곧바로 에러가 뜹니다.
컴파일은 성공했어도 화면에 어셈블 에러가 막 뜨고 난리가 아닙니다.

배열로 쓸때는 에러가 안나다가도 포인터 쓰면 에러가 나고
포인터 쓸때는 에러가 안나다가고 배열 쓰면 에러가 나고..
이해를 잘 못해서인지 어렵네요.

위의 popen으로 불러들이는 data들을 strtok를 사용해서
배열하나를 만들어서 그곳에 순서대로 차곡차곡 쌓을려면 어떻게
해야 하나요?
아니면, 제가 지금 엉뚱한 곳 혹시 긁고 있는 것은 아닌지요?

조언부탁드리겠습니다.

june8th의 이미지

읽을려는 데이터가 "# 4 V V v" 인가요?
아님. "0x23 0x34 0x56 0x56 0x76"인가요?

올리신 코드는 읽은 char * 스트링을 " "로 잘라서 프린트 잘 할거 같은데,
문제가 뭔지 정확히 모르겠네요..

eagle123의 이미지

문자열을 필요한 분리자(delim)로 자른 후 배열(optstr)에 넣은 후 그 갯수(opt_num)을 리턴해 줍니다.

도움이 되시길...

#include <stdio.h>
#include <string.h>

int main()
{
    char *optstr[100] = {0l,};
    char *str = "1234 가나다라 abcd";
    int opt_num=0, i=0;
    char *delim=" ";

    opt_num=line2opt(&str,optstr,delim);

    for (i=0; i< opt_num; i++)
    {
        printf("%s\n",optstr[i]);
    }

    return 0;
}

int line2opt(char **line, char *opt[], char *delim)
{
    char *buf;
    register int i;

    buf = strdup(*line);

    opt[0] = strtok(buf,delim);

    for(i=1;;i++) {
        opt[i] = strtok(NULL,delim);
        if(opt[i] == NULL) break;
    }

    return i;
}
jemiro의 이미지

man strtok 에서 발췌
Never use these functions. If you do, note that:
These functions modify their first argument.
These functions cannot be used on constant strings.
The identity of the delimiting character is lost.
The strtok() function uses a static buffer while parsing, so
it's not thread safe. Use strtok_r() if this matters to you.

저도 한때 이홈수를 즐겨 사용했었지만.,
요즘은 거의 ssscanf나, strstr , strtstrchr,,
이런 함수들로 대채해서 작성합니다..

jemiro의 이미지

eagle123 wrote:
문자열을 필요한 분리자(delim)로 자른 후 배열(optstr)에 넣은 후 그 갯수(opt_num)을 리턴해 줍니다.

도움이 되시길...

#include <stdio.h>
#include <string.h>

int main()
{
    char *optstr[100] = {0l,};
    char *str = "1234 가나다라 abcd";
    int opt_num=0, i=0;
    char *delim=" ";

    opt_num=line2opt(&str,optstr,delim);

    for (i=0; i< opt_num; i++)
    {
        printf("%s\n",optstr[i]);
    }

    return 0;
}

int line2opt(char **line, char *opt[], char *delim)
{
    char *buf;
    register int i;

    buf = strdup(*line);

    opt[0] = strtok(buf,delim);

    for(i=1;;i++) {
        opt[i] = strtok(NULL,delim);
        if(opt[i] == NULL) break;
    }

    free(buf); /* 요게 빠졌는것 같습니다. 중요한 습관이죠 */

    return i;
}
tazanboy의 이미지

답변 달아주셔서 감사드립니다. ^^
에러가 계속 납니다. 그래서 다른 방법을 강구해볼까 합니다.
참.. 제가 미처 말씀을 드리지 못했는데, 일반 PC에서 돌리는게 아니고,
임베디드 개발보드상에서 돌리는 프로그램입니다.
프로세서는 ARM이고요.

답변주셔서 정말로 감사합니다. ^^

dotri의 이미지

rdata=strtok(NULL," ");

중간에 이런 문장이 보이는데요.. 이거 잘못된거 아닌가요?;

kslee80의 이미지

strtok() 함수는 첫번째 argument 인 스트링에서
두번째 argument 에 해당하는 것을 만났을때
해당 위치의 문자를 '\0' 문자로 바꿔 버립니다 -_-;;;

즉,
123 4567 89
라는 스트링에 strtok(str, " "); 를 사용하게 되면
123x4567 89
(x 는 '\0' 문자를 의미합니다 -_-;;;)
로 변해 버립니다;;

그러므로, 하시고자 하는 것을 구현할려면
strtok() 대신 다른 방법을 사용해야 할듯 합니다.

man strtok 에 나오는 내용도 이것을 경고하는 것이죠...

뱀발)
전 strtok 를 '\n' 문자 짤라낼때만 씁니다;;
strtok(str, "\n"); 으로 말이죠...

shean0의 이미지

   char *optstr[100] = {0l,};
    char *str = "1234 가나다라 abcd";

이부분을
    char *optstr[100] = {0l,};
    char str[100]; /* = "1234.가나다라.abcd"; */
    int opt_num=0, i=0;
    char *delim=".";
    memset(str,0x0,sizeof(str));
    memcpy(str,"1234.가나다라.abcd",strlen("1234.가나다라.abcd"));

이렇게 하면 세그먼트폴트가 나는데요???
차이가 무엇인지 음.. 알수가 없습니다.. 지적을 부탁드립니다.
제가 만든소스==>

int main()
{
    char *optstr[100] = {0l,};
    char str[100]; /* = "1234.가나다라.abcd"; */
    int opt_num=0, i=0;
    char *delim=".";

memset(str,0x0,sizeof(str));
memcpy(str,"1234.가나다라.abcd",strlen("1234.가나다라.abcd"));

    opt_num=line2opt(&str,optstr,delim);

    for (i=0; i< opt_num; i++)
    {
        printf("%s\n",optstr[i]);
    }
    printf("str[%s]",str);
    return 0;
}

올려주신 원본소스==>

jemiro wrote:
eagle123 wrote:
문자열을 필요한 분리자(delim)로 자른 후 배열(optstr)에 넣은 후 그 갯수(opt_num)을 리턴해 줍니다.

도움이 되시길...

#include <stdio.h>
#include <string.h>

int main()
{
    char *optstr[100] = {0l,};
    char *str = "1234 가나다라 abcd";
    int opt_num=0, i=0;
    char *delim=" ";

    opt_num=line2opt(&str,optstr,delim);

    for (i=0; i< opt_num; i++)
    {
        printf("%s\n",optstr[i]);
    }

    return 0;
}

int line2opt(char **line, char *opt[], char *delim)
{
    char *buf;
    register int i;

    buf = strdup(*line);

    opt[0] = strtok(buf,delim);

    for(i=1;;i++) {
        opt[i] = strtok(NULL,delim);
        if(opt[i] == NULL) break;
    }

    free(buf); /* 요게 빠졌는것 같습니다. 중요한 습관이죠 */

    return i;
}

언제나 즐프를 꿈꾸며~

shean0의 이미지

그냥 이렇게 수정해서 사용해야 겠네요.. 그래두 왜 세그먼트 폴트였는지...음.
잘 모르겠음.. 음..뭐였지...

    
main()
{
   char *optstr[100] = {0l,};
    char str[100]; /* = "1234.가나다라.abcd"; */
    int opt_num=0, i=0;
    char *delim=".";
    memset(str,0x0,sizeof(str));
    memcpy(str,"1234.가나다라.abcd",strlen("1234.가나다라.abcd"));
     opt_num=line2opt(str,optstr,delim); 
}
int line2opt(char *line, char *opt[], char *delim) 
{ 
    char *buf; 
    register int i; 
    buf = strdup(line); 
    opt[0] = strtok(buf,delim); 
    for(i=1;;i++) { 
        opt[i] = strtok(NULL,delim); 
        if(opt[i] == NULL) break; 
    } 
    return i; 
} 

shean0 wrote:
   char *optstr[100] = {0l,};
    char *str = "1234 가나다라 abcd";

이부분을
    char *optstr[100] = {0l,};
    char str[100]; /* = "1234.가나다라.abcd"; */
    int opt_num=0, i=0;
    char *delim=".";
    memset(str,0x0,sizeof(str));
    memcpy(str,"1234.가나다라.abcd",strlen("1234.가나다라.abcd"));

이렇게 하면 세그먼트폴트가 나는데요???
차이가 무엇인지 음.. 알수가 없습니다.. 지적을 부탁드립니다.
제가 만든소스==>

int main()
{
    char *optstr[100] = {0l,};
    char str[100]; /* = "1234.가나다라.abcd"; */
    int opt_num=0, i=0;
    char *delim=".";

memset(str,0x0,sizeof(str));
memcpy(str,"1234.가나다라.abcd",strlen("1234.가나다라.abcd"));

    opt_num=line2opt(&str,optstr,delim);

    for (i=0; i< opt_num; i++)
    {
        printf("%s\n",optstr[i]);
    }
    printf("str[%s]",str);
    return 0;
}

올려주신 원본소스==>

jemiro wrote:
eagle123 wrote:
문자열을 필요한 분리자(delim)로 자른 후 배열(optstr)에 넣은 후 그 갯수(opt_num)을 리턴해 줍니다.

도움이 되시길...

#include <stdio.h>
#include <string.h>

int main()
{
    char *optstr[100] = {0l,};
    char *str = "1234 가나다라 abcd";
    int opt_num=0, i=0;
    char *delim=" ";

    opt_num=line2opt(&str,optstr,delim);

    for (i=0; i< opt_num; i++)
    {
        printf("%s\n",optstr[i]);
    }

    return 0;
}

int line2opt(char **line, char *opt[], char *delim)
{
    char *buf;
    register int i;

    buf = strdup(*line);

    opt[0] = strtok(buf,delim);

    for(i=1;;i++) {
        opt[i] = strtok(NULL,delim);
        if(opt[i] == NULL) break;
    }

    free(buf); /* 요게 빠졌는것 같습니다. 중요한 습관이죠 */

    return i;
}

언제나 즐프를 꿈꾸며~

cdpark의 이미지

memcpy와 strlen의 조합이라면 그냥 strcpy를 쓰세요.

혹시나 memcpy로 복사할 때는 strlen() + 1 만큼 복사해야 '\0'으로 끝나는 걸 보장할 수 있습니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.