[英]Extract decimal numbers from string in C results in segmentation fault
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int Extract(char input[], double output[])
{
int i, j, len;
i=0;
j=0;
len=0;
char s[50];
while(i<strlen(input)-1)
{
if(input[i]==' ') i++;
j=0;
s[0]='\0';
while(input[i]!=',')
{
if(input[i]==' ') i++;
s[j]=input[i];
i++;
j++;
}
s[j]='\0';
i++;
printf("%s - ", s);
output[len]=(double)atof(s);
printf("Element %d: %lf\n", len, output[len]);
len++;
}
printf("%d", len);
return len;
}
int main(){
char s[120]="0.1,0.35,0.05,0.1,0.15,0.05,0.2.";
double v[1000];
int len = Extract(s, v);
int i;
for(i=0; i<len; i++)
{
printf("%d: %lf\n", i, v[i]);
}
return 1;
}
我嘗試運行此代碼,但即使它正確編譯,我也有堆棧錯誤,有人可以幫助我嗎? 請注意,字符串由一些以逗號分隔的十進制數字組成,字符串以 .
更新:也許文件夾中有一些臟東西,但現在我有一個輸出:長度:32
0.1 - 元素 0:0.000000
0.35 - 元素 1:0.000000
0.05 - 元素 2:0.000000
0.1 - 元素 3:0.000000
0.15 - 元素 4:0.000000
0.05 - 元素 5:0.000000
分段錯誤(核心轉儲)
由於我已經制作了線程,我是否仍然可以利用您的幫助將字符串轉換為雙精度,因為atof
正在轉換為浮點數,這可能就是它打印所有 0.0000 的原因?
我想我發現了問題:
','
。 在您輸入的末尾,您沒有','
字符,而是有一個'.'
這將導致您的循環永遠持續下去,從而導致段錯誤。 您可以通過將輸入的最后一個字符更改為','
來修復它。%lf
更改為%.2lf
。這完全取決於您的輸入受到的監管。 如果可以,請先處理您的輸入,然后再將其輸入到您的函數中。
如果這有幫助,請告訴我們!
我在這里展示了 3 個代碼,其中第一個解決了段錯誤問題; 第二,對所呈現的 Extract 功能的詳細評論; 第三,以多種可能的改進形式之一編寫的 Extract 函數示例。
主要的收獲應該是始終防止代碼中的緩沖區(數組)溢出並與調試器交朋友。
代碼中 printf 的重復表明沒有使用調試器。 編碼任何超越瑣碎(你好,世界?)的東西都需要調試器知識。 了解調試器等工具與了解語言一樣重要。
我希望這可以作為一個指南,甚至是一些靈感。 祝你的編碼冒險好運。
這是修復段錯誤(數組溢出)的最小更改的原始代碼
int Extract(char input[], double output[])
{
int i, j, len;
i = 0;
j = 0;
len = 0;
char s[50];
while (i<strlen(input) - 1)
{
if (input[i] == ' ') i++;
j = 0;
s[0] = '\0';
/* Primary bug fix; guard against input array overrun *and* check for separator */
while (input[i] && input[i] != ',')
{
if (input[i] == ' ') i++;
s[j] = input[i];
i++;
j++;
}
s[j] = '\0';
/* bug fix; guard against input array overrun when incrementing */
if (input[i]) {
i++;
}
printf("%s - ", s);
output[len] = (double)atof(s);
printf("Element %d: %lf\n", len, output[len]);
len++;
}
printf("%d", len);
return len;
}
這是對原始代碼的批評。
int Extract(char input[], double output[])
{
/* Tedious variable declaration and initialization */
int i, j, len;
i = 0;
j = 0;
len = 0;
/* why not 70? or 420? */
char s[50];
/* This is an exceedingly expensive way to determine end of string. */
while (i<strlen(input) - 1)
{
/* Why test for space? There are no spaces in sample input.
This increment risks overrunning the input array (segfault)
*/
if (input[i] == ' ') i++;
j = 0;
s[0] = '\0';
/* no guard against input array overrun */
while (input[i] != ',')
{
/* Why test for space? There are no spaces in sample input.
This increment risks overrunning the input array (segfault)
*/
if (input[i] == ' ') i++;
s[j] = input[i];
i++;
j++;
}
s[j] = '\0';
/* Bug - no guard against input array overrun when incrementing i */
i++;
/* these print statements suggest someone is NOT using a debugger - major fail if so. */
printf("%s - ", s);
output[len] = (double)atof(s);
printf("Element %d: %lf\n", len, output[len]);
len++;
}
/* again, this is easily seen in the debugger. Use the debugger. */
printf("%d", len);
return len;
}
最后,有一些(櫻桃采摘)約定的替代提取物。
int Extract(double* output, const int output_max, const char* input, const char separator)
{
/* declare variables in the scope they're needed and ALWAYS give variables meaningful names */
int input_index = 0, output_count = 0;
/* Detect end of string and guard against overrunning output buffer */
while (input[input_index] && output_count < output_max)
{
const int BUFFER_MAX = 50;
/* let the compiler init buffer to 0 */
char buffer[BUFFER_MAX] = { 0 };
int buffer_index = 0;
/* accumulate values into buffer until separator or end of string encountered */
while (input[input_index] && input[input_index] != separator)
{
buffer[buffer_index++] = input[input_index++];
if (buffer_index == BUFFER_MAX) {
/* Overrun, cannot process input; exit with error code. */
return -1;
}
}
/* only convert buffer if it had accumulated values */
if (buffer_index) {
/* note atof will discard, say, a trailing period */
output[output_count++] = atof(buffer);
}
/* Guard against input_index increment causing an array overrun (possible segfault) */
if (input[input_index]) {
input_index++;
}
}
return output_count;
}
int main() {
const int OUTPUT_MAX = 1000;
const char separator = ',';
const char* input = "0.1 ,0.35,0.05,0.1,0.15,0.05,0.2.";
double output[OUTPUT_MAX];
const int num_elems = Extract(output, OUTPUT_MAX, input, separator);
/* print results to stdout */
if (num_elems == -1) {
fprintf(stdout, "\nElement too long to process error\n");
}
else {
fprintf(stdout, "\nTotal number of elements: %d\n\n", num_elems);
for (int i = 0; i < num_elems; i++) {
fprintf(stdout, "Element %d: %lf\n", i, output[i]);
}
}
return num_elems;
}
祝你的編碼冒險好運。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.