我是C的初学者并使用结构 . 我正在尝试创建一个对日期列表进行排序的程序 . 用户首先输入日期数,然后输入日期本身,即月,日和年 . 然后使用qsort我想按时间顺序对它进行排序(首先是按年然后是按月计算) . 我试图先对年份进行排序,但我只是将输出设为“0” .
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char* month;
int day;
int year;
} date;
int sort(const void* a, const void* b)
{
date* date1 = (date*)a;
date* date2 = (date*)b;
if (date2->year != date1->year) {
int year2 = date2->year;
int year1 = date2->year;
if (year1 < 14) {
year1 = year1 + 100;
}
if (year2 < 14) {
year2 = year2 + 100;
}
int yearcompare = year2 - year1;
return -yearcompare;
}
}
output(date* ar, int i, int n)
{
for (i = 0; i < n; i++) {
//printf("Enter the date (month day year) i n the following format: text number number");
// printf("%s ", ar[i].month);
//printf("%d ", ar[i].day);
printf("%d\n", ar[i].year);
}
}
int main()
{
int n;
int i;
int MIN_SIZE = 0;
int MAX_SIZE = 1000;
while (1) {
printf("Enter number of dates you want to enter (between 1 and 10000):\n");
scanf("%d", &n);
if (n < MIN_SIZE) {
printf("You have entered a number lower than 0\n");
}
if (n > MAX_SIZE) {
printf("You have entered a number higher than 1000\n");
}
else {
break;
}
}
date* ar = malloc(sizeof(int) * n);
//ALLOCATE MEMORY
printf("Enter the date (month day year) in the following format: text, number(between 1 and 31), number(between 00 and 12): \n");
for (i = 0; i < n; i++) {
scanf("%s", ar[i].month);
scanf("%d", &ar[i].day);
scanf("%d", &ar[i].year);
}
qsort(ar, n, sizeof(date), sort);
output(ar, i, n);
}
1 回答
看起来好像你需要相当多的帮助把拼图的所有部分组合在一起 . 首先,在
date
的date
中,包括char *month
. 当你分配ar
时,这是一个未初始化的指针,这意味着你需要为ar[i].month
单独分配 . 你可以自由地做到这一点,(在这种情况下你可以有效地使用strdup
),但为什么呢?如果您正在使用月份的字符串输入,则最大长度为10个字符(September
nul-byte
) . 只需使用静态声明的month
或10
或更多字符,并避免在month
上进行动态分配 .例如,您可以使用单独的
#define
指令声明有用的常量以用于您的代码,或者您可以使用全局enum
来完成相同的操作,例如:您将遇到的下一次火车残骸是在
scanf
中混合字符和数字输入,每次调用时都不会清空 input buffer (例如stdin
) . 这意味着如果用户为'n'
输入了有效小数以外的其他内容(例如,如果他意外命中'q'
而不是'1'
),则"q\n"
将保留在输入缓冲区中,该缓冲区将作为下面ar[0].month
的输入 . 为防止这种情况发生,您需要手动清空输入缓冲区(或使用fgets
后跟sscanf
来解析用户输入 - 使用scanf
进行用户输入时存在许多缺陷) .尽管如此,你可以很容易地清空
stdin
. 您可以使用_197349进行内联或创建一个短函数,如果您将反复调用它以减少打字,例如:当你接受输入时(无论是
scanf
系列函数还是fgets
(或任何其他方法),总是 validate 用户输入 . 你只知道猫可能正在踩键盘 . 另外,总是检查EOF
表示用户通过Ctrl d或Ctrl z取消输入(在windoze上) . 例如:与使用
fgets
和sscanf
进行比较,以读取/解析month
,day
,year
输入 . 你可以做一些简单的事情:没有必要将
int i
作为参数传递给函数output
,只需在本地声明它,例如:接下来,当您的
sort
函数可以工作时,您可以按年度压缩排序,同时通过使用不等式来避免潜在的溢出:最后,如果你分配内存,你有责任保留一个指向块起始的指针,然后在不再需要时保留内存 . 虽然它将在
exit
上释放,但要养成跟踪和释放所分配的所有内存的习惯 . 当你从事更复杂的项目时,良好的习惯会很好地为你服务 .如果用户只是点击Enter而不是输入日期,则完全放入并添加退出提示,您可以执行以下操作:
注意:有很多很多方法可以处理代码的每个部分 . 如果你看一下大部分行的位置,它们会在 validating 输入中使用 . 这只是验证的最低限度 . 理想情况下,将每个
day
和year
的值与最大/最小值进行比较,然后将每个month
与查找(或散列)表进行比较,以验证每个月是否为有效月份(您还可以使用日期/时间函数,但是留待另一个问题)Example Use/Output
仔细看看,确保您了解正在发生的事情的每个部分,并询问您是否还有其他问题 .