我需要编写一个程序,用飓风数据加载文件中的数据(如年份,名称,受影响的状态)
数据文件如下所示:
1960 Dnna Fl,NC
1972年Agnes FL
1969年Camile MS
用户将能够选择飓风是按年份还是按名称排序。 sort函数应使年份列表和受影响的状态列表与飓风名称保持平行。允许最多30个飓风,但使用常数宏来获得此数字,以便日后轻松扩展数据库。
如果按年份排序,他们希望输出看起来像这样
年名称国家
1960 Donna FL,NC
1969年卡米尔MS
1972年Anges FL
我想我不会正确地解决这个问题。我只是无法弄清楚如何对数组进行排序并打印出来。每次我只是尝试打印数组以确保它加载了正确的数据,我只是得到一堆垃圾,或者它只是崩溃。
这是最好的代码(如果你可以称之为)
到目前为止。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define Numof_Hurricane 23
char Hurrican_data[Numof_Hurricane][3];
char temp[Numof_Hurricane][3];
int i,j;
char HowSort;
int cmp ( const void *pa, const void *pb ) {
const char (*a)[4] = pa;
const char (*b)[4] = pb;
return strcmp(*a, *b);
}
// start of program
int main()
{
FILE *Hurrican;
Hurrican = fopen("hurricane_data.txt","r"); // the data file for Hurricanes
if (Hurrican==NULL)
{
printf("ERROR: File failed to open\n");
fclose(Hurrican);
}
for(i=0; i<30; i++)
{
for(j=0; j<3; j++)
{
fscanf(Hurrican," %s", &Hurrican_data[i][j]); //loads data into array
}
}
fclose(Hurrican);
printf("How would you like to sort the data?\n"
"(by Year or Name, use Y for year and N for name)"); // ask how user wants to sort it
scanf(" %c", &HowSort);
if (HowSort == 'Y'|| HowSort == 'y') //sort by year
{
printf("\nYou chose to sort by year");
//I plan on adding a function here to sort by year
// my atempt to sort by year
qsort(Hurrican_data, 1, sizeof Hurrican_data[0], cmp );
// To print sorted data
for ( i = 0 ; i < Numof_Hurricane ; i++ )
{
for ( j = 0 ; j < 4 ; j++ )
{
printf( "%s ", Hurrican_data[i][j] );
}
printf("\n");
}
}
else
{
printf("\nYou chose to sort by name");
// I plan to put a function here to sort by Name
}
return 0;
}
答案 0 :(得分:0)
此代码中的错误:
fclose
调用错误
if (Hurrican==NULL)
{
printf("ERROR: File failed to open\n");
fclose(Hurrican); /// HERE
}
那fclose
毫无意义,是崩溃的秘诀。您刚刚确定fopen
的结果为NULL。因此,文件没有打开。因此,文件指针不是你可以关闭的东西。如果文件无法打开,则没有理由继续该程序:
if (Hurrican==NULL)
{
perror("hurricane_data.txt: ");
return EXIT_FAILURE;
}
数组大小错误。
鉴于您的数据如下所示:
1960 Dnna Fl,NC
1972 Agnes FL
1969 Camile MS
并且您的加载器循环尝试将此内容读入此内容:
#define Numof_Hurricane 23
char Hurrican_data[Numof_Hurricane][3];
使用此循环:
for(i=0; i<30; i++) // HERE: 30??? What about that 23 ??
{
for(j=0; j<3; j++)
{
// HERE: Each of these can be no longer than TWO chars wide.
fscanf(Hurrican," %s", &Hurrican_data[i][j]);
}
}
这假设文件中总共有30个项目,分配明确指出可能,但不是精确。 &#34;允许最多30次飓风......&#34; 意味着可能有30个,但也可能有一个,五个甚至无 。真的在伤口上倒盐,你在一个只有 23 元素宽的阵列核心阵列上循环到三十个(一路上溢出的缓冲区,更多在下面)。如果有三十个元素,则会在第二十四行突破您的主阵列。
此外,您的加载器外观是(a)未选中,以及(b)每次读取时缓冲区溢出的配方。考虑第一行1960
上的第一个字符串值。该字符串长度为四个个字符;五个包括终结符,但你试图将它推入一个只有三个字符宽的缓冲区。
打破排序算法
您的排序循环正在对名称的第一个字符进行排序。这是错的。
不同的方法
算法很简单:
Hurricane
,其中包含三个字段
year
- 一个简单的整数name
- 长度合理的字符缓冲区states
- 一个char缓冲区,能够用逗号分隔符保存足够数量的状态缩写。结果代码如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_DATA 30
#define MAX_NAME_LEN 64
#define MAX_STATES_LEN 151
struct Hurricane
{
int year;
char name[MAX_NAME_LEN];
char states[MAX_STATES_LEN];
};
struct Hurricane data[MAX_DATA];
void print_data(const struct Hurricane ar[], int size)
{
for (int i=0; i<size; ++i)
printf("%d %s %s\n", ar[i].year, ar[i].name, ar[i].states);
}
void sort_year(struct Hurricane ar[], int size)
{
int swapped = 1;
while (swapped && size--)
{
swapped = 0;
for (int i=0; i<size; ++i)
{
if (ar[i].year > ar[i+1].year)
{
swapped = 1;
struct Hurricane tmp = ar[i];
ar[i] = ar[i+1];
ar[i+1] = tmp;
}
}
}
}
void sort_name(struct Hurricane ar[], int size)
{
int swapped = 1;
while (swapped && size--)
{
swapped = 0;
for (int i=0; i<size; ++i)
{
if (strcmp(ar[i].name, ar[i+1].name) > 0)
{
swapped = 1;
struct Hurricane tmp = ar[i];
ar[i] = ar[i+1];
ar[i+1] = tmp;
}
}
}
}
// start of program
int main()
{
int count=0, i;
char line[256];
char HowSort;
FILE *fp = fopen("hurricane_data.txt","r"); // the data file for Hurricanes
if (fp==NULL)
{
printf("ERROR: File failed to open\n");
fclose(fp);
}
// read until we are full or no more data
for (i=0; (i < MAX_DATA && fgets(line, sizeof(line), fp)); )
{
if (sscanf(line, "%d %63s %150s", &data[i].year, data[i].name, data[i].states) == 3)
++i; // only increment if we got good data
}
// save the number of successful reads.
count = i;
// close the file
fclose(fp);
printf("How would you like to sort the data?\n"
"(by Year or Name, use Y for year and N for name)"); // ask how user wants to sort it
scanf(" %c", &HowSort);
if (HowSort == 'Y'|| HowSort == 'y')
{
printf("\nYou chose to sort by year");
sort_year(data, count);
}
else if (HowSort == 'N' || HowSort == 'n')
{
printf("\nYou chose to sort by year");
sort_name(data, count);
}
print_data(data, count);
return EXIT_SUCCESS;
}
我没有机会测试这个,但它可能非常接近你想要的。两种情况下的排序算法都是简单的冒泡排序。对于真实世界的等价,我们将创建适当的qsort
比较函数并使用标准库,特别是如果元素的数量明显大于几十个。但是,就我们的目的而言,这已足够。请参阅qsort()
here的文档和示例。
最重要的是,请注意,通过使用一个结构来保存记录而不是将其展现在一系列字符缓冲区中,您不仅可以获得正确类型的好处(例如,年份为int
),你可以获得更好的数据管理,最重要的是,很多更容易在排序例程中交换元素(结构值交换ftw)。
无论如何,这就是我认为你正在尝试做的事情。