2015-12-22 126 views
1

林做一個非常簡單的TodoList的在C.如何通過價值添加字符串,而不是引用

我的附加功能需要一個char *作爲參數。當我將它添加到我的char **提醒列表中時,它會添加緩衝區的內存地址而不是字符串的值。

當我運行下面給定的源時,問題就變得很明顯。

如果您嘗試[dd]一個字符串,比如說「Test」,然後發出命令[p] rint,則會打印一個「p」。

我明白,這是因爲我的list[0]持有一個指向我的緩存,這樣,當緩衝的值發生變化,所以確實在我的列表中的值。

我的C是生鏽的,我知道strcpy()可能會解決這個問題?但這是處理這個問題的常用方法嗎?

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


int size = 0; 
int capacity = 50; 
char **list; 

void initList() { 
    list = malloc(capacity * sizeof(char *)); 
    for (int i = 0; i < capacity; i++) { 
     list[i] = malloc(256 * sizeof(char)); 
    } 
} 

void saveReminders() { 
} 

void add(char *reminder) { 
    list[size++] = reminder; 
} 

void delete(int index) { 
} 

void print() { 
    for (int i = 0; i < size; i++) 
     printf("%s\n", list[i]); 
} 

void quit() { 
    saveReminders(); 
    exit(0); 
} 

void readReminders() { 
} 

void helpMenu() { 
    printf("Enter a command:\n"); 
    printf("[a]dd a reminder\n"); 
    printf("[d]elete a reminder\n"); 
    printf("[p]rint all reminders\n"); 
    printf("[q]uit\n"); 
} 

void menu() { 
    helpMenu(); 

    while (1) { 
     char buffer[64]; 
     int index = 0; 
     printf("> "); 
     scanf("%s", buffer); 

     if (strcmp(buffer, "a") == 0) { 
      printf("Enter a reminder:\n> "); 
      scanf("%s", buffer); 
      add(buffer); 
      helpMenu(); 
     }else if (strcmp(buffer, "d") == 0) { 
      printf("Remove which index?\n> "); 
      scanf("%d", &index); 
      delete(index); 
      helpMenu(); 
     }else if (strcmp(buffer, "p") == 0) { 
      print(); 
      helpMenu(); 
     }else if (strcmp(buffer, "q") == 0) { 
      quit(); 
     } 
    } 
} 

int main(int argc, char* argv[]) { 
    initList(); 
    menu(); 
} 
+3

你會想複製字符串;) – SBI

回答

3

是的,你認爲是對的。在你的代碼,而不是分配指針本身,這樣做

strcpy(list[size++], reminder); 

內容複製。請參閱man page以供參考。

如果您想要採用第二種方法,則無需爲每個list[i]設置malloc()。除了使用malloc()strcpy()之外,您可以直接使用strdup()並將返回值分配給每個list[i]以獲得相同的結果。

儘管如此,其他一些需要注意的事項

  • 利用的list[size++]之前,請確保size小於capacity,否則你會最終超越分配內存,創建undefined behavior
  • scanf("%s", buffer);應該是scanf("%63s", buffer);以防止任何可能的緩衝區溢出。
  • 在使用返回的指針之前,請檢查返回值malloc()是否成功。在C標準中定義爲1。用它作爲乘數是冗餘。的
+0

我在想這個,但想知道這是否是解決這個問題最常用的方法? 我想我只是問這是不是每個人都在做......謝謝 –

+0

在將內容分配給list [size ++]之前,OP還應該測試'size chqrlie

+0

@chqrlie是的,公平的一點。感謝你的提示,我會在答案中加上這一點。 :) –

0

代替:

list[size++] = reminder 

使用

strcpy(list[size++], reminder) 

或者更好的是,當你SCANF,記得寫的字符數,通過它來添加(),然後執行:

strncpy(list[size++], reminder, len) 
+1

'strnpy' - >'strncpy',不,strncpy不是一個更安全的strcpy版本,反正。 :) –

+0

不要使用'strncpy',特別是源字符串的長度作爲額外的參數。如果源字符串比長度參數長,則'strncpy'不會終止目標緩衝區。這個函數**非常容易出錯**。使用Sourav Gosh的答案中的'strdup()'方法。 – chqrlie

相關問題