我試圖將兩個字串相加,這是我的嘗試:
- 使用 strtol 將字串轉換為數字,因為它比 atoi 更安全。
- 計算總和。
- 使用 log(以 10 為底)四舍五入使用 floor 1 查找位數。(這是完成該任務的最快方法)。(我使用了 floor,因為 floor 將數字四舍五入到左側最接近的整數)。
- 我已經在堆中分配了足夠的記憶體來存盤每個數字。
- 我使用 snprintf 將數字存盤在字串中。
問題是該函式只回傳“4”,而不是“42”。我認為微妙的部分是最后一步。
另一件事是:“可能丟失資料:從 double 到 size_t”。但它是四舍五入的,因此它應該不是問題,但我仍然在錯誤/警告串列中。(我使用視覺作業室)。
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
char* sum_of_strings(const char* a, const char* b) {
int x = strtol(a, NULL, 10); int y = strtol(b, NULL, 10);
int sum = x y;
size_t length = floor(log10(sum)) 1;
char* str = malloc(length 1);
if (str == NULL) {
return NULL;
}
snprintf(str, length, "%d", sum);
return str;
}
int main(void) {
char a[] = "34";
char b[] = "8";
char* str = sum_of_strings(a, b);
free(str);
return 0;
}
uj5u.com熱心網友回復:
你可能想多了這個問題。
輸出字串的最大大小 [相當] 小于 64 位元組。
所以,如果我們使用一個固定大小的緩沖區來做sprintf,我們可以完全消除所有的浮點舍入:
char *
sum_of_strings(const char *a,const char *b)
{
int x = strtol(a,NULL,10);
int y = strtol(b,NULL,10);
int sum = x y;
char str[64];
sprintf(str, "%d", sum);
return strdup(str);
}
上面的代碼非常簡單快速。
但是,strdup必須[有效地]掃描字串兩次:一次獲取長度,第二次將其復制到分配的緩沖區。
我們可以 [可能] 稍微加快一點:
char *
sum_of_strings(const char *a,const char *b)
{
long x = strtol(a,NULL,10);
long y = strtol(b,NULL,10);
long sum = x y;
char str[64];
ssize_t len = sprintf(str, "%ld", sum);
// add space for EOS
len;
char *ret = malloc(len);
if (ret != NULL)
memcpy(ret,str,len);
return ret;
}
獲取位數的常用方法不是使用浮點數,而是:
size_t len = (sum != 0) ? 0 : 1;
for (long tmp = sum; tmp != 0; tmp /= 10, len);
可以說,這可能比浮點[在具有快速 H/W FPU 的系統上] 慢。我認為您已經對兩種方式進行了基準測驗[能夠說明您的 FP 方法是最快的]。如果沒有,以上內容可能會替代您的 FP 代碼。
[平均]真的floor(log10(sum))比 5 個定點除法更快嗎?
但即使這樣也沒有考慮隱藏成本。
sprintf等。人。在生成其輸出時必須做同樣的事情(例如sum % 10和sum /= 10)。
如果我們對速度很“瘋狂”,并且如果我們做我們自己的有限版本sprintf,我們可以在與數字存盤相同的回圈中進行長度計算:
#include <stdlib.h>
#include <string.h>
#define MAXBUF 64
char *
sum_of_strings(const char *a,const char *b)
{
long x = strtol(a,NULL,10);
long y = strtol(b,NULL,10);
long sum = x y;
char str[MAXBUF];
char *lhs = &str[MAXBUF];
// store digits in right-to-left order
for (; sum != 0; sum /= 10)
*--lhs = (sum % 10) '0';
// get number of digits
size_t len = &str[MAXBUF] - lhs;
// handle special case of sum being zero
if (len == 0) {
*--lhs = '0';
len;
}
// allocate the space
char *ret = malloc(len);
// copy out the data
if (ret != NULL) {
memcpy(ret,lhs,len);
ret[len] = 0;
}
return ret;
}
當然,哪種方法“最好”取決于簡單性/復雜性與 [基準] 速度。也就是說,為[可能的]速度增益增加復雜性值得嗎?
YMMV...
uj5u.com熱心網友回復:
我已經修改了您的sum_of_strings代碼,現在它似乎正在根據您的示例作業。
更改包括以下內容:
- 資料型別現在是 long 而不是 ints
- 我在長度上添加了兩個位元組來說明地板和空位元組
- 字串的最后一個位元組設定為空位元組,這使得列印作業正常
char* sum_of_strings(const char* a, const char* b) {
long const x = strtol(a, NULL, 10);
long const y = strtol(b, NULL, 10);
long const sum = x y;
size_t const length = floor(log10(sum)) 2;
char * const str = malloc(length);
if (str == NULL) {
return NULL;
}
snprintf(str, length, "%ld", sum);
str[length - 1] = '\0';
return str;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/426979.html
上一篇:洗掉每個重復的子字串,區分大小寫
