C中的分段错误主要但不是我的功能

时间:2013-12-06 16:25:56

标签: c

我正在尝试创建一个程序,该程序将检查用户输入文件的名称,并查看文件中有多少次出现。但是在我的getrawdata函数中,我一直遇到分段错误。

以下是代码:

struct NameRecord{ // Holds all the name information
    int year;
    char name [31];
    int frequency;
};


void allCaps(char s[]){ //Capitalizes all of the characters of s
    int i=0;
    while (s[i])
        {
            s[i] = toupper(s[i]);
            i++;
        }
    printf("The name entered is now in all caps! %s", s);
}

int getRawData1(FILE* male, struct NameRecord records[], int currSize){
    int readResult;
    printf("The current size is %d", currSize);
    readResult=fscanf(&*male, "%d", &records[currSize].year);
}
//Main
int main (){
    char name [31];
    FILE *male;
    FILE *female;
    int size = 0;
    //Opening files
    male = fopen("malebabynames.csv", "r"); //Dont leave in home directory 
    female = fopen("femalebabynames.csv", "r");
    struct NameRecord records[160000];

    if ( male==NULL){
        printf ("Error: the data file does not exist");
    }
    if ( female==NULL){
        printf ("Error: the data file does not exist");
    }

    size = getRawData1(male, records, size);
    //Output   
    printf("Please enter a name: ");
    scanf("%s", name);
    allCaps(name);
}

修改后的代码 - 仍然崩溃

Codepad的原始版本;这个版本SSCCE'd。

#include <stdio.h>

struct NameRecord
{
    int year;
    char name[31];
    int frequency;
};
struct NameRecord records[160000];

void allCaps(char s[])
{
    int i = 0;
    while (s[i])
    {
        s[i] = toupper(s[i]);
        i++;
    }
    printf("The name entered is now in all caps! %s", s);
}

int getRawData1(FILE *male, struct NameRecord records[], int currSize)
{
    int readResult;
    printf("The current size is %d", currSize);
    readResult = fscanf(male, "%d,%[^,],%d\n", &records[currSize].year,
                        records[currSize].name, records[currSize].frequency);

    while (readResult == 3)
    {
        currSize++;
        readResult = fscanf(male, "%d,%[^,],%d\n", &records[currSize].year,
                            records[currSize].name, &records[currSize].frequency);
    }
    printf("The size of the array is %d", currSize);
    return currSize;
}

int main()
{
    char name[31];
    FILE *male;
    FILE *female;
    int size = 0;

    male = fopen("malebabynames.csv", "r");
    female = fopen("femalebabynames.csv", "r");
    int i = 0;
    int readResult;
    if (male == NULL)
    {
        printf("Error: the data file does not exist");
    }
    if (female == NULL)
    {
        printf("Error: the data file does not exist");
    }
    getRawData1(male, records, size);

    printf("Welcome to the Name Popularity Checker \n====================================== \n");
    printf("Please enter a name: ");
    scanf("%s", name);
    allCaps(name);
}

2 个答案:

答案 0 :(得分:1)

由于这条线路,我在启动时实际上在VS2012中崩溃了:

struct NameRecord records[160000];

我认为您可能超出了可用的堆栈空间。至少这对我来说!这个数字需要这么高吗?你可以根据你从文件中读到的内容动态分配吗?

根据Barmar的建议,你可以这样做来解决它(如果你真的需要160k记录的静态分配):

struct NameRecord{ // Holds all the name information
  int year;
  char name [31];
  int frequency;
};

NameRecord records[160000];

换句话说,将它设为全局变量而不是堆栈上的变量。

更新:此外,使用Jonathan Leffler的建议,您可以确保正确打开文件。您目前只是在文件未正确打开时打印消息,但如果是这种情况则不应继续执行。

if (male == NULL)
{
    printf("Error: the data file does not exist");
    return EXIT_FAILURE;
}
if (female == NULL)
{
    printf("Error: the data file does not exist");
    return EXIT_FAILURE;
}

答案 1 :(得分:1)

注意编译器警告。如果您没有收到编译器警告,请将它们打开;如果你仍然没有得到编译器警告,那就得到一个更好的编译器。

$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition x.c -o x
x.c: In function ‘getRawData1’:
x.c:30:25: warning: format ‘%d’ expects argument of type ‘int *’, but argument 5 has type ‘int’ [-Wformat=]
                         records[currSize].name, records[currSize].frequency);
                         ^
x.c:30:25: warning: format ‘%d’ expects argument of type ‘int *’, but argument 5 has type ‘int’ [-Wformat=]
$

您错过了&

                         records[currSize].name, &records[currSize].frequency);

(我已经添加了#include <ctype.h>并将static放在函数前面以平息编译器发出的其他警告。)


您还应该重新设计getRawData1()

的界面
int getRawData1(FILE *fp, struct NameRecord records[], int maxSize)
{
    int readResult;
    printf("The maximum size is %d", maxSize);
    int currSize = 0;

    while (currSize < maxSize &&
           (readResult = fscanf(fp, "%d,%[^,],%d\n", &records[currSize].year,
                                records[currSize].name, &records[currSize].frequency)) == 3)
        currSize++;

    printf("The amount of data in the array is %d", currSize);
    return currSize;
}

调用:

num_male_names = getRawData1(male, records, 160000);

如果文件中有超过160,000条记录,这可以防止缓冲区溢出。