gcc에서 구조체를 사용하여 시리얼 데이터를 받으려 합니다

callor의 이미지

시리얼 통신을 하면서 구조체를 이용하여 데이터를 받아 오려 합니다.

그런데, 원하는 값이 나오질 않아 질문 올립니다.

typedef struct
{

char dev_key[3], dev_name[10, dev_value[4] ;

} DEV_STR ;

DEV_STR sBuf ;

;;;;;;;;;;;;;;;;;;;

// 시리얼 통신을 위해 Device를 Open
fp = open("/dev/ttyAMA0", O_RDONLY | O_NOCTTY );

res = read( fp, & sBuf, sizeof(DEV_STR)) ;

// 시리얼을 통해 넘어오는 데이터
// CONROOM 0034

// 위와 같이 read를 통해 읽은 데이터를 화면에 표시

printf("KEY : %s \n", sBuf.dev_key ) ;
printf("KEY : %s \n", sBuf.dev_name ) ;
printf("KEY : %s \n", sBuf.dev_value ) ;

// 결과값
CONROOM 0034
ROOM 0034
0034

왜 위와 같이 출력이 되는지 도무지 이유를 알수 없어 글 올립니다.

도와 주십시요

twinwings의 이미지

당연히 저렇게 출력이 되지요..

C에서는 객체(구조체)의 경계에 대해서 런타임에 아무런 정보를 가지고 있지 않습니다.

송신측에서
CONROOM 0034(12바이트)
데이터를 송신하면 구조체에 해당 데이터가(12바이트)가 구조체 처음부터 차곡차곡 저장됩니다.

다른말로하면

struct {
    char dev_key[3];     /* CON, 3바이트 */
    cahr dev_name[10];   /* ROOM 0034,  9바이트 */
    cahr dev_value[4];   /* 정보 없음(쓰레기 값) */
};

요렇게 저장될겁니다. 출력시에 당연히 dev_key의 경우 NULL문자가 없으니까

NULL 문자 나올때까지 출력하는 거구요.

그리고 통신예제는 송신, 수신 둘다 올려주셔야 질문이 말이됩니다.

수신쪽만 올리시면 안되요.

callor의 이미지

널 문자에 대한 이해가 다소 부족했나 봅니다.

통신 프로그램 문제라기 보단 제가 구조체에 대한 이해가 부족하여 롤린 질문이니

너그러이 앙해 부탁드립니다.

감사합니다.

익명 사용자의 이미지

위에서 이렇게 출력하셨습니다.

printf("KEY : %s \n", sBuf.dev_key ) ;
printf("KEY : %s \n", sBuf.dev_name ) ;
printf("KEY : %s \n", sBuf.dev_value ) ;

그런데, printf() 는 무조건 \0 즉, NULL문자가 나올때 까지 출력합니다.

해결책 1). printf() %s 출력자에게 요청하기 ( % + '.' + 길이 + s )

예시) %.3s : 문자열이 널로 끝나지 않아도 3자만 출력한다.
즉,
printf("KEY : %.3s \n", sBuf.dev_key ) ;
printf("KEY : %.10s \n", sBuf.dev_name ) ;
printf("KEY : %.4s \n", sBuf.dev_value ) ;

이런식이 되겠습니다.

해결책 2 ) 출력전에 NULL로 종료되는 문자열로 변경한다.
char outBuf[4];

memset(outBuf, 0, 4);
memcpy(outBuf, sBuf.dev_key, 3); // 마지막에 \0 문자(널)가 들어 가므로 printf()에서는 그냥 %s로 해도 출력될 것이다.
printf("KEY : %s \n", sBuf.dev_key ) ;

-------------
* tip) 통신 프로그램에서 실수를 줄이기 위해서는 str*()함수를 모두 포기하고, mem*()함수를 쓰는 습관을 가지도록 하세요.
포기하는 이유는 인간이니까, 그리고, 문자열 처리에서 발생할 수 있는 문제를 원천 회피(!)하기 위함입니다. str*()은 잠재적으로는 버그를 내포할 수 있다는....
* tip) 시리얼 통신에서는 송/수신버퍼의 크기를 디폴트 크기로 사용하지 말고, 보다 늘려 주는게 도움이 됩니다.

익명 사용자의 이미지

이런 오타가 났네요.
해결책 2) 에서, 마지막 프린트문(printf())는 다음과 같아야 합니다.

printf("KEY : %s \n", outBuf ) ;

----

3333======ㅎㅎ

callor의 이미지

많이 초보인지라 사소한 것들에서 발생하는 문제를 해결하지 못하고 헤메이고 있습니다.^^

mem* 관련 함수에 대해 좀더 깊이 있게 공부해봐야 겠습니다.

감사합니다.

shint의 이미지

저는 윈도우 CYGWIN 에서 해봤습니다.

구조체 전송은 잘 안되네요.

그래서.
그냥. char buf[20]; 잡아서 전송하니 잘 됩니다.

참고하시기 바랍니다.

댓글 첨부 파일: 

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

callor의 이미지

감사합니다.

좋은 소스까지 주셔서 공부하는데 많은 도움이 되겠습니다.^^

char buf[20] 을 사용했는데

수신측에서 문자열 자를때 아직 익숙하지 않아서

예전 파일에서 읽을때 구조체로 읽어 들이면 좀 쉽게 되었기에 꼼수 부려 볼 생각이엇습니다만 잘 안되는군요..

다시 한번 감사 드립니다.

댓글 달기

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