赛格。故障逐行读取

时间:2016-01-22 23:35:14

标签: c segmentation-fault

我正在尝试计算每行显示最多的模式或整数。

我得到一个打印两个值然后分段错误。

        for (i = 0; i < count; i++) {

            if (array[i]) {
                int i, j, k, cnt = 1, p, big;
                int b[MAX_NUM] = {0};
                printf("count:%d\n", count);
                for (i = 1; i <= array[i]; i++) {
                    for (j = i + 1; j <= array[i]; j++) {
                        if (array[i] == array[j])
                            printf("cnt:%d\n", cnt);
                        cnt++;
                    }
                    printf("cnt2:%d\n", cnt);
                    b[k] = cnt;
                    k++;
                    cnt = 1;
                }        
                big = b[k];
                p = 1;

                for (i = 2; i <= array[i]; i++) {
                    if (big < b[i]) {
                        big = b[i];
                        p = i;
                    }
                }
                printf("The element that occurs offen is %d\n", array[p]);
                printf("And it has occurred %d times\n", b[p]);
            }
        }
    }
}
}

return 0;
}

编辑:

请参阅我的代码中的外观。打印的值是文件每行的数字,后跟一个空行,如下所示:

1
2
3
4
5
6
5
4
5

14
62
48
14
1
3
5
7
9

123
456
789
1234
5678

34
34
34
34
34

1

1
2
2
2
2
2
3
3
4
4
4
4
5
5
6
7
7
7
1
1

Integers: 9
.....

2 个答案:

答案 0 :(得分:2)

您在内部作用域中重新定义ip,它们会影响当前定义。这显然是无意的,因为表达式看起来非常错误:

if (array[i]) {
    int i, j, k=1, cnt = 1, p, big;
    //  ^
    //  Redefinition of i.
    //  You should use a different name for the loop index below
    //  Same remark for p, it is safer to not redefine local variables
    //  in inner scopes.  Any { starting a block creates a new scope
    //  in which variables can be defined, or in this case redefined.
     ...
    for (i = 1; i <= array[i]; i++) {
        ...
    for (i = 2; i <= array[i]; i++) {
        ...

在代码的同一区域,您使用k而无需事先初始化。

计算最大出现次数的代码可以放入一个单独的函数中并以这种方式简化:

#include <stdio.h>

// get the number of ocurrences of val in array a of size n
int get_number_of_occurrences(int a[], int n, int val) {
    int cnt = 0, i;

    for (i = 0; i < n; i++) {
        if (a[i] == val)
            cnt++;
    }
    return cnt;
}

// return the index for the number that occurs the most
int get_max_occurrence_index(int a[], int n) {
    int p = 0, cnt, max = 0, i;

    for (i = 0; i < n; i++) {
        cnt = get_number_of_occurrences(a, n, a[i]);
        if (max < cnt) {
            max = cnt;
            p = i;
         }
     }
     return p;
}

int main() {
    int i, n, a[20], max;

    printf("Enter the maximum number of elements\n");
    scanf("%d", &n);
    printf("Enter the elements\n");
    for (i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }
    i = get_max_occurrence_index(a, n);
    max = get_number_of_occurrences(a, n, a[i]);
    printf("The element that occurs most oftenly is %d\n", a[i]);
    printf("And it has occurred %d times\n", max);
    return 0;
}

如果要在原始程序中使用此逻辑,则应在读取文件时将其用于每行,而不是在仅应用于最后一行的末尾。行解析代码也是错误的:您将第一个数字的ASCII值作为值,而不是使用strtol()解析它。

以下是更正后的版本:

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

#define MAX_NUM 1000
#define MAX_LINE_LEN 2048
#define N 100

void fatal(const char *msg) {
    printf("%s\n", msg);
    exit(1);
}

int main(int argc, char *argv[]) {
    FILE *fp;
    char filename[100];
    char line[MAX_LINE_LEN];
    char *p;
    int array[MAX_NUM];
    int index, count, max;

    printf("Please enter the file name: \n");

    if (scanf("%99s", filename) != 1) {        
        fatal("Error in entering file.");
    }

    if ((fp = fopen(filename, "r")) == NULL) {
        fatal("Unable to open the file.");
    }

    while ((p = fgets(line, MAX_LINE_LEN, fp)) != NULL) {
        /* skip white space */
        p += strspn(p, " \t\n");
        if (*p == '#' || *p == '\0') {
            /* ignore comment and blank lines */
            continue;
        }
        /* scan and convert the numbers */
        for (count = 0; *p != '\0'; ) {
            if (isdigit((unsigned char)*p)) {
                array[count++] = strtol(p, &p, 10);
                printf("%d\n", array[count]);
            } else {
                /* skip to next space or end of string */
                p += strcspn(p, " \t\n");
            }
            /* skip white space after the number */
            p += strspn(p, " \t\n");
        }

        index = get_max_occurrence_index(array, count);
        max = get_number_of_occurrences(array, count, array[index]);

        printf("The element that occurs most often is %d\n", array[index]);
        printf("And it has occurred %d times\n", max);
    }
    fclose(fp);
    return 0;
}

答案 1 :(得分:2)

也许我只是看不到您的代码,但我没有看到您将文件中的实际数字加载到任何变量或数组中以供使用。

您正在使用while ((p = fgets(line, MAX_LINE_LEN, fp)) != NULL) {加载一行 在该循环中,您将此行分为标记以计算您拥有的数字。

据我所见,array[count]++;用于计算每行中有多少个数字。使用索引作为行号。

您应首先考虑如何将数据转换为可用格式
您可以开始尝试将值加载到二维数组中 使用行号的第一个维度和值的第二个维度。

如果您不能很好地理解您的代码,则应该从更多评论开始
你用什么你的差异和变量。
#define MAX_NUM 1000 //maximum number of lines

int array[MAX_NUM] = {0}; //index refers to line number of file. used to count numbers in each line.

// read file line by line, split every line into tokens to count amount of numbers
while ((p = fgets(line, MAX_LINE_LEN, fp)) != NULL) {
    if (count >= MAX_NUM) {
        fatal("Array error");
    }
    if (line[0] != '#') {
        p = strtok(line, " ");
        while (p != NULL) {
            if (isdigit(*p)) {
                array[count]++;
            }
            p = strtok(NULL, " ");
        }
    }
    count++;
    //printf("COUNT:%D\n", count);
}  

另外选择好的变量名称会更好
#define MAX_NUM 1000 - &gt; #define MAX_LINE_NUM 1000

我不知道您的变量int i, j, k, cnt = 1, p, big;做了什么。 给他们更好的名字或评论他们。不仅会帮助你,还会帮助你了解你打算用它们做什么。

首先我认为您需要有关模式算法的帮助,所以我先写了这个:
使用非常基本的东西来保持尽可能简单。 如果你知道如何把它变成功能会更干净。 没有使用函数,因为你似乎并不完全知道如何使用它们(你应该研究一下)

此算法执行以下操作:

  1. 获取数组中的第一个数字
  2. 运行数组,每次找到该数字时,都会增加counter
  3. 将号码和计数保存为highesthighestCnt
  4. 重复数组中的每个数字,并在highest
  5. 时覆盖highestCntcount > highestCnt

    当有多个出现次数最多的数字时,它只会记住先计算的数字。如果要返回具有最高出现次数的所有数字,则需要更改该数字。 可以做一些事情,比如检查count == highestCnt然后设置一些东西,这样你就知道没有一个具有最高计数的数字,直到找到一个具有更高计数的数字。

    #include<stdio.h>
    
    #define sizea 100
    
    int main(void) {
        int array[sizea] = { 1,3,6,8,3,6,7,4,6,9,0,3,5,12,65,3,76,5,3,54,
                             1,3,6,89,3,6,7,4,6,9,0,4,5,12,65,3,76,5,3,54,
                             1,9,6,8,3,45,7,4,6,9,0,89,5,12,65,3,76,5,3,54,
                             6,3,6,8,3,6,7,4,6,9,0,23,5,12,65,3,76,5,3,54,
                             1,3,6,90,3,6,7,4,6,9,0,5,5,12,65,3,76,5,3,54 };
    
        int number;
        int count = 1;
        int highest = 1;
        int highestCnt = 1;
        int end = sizea - 1;  //end defines at what element in the array the loop will end
        int j;  //j is used to load a number that will be count
        int i;  //i is used run through the array and compare every number the the one that is being count
    
        for (j = 0; j <= end; j++) {
            number = array[j];  // load a number to count
            count = 1; // start counting at 1
    
            for (i = j+1; i <= end; i++) {
                // if we find the same number again, we increase the counter
                // then we load the last element into the current array position 
                // then we change decrement "end" by 1
                // this is like throwing out all the numbers we allready count
                // using while instead of if so it will check the last element that was moved to current position as well
                // check for i <= end so it doesnt count twice when the last element equals our number
                while (array[i] == number && i <= end) {
                    count++;
                    array[i] = array[end];
                    end--;
                }
            }
            // if the count of the number is highers the the previus highest, it's obviously our new highest count.
            if (count > highestCnt) {
                highest = number;
                highestCnt = count;
            }
    
        }
        printf("number: %i, count: %i", highest, highestCnt);
    }