簡體   English   中英

從 C 中的字符串中提取十進制數會導致分段錯誤

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM