評價: 3 回應: 2 閱覽: 349
置頂

用memcpy 會有殘餘值怎麼辦?

太后在撰寫C++的時候

我用 memcpy (Ptr->ListString, CharPtr, Length);

去餵資料,然後用link list 去存值,在只有兩個字元時,會多了殘餘值

餵入的資料是char StringOriginalData[100] = "Abian is son of the bitch";

預期的正確結果(Expected Output):
Abian 5
is 2
son 3
of 2
the 3
bitch 5

錯誤結果(Wrong Output):
Abian 5
iss 2
son 3
ofs 2
the 3
bitch 5
 

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

char StringOriginalData[100] = "Abian is son of the bitch";
char StringChange[10] = "are";



typedef struct _VOCABULARY_LIST {
  char *ListString;
  struct _VOCABULARY_LIST *Node;
}VOCABULARY_LIST;

void TearOffAndAdd (VOCABULARY_LIST *Ptr);

int main (int argc, char *argv[]) {
  VOCABULARY_LIST *FirstVocabulary;
  VOCABULARY_LIST *PtrVocabulary;
  FirstVocabulary = (VOCABULARY_LIST *)malloc (sizeof (VOCABULARY_LIST));
  PtrVocabulary = FirstVocabulary;
  PtrVocabulary->Node = NULL;

  TearOffAndAdd (PtrVocabulary);

  system("PAUSE");
  return 0;
}

void TearOffAndAdd (VOCABULARY_LIST *Ptr) {
  char *CharPtr;
  VOCABULARY_LIST *NewList;
  int Length;

  CharPtr = StringOriginalData;
  Length = strcspn (CharPtr, " ");

  while (Length != 0) {
    Ptr->ListString = (char *)malloc (Length * sizeof(char));
    memcpy (Ptr->ListString, CharPtr, Length);
    printf ("s",  Ptr->ListString);
    printf (" d\n",Length);
    NewList = malloc (sizeof (VOCABULARY_LIST));
    NewList->Node = NULL;
    Ptr->Node = NewList;
    Ptr = NewList;

    CharPtr += (Length + 1);
    Length = strcspn (CharPtr, " ");
  }


}

這個問題要請教各位先進,該怎麼解決呢?

熱門回應

memcpy只是如實的複製memory裡的值喔 不會幫你生出\0

另一方面s是看\0決定結束在哪 你沒有給\0它不知道到哪結束

你可以找memcpy strcpy strncpy的code比較差異

我沒有仔細看你的本文,不過針對你補充的部分:

    Ptr->ListString = (char *)malloc ((Length + 1) * sizeof(char));
    memset (Ptr->ListString, '\0', Length + 1);
    memcpy (Ptr->ListString, CharPtr, Length);
    strcat (Ptr->ListString , "\0");
    printf ("s",  Ptr->ListString);
    printf (" d\n",Length);

有些建議

1. strxxx系列function以及s顧名思義都是在處理string

   string的定義就是結尾為0(='\0')的char array

   因此你沒有放'\0'在結尾之前,都別用這些functions,會壞掉

   (這也是為啥有strxxx_s系列的理由)

2. memxxx系列的效率比strxxx系列高很多

   因為後者除了要處理array以外,還要隨時注意'\0'到了沒

3. 雖然memxxx比較快,但copy本質上就是比用指標重複利用一塊data來得慢

   所以盡量用指標處理資料傳遞,當然用指標比較難而且比較多限制就是

4. 如果你打定主意這個array都要用string形式處理,那memset就不用做了

   浪費成本

   舉個例子: a[0]='A', a[1]='B', a[2]='\0', a[3]='C'

             b[0]='A', b[1]='B', b[2]='\0', b[3]='\0'

   用printf("s s", a, b)印出來的a,b字串是一模一樣的,都是AB

   不管a[3]是多少,從s[0]開始掃到a[2]發現有'\0'時,電腦就會結束掃下去了

5. 承第一點,strcat的意思是"在str開始第一個出現'\0'的位置後面接上指定字串"

   言下之意是,如果你能接上指定字串"\0",代表它前面有個'\0'

   另外"\0"是個字串,裡面有\跟0,用單引號包起來的'\0'才是0的意思

   你strcat (Ptr->ListString , "\0");這一行是一點意義也沒有的

   真正幫你補0的是你一開始的memset (Ptr->ListString, '\0', Length + 1);

   可如同我第四點所說的,你這樣做是有點浪費成本的

   因為[0]~[Length]才改完的值隨即會被memcpy蓋過,很心酸~

   (也是可以寫啦,看風格,有人覺得浪費點成本但是初始時寫memset比較整齊)

 


建議如下:

    Ptr->ListString = (char *)malloc ((Length + 1) * sizeof(char));
    memcpy (Ptr->ListString, CharPtr, Length); //等同[0]~[Length-1]裡放滿值
    *(Ptr->ListString + Length) = '\0'; //[Length]放'\0',等同補成完整string
    printf ("s",  Ptr->ListString); //因為[Length]放'\0',所以可以正常顯示
    printf (" d\n",Length);

會員登入 (先登入會員才能回覆留言喔!)

Facebook留言