2013-01-24 119 views
1

我在將結構寫入共享內存時遇到問題,因爲當我這樣做時,代碼只寫入結構的第一部分。C - 將整個結構寫入共享內存的困難

這裏是我的數據結構:

struct shmData{ 
    char number[4]; 
    char description[1020]; 
}; 

這裏是我的代碼:

//Structure Pointer - placed on SHM 
struct shmstruct *ptr; 
char description_to_write[1024] = {0}; 
struct shmData *data_ptr; 
data_ptr = (struct shmData*) description_to_write; 

//Shared Memory init 
create_shm(&ptr); 
printf("Started\n"); 

//Define Offsets 
//init_shm(ptr); 

//######################### 

//Check if number exist 
    if (!(strcmp("NO SUCH CODE\0", get_description(ptr, 6)))) { 
     //-> If not, get next offset (nput) where to write new data 
//  sem_wait(&ptr->mutex); 
//  long offset = ptr->msgoff[ptr->nput]; 
//  printf("OFFSET: %li\n", offset); 
//  if (++(ptr->nput) > NMESG) 
//   ptr->nput = 0; /* circular buffer */ 
//  sem_post(&ptr->mutex); 
//  printf("Buffer: %s", argv[2]); 

    snprintf(data_ptr->number, 4, "%s", "6"); 
    snprintf(data_ptr->description, 1020, "%s\n", argv[2]); 

    printf("DATA: %s\n", data_ptr->number); 
    printf("DATA: %s\n", data_ptr->description); 

    printf("description_to_write: %i\n", description_to_write); 

    //strcpy(&ptr->msgdata[offset],); 
    //sem_post(&ptr->nstored); 
    //printf("Wrote...\n\n"); 
} else { 
    //-> Else get offset of this number and put data to it 
} 

我應該怎麼寫呢?在上面的代碼中,我試圖簡單地顯示描述數組,但我只獲取數字。

我需要它被寫入到共享存儲器如下:

Number(space)(space)(space)Description 

共享內存轉儲看起來像:

00003b0: 3120 2020 496e 7075 7420 4572 726f 720a 1 Input Error. 
00003c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 
* 
00007b0: 3220 2020 4f75 7470 7574 2045 7272 6f72 2 Output Error 
00007c0: 0a00 0000 0000 0000 0000 0000 0000 0000 ................ 
00007d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 

從調試器:

description_to_write[0] char 54 '6' 
description_to_write[1] char 0 '\000'  
description_to_write[2] char 0 '\000'  
description_to_write[3] char 0 '\000' 
description_to_write[4] char 83 'S' 
description_to_write[5] char 111 'o' 
description_to_write[6] char 109 'm' 
description_to_write[7] char 101 'e' 
description_to_write[8] char 84 'T' 
description_to_write[9] char 101 'e' 
description_to_write[10]char 120 'x' 
description_to_write[11]char 116 't' 
description_to_write[12]char 10 '\n' 

醜陋溶液:

int i = 0; 
     while(i < 4){ 
      if(data_ptr->number[i] == '\000'){ 
       data_ptr->number[i] = 32; 
      } 
      i++; 
     } 
+0

你會得到什麼輸出*完全*? 'data_ptr'從哪裏來? –

+0

對不起,我忘了一些代碼,等一下 – x4k3p

+0

另外,你確定你的意思是'argv [2]'而不是'argv [1]'?如果你確定,你確定'argc'大於或等於三? –

回答

4

傳遞給snprintf的4指定了要寫入的最大字符數。不是寫的金額。 snprtinf返回它寫入的字符數。所以你只打印1個字符,之後會留下3個空值。

只要做到:

snprintf(data->number,4,"%s ","6"); 

這樣,它會嘗試打印字符串後面4位,並打印4個charcacters一個最大值。

+0

幾乎 - 'data-> number [3]'將是一個空終止符而不是空格(或者不是第四個數字大於999)。 –

1

你醜陋的解決方案使用snprintf()然後重寫「\ 0」字符空格有一些缺陷:

  • snprintf()絕不會寫一個數字爲data_ptr->number[3]。對於長度超過3個字符的字符串,它將截斷並寫入'\ 0',而不是複製源字符串中的第4個字符。

  • ,除非你確定的結構將是以後「\ 0」是snprintf()被要求寫不會被snprintf()任意設置主叫snprintf()然後字符前初始化爲零。這在發佈代碼時可能不會有問題,但是在面向更改結構data_ptr指向的結構時,它是脆弱的。

由於該領域是如此之小,你可能會考慮這樣的:

memset(data_ptr->number, ' ', sizeof(data_ptr->number)); 
memcpy(data_ptr->number, "6", strlen("6")); 

仍然有你需要添加更多的邏輯,如果源字符串都不可能長於一個缺點字段大小。另外,如果你在一兩個以上的位置上做的事情很容易成爲複製/粘貼錯誤的來源。

這裏是一個輕測試功能,您可以使用,而不是(雖然我得承認,我最討厭的名稱):

size_t str2mem_padded(char* dest, size_t dest_size, char const* src, char fill) 
{ 
    size_t result = 0; 

    while (dest_size && *src) { 
     *dest++ = *src++; 
     ++result; 
     --dest_size; 
    } 
    while (dest_size) { 
     *dest++ = fill; 
     --dest_size; 
    } 

    return result; // returns number of chars copied from src so you 
        // can determine if there was truncation 
} 

在代碼中,你可以使用以下的,而不是調用snprintf(data_ptr->number, 4, "%s", "6")

str2mem_padded(data_ptr->number, sizeof(data_ptr->number), "6", ' '); 

哇 - 這比我想象的要多得多。