中止陷阱6和文本文件输出

时间:2014-12-12 00:29:21

标签: c memory-management fopen abort

此代码用于输入一个输入文本文件" playlist.txt",它由一些歌曲名称组成,每个歌曲名称各自独立。然后它将播放列表混洗7次,并将洗牌后的列表输出到名为" shuffle [星期几]"的文件中。

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>

void open(char *playlist, int *size);
void shuffle(char *playlist, int size, char *day);

int main()
{
    char playlist[5000];
    int size = 0;
    open(playlist, &size);
    time_t t;
    srand((unsigned) time(&t));
    shuffle(playlist, size, "Monday");
    shuffle(playlist, size, "Tuesday");
    shuffle(playlist, size, "Wednesday");
    shuffle(playlist, size, "Thursday");
    shuffle(playlist, size, "Friday");
    shuffle(playlist, size, "Saturday");
    shuffle(playlist, size, "Sunday");
}

void open(char *playlist, int *size)
{
    FILE *in = fopen("playlist.txt", "r");
    int i = 0;
    while(fgets(&playlist[i], 30, in) != NULL)
    {
        i++;
        (*size)++;
    }
    fclose(in);
}

void shuffle(char *playlist, int size, char *day)
{
    printf("started %s shuffle\n", day);
    int done = 0;
    int n, i, j;
    int tempsize = size;
    char templist[5000];
    for(i = 0; i < size; i++)
    {
        strcpy(&templist[i], &playlist[i]);
    }
    char newlist [5000];
    for(i = 0; i < size; i++)
    {
        n = rand()%tempsize;
        strcpy(&newlist[i], &templist[n]);
        for(j = n; j < tempsize; j++)
        {
            strcpy(&templist[j], &templist[j+1]);
        }
        tempsize--;
    }
    char listname[20] = "shuffle";
    strcat(listname, day);
    strcat(listname, ".txt");
    FILE *out = fopen(listname, "w");
    for(i = 0; i < size; i++)
    {
        fprintf(out, "%s\n", &newlist[i]);
    }
    fclose(out);
    printf("Finished %s shuffle\n", day);
}

当我运行它时,输出表示周一和周二都开始并完成。然后说星期三开始了,但后来我得到了Abort陷阱6。 只创建了星期一和星期二的输出文件,但它们都包含看似随机的字符,它们之间有随机数字的换行符。

我做错了什么? 如何修复中止陷阱?

1 个答案:

答案 0 :(得分:0)

除了user3629249识别的错误(由于星期三因文件名中的一个字节溢出)之外,您用于播放列表和临时列表的数据类型也不正确。如果你想要一个5000首歌曲的播放列表,每个歌曲由一串文字标识,你需要

char *playlist[5000];  /* an 5000-element array of char *s.  */
char *templist[5000];  /* ditto */

如你所知,&amp; playlist [i]是5000个元素字符数组的第i个字符,而不是5000个元素char * s的第i个字符串指针。在当前的实现中,您在迭代时逐字节地继续踩数据。如果更改为char *数组,则将按指针步进指针。

但是!请注意,您声明了一个固定大小的数组(5000个元素),但您无法确认您是否尝试编写超过5000个元素,这也可能导致Abort(信号6)或Segfault(信号9)。