2011-07-10 46 views
0

我得到了如下代碼:的fputs和printf問題

char* writeSpace(int i) 
{ 
fputs("        " + (30-i), stdout); 
} 

printf("#%i key: %s%svalue: %s%s value2: %s", id, key, writeSpace(10), value, writeSpace(8), value2); 

我的輸出應該是這個樣子:

#1 key: foo   value: bar  value2: foobar 

,但事實並非如此。它看起來像:

     #1 key: foo(null)value: bar(null)value2: foobar(null) 

我的代碼有什麼問題?

+0

你爲什麼要使用這些舊的遺留功能?您可以訪問C++標準庫:使用它。 –

+1

這看起來應該用'C'(而不是'C++')標記。 – Johnsyweb

+0

請解釋一下你想做什麼:讓writeSpace(i)創建並返回一串i *空白字符串,或者你想要一個副作用,以便writeSpace(i)將這樣的字符串寫入一個流?甚至是兩者? – Nico

回答

4

那麼,你是fput所有這些空間到控制檯,所以你讓他們第一。

然後你輸出所有的東西,所以你明白了。

也許你的意思是writeSpace返回一個C風格的字符串,而不是打印到控制檯。

但是一定要爲它分配空間!由於內存緩衝區的所有權變得有點詭異,因此最好在該函數的之外分配空間

void writeSpace(char* buf, int i) { 
    fputs("        " + (30-i), buf); 
} 

char spaceBuf1[30]; 
writeSpace(spaceBuf1, 10); 

char spaceBuf2[30]; 
writeSpace(spaceBuf2, 8); 

printf("#%i key: %s%svalue: %s%s value2: %s", 
    id, key, spaceBuf1, value, spaceBuf2, value2); 

,並考慮使用像iostream和std::string實際 C++功能。它會容易得多:

std::cout << "#" << id << " " 
      << " key: " << std::setw(30) << key 
      << " value: " << std::setw(30) << value 
      << " value2: " << value2; 

我推薦these resources學習習慣C++。

4

您已聲明writeSpace()返回char*,但您尚未從中返回任何內容。

0

您的writeSpace函數沒有返回一個新字符串(即使您已經這樣聲明),但是直接寫入終端。由於您在printf調用中將其稱爲參數,因此首先調用writeSpace,打印其內容,然後printf打印其內容。你應該做的是這樣的:

char* writeSpace(int i) 
{ 
    char *ret = NULL; 
    asprintf(ret, "        " + (30-i)); 
    return ret; 
} 

當然,這需要你free內存(否則你就會有一個內存泄漏)。你可以做這樣的:

char *spaces = writeSpace(10); 
printf("%s%i", spaces, 42); 
free(spaces); 

另一種方法是使用一個靜態變量,函數本身下次調用清理:

char* writeSpace(int i) 
{ 
    static char *ret = NULL; 
    if (ret != NULL) free(ret); 
    asprintf(ret, "        " + (30-i)); 
    return ret; 
} 

但其缺點是,你只能使用在你的printf參數中一個調用writeSpace,因爲第二個將清除先前調用的內存。仍然可能是你想要的。

順便說一句,+ (30-i)部分是邪惡的。你可能想要的是這個:

asprintf(ret, "%*s", i, ""); // Prints i spaces 
0

如果要格式化變量WS',你絕對必須使用純C,你可以使用這種格式的字符串(%* c,其中*是WS的數量和c表示字符設置(」'在這種情況下,當然)):

sprintf(buffer, "%*cafterspace", 30, ' '); // Will print 30 ws and then "afterspace".
sprintf(buffer, "%*cafterspace", 15, ' '); // Will print 15 ws and then "afterspace".

但你還是得準備一個緩衝區託默勒格解釋!

0

提供的其他答案有您正在尋找的正確答案。不過,我想嘗試添加一些關於您所看到的症狀的小解釋,以幫助您在將來避免它們。

當執行你的printf語句:

printf("#%i key: %s%svalue: %s%s value2: %s", id, key, writeSpace(10), value, writeSpace(8), value2); 

兩個writeSpace()中的printf本身做任何事情之前,方法調用執行。原因是這些方法的返回值被用作printf方法的參數。因此,上述代碼行的執行順序爲:

  • writeSpace(10)將一些空格輸出到標準輸出並返回空指針。
  • writeSpace(8)打印一些更多的空白到標準輸出並且還返回一個空指針。
  • 最後的printf被稱爲以以下的參數:輸出( 「#%i鍵:%S%S值:%s%S值2%S」,身份證,鑰匙,,價值,,值2 );

這就是爲什麼你在開頭看到空格打印的原因,也是爲什麼你看到「(null)」出現在輸出中。

所以這裏學到的教訓是,在程序執行過程中,方法的參數在方法本身被調用之前被解析。