【发布时间】:2014-12-12 00:29:20
【问题描述】:
此代码用于获取输入文本文件“playlist.txt”,该文件由若干歌曲名称组成,每个歌曲名称各占一行。然后它将播放列表随机播放 7 次,并将随机播放的列表输出到名为“shuffle[day of week]”的文件中。
#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);
}
当我运行它时,输出显示周一和周二开始和结束。然后它说星期三开始,但后来我得到了中止陷阱 6。 只创建了星期一和星期二的输出文件,但它们都包含看似随机的字符,它们之间有随机数量的换行符。
我做错了什么? 如何修复中止陷阱?
【问题讨论】:
-
首先,您应该始终检查来自
fopen的返回值。如果文件无法打开,它将返回 NULL。其次,您应该使用调试器单步执行while(fgets...循环,同时观察playlist数组发生的情况。这应该使问题显而易见(或至少其中一个问题)。 -
关于这一行: void open(char *playlist, int *size); 'open' 是库函数名称。并且代码执行了一个#include
,它具有open() 的原型。所以编译器应该给出一个关于函数签名不匹配的警告,而链接器可能已经给出了一个关于同一个编译对象中的多个同名函数的警告。 -
文件名;: shuffle + wednesday + .txt + null byte 是21个字节,只分配了20个字节,所以文件名缓冲区溢出。导致未定义的行为和可能的段错误事件
-
作为播放列表的(字符)列表被随机数分割,这些限制是列表 1 和 0 的总长度。这导致字符串随机分割播放列表名称,包括中间的播放列表名称。可能不是你想要的。
标签: c memory-management fopen abort