【问题标题】:Problems with setting a custom date in c在 c 中设置自定义日期的问题
【发布时间】:2015-04-26 20:40:51
【问题描述】:

我需要用户输入一个日期,并且我需要能够在以后比较日期的年份,我认为这很简单,但我现在收到错误 表达式必须是可修改的值 em>,我尝试用谷歌搜索错误,但找不到解决问题的方法,下面是导致错误的代码:

我要存储日期的结构

struct node{

int data;
char name[20];
char address[20];
char depart[20];
int day,mounth,year;
char doj[15];
int salary;
char email[30];
struct node *next;

};

我得到错误的函数:

void addToStart (struct node** head)
{
    struct node *newNode;
    newNode = (struct node*)malloc(sizeof(struct node));
    printf("\nEnter data for this node:\n");
    scanf("%d", &newNode->data);
    printf("\nEnter address:\n");
    scanf("%s", &newNode->address);
    printf("\nEnter department:\n");
    scanf("%s", &newNode->depart);
    printf("\nEnter Data Of Join(dd/mm/yyyy):\n");
    scanf("%d %d %d", &newNode->day, &newNode->mounth, &newNode->year);
    newNode->doj = validDate(newNode->day, newNode->mounth, newNode->year);
    printf("\nEnter Salary:\n");
    scanf("%d", &newNode->salary);
    printf("\nEnter email:\n");
    scanf("%s", &newNode->email);

    newNode->next = NULL;
    if (*head==NULL)
    {
        *head = newNode;
    }
    else
    {
         newNode->next = *head;
        *head = newNode;

    }
    printf("%u,%u",&head,&newNode);
   // *first = newNode; // transfer the address of newNode' to 'head'
}

我用来创建日期的方法:

char * validDate(int dd, int mm, int yy)
{
 struct tm t;
 struct tm *info;
 time_t rawtime;
 info = localtime(&rawtime);
 char buffer[80];

 info->tm_mday   = dd;
 info->tm_mon    = mm;
 info->tm_year   = yy;

 strftime(buffer,80,"%x", info);
 return buffer;
}

【问题讨论】:

  • 请发布更多代码来说明newNode 的声明方式。
  • validDate(int dd, int mm, int yy) 中,您声明了一个指针struct tm *t;,但在您尝试分配值之前它没有指向任何东西。
  • 第三,validDate返回的buffer是一个局部变量,在函数返回时被销毁。请声明为static char buffer[80];
  • 我已经更新了代码并更改了 struct tm *t 部分,知道有什么问题吗?我从来没有尝试过这样使用日期,所以我有点困惑
  • 在 C 中,不要从 malloc()(和函数族)转换返回值,始终检查(!=NULL)返回值以确保操作成功

标签: c date pointers time linked-list


【解决方案1】:

我可以在您的代码中看到一些错误:

  • scanf("%s", &newNode->address); : newNode->address 是一个字符数组,它衰减 为一个指针 => 你不能在此处添加&。恕我直言,这是您错误的原因,因为数组不是可修改的值。由于它的大小为20,因此您最好限制读取以避免可能的溢出(以及相关的未定义行为)。所以该行应该是:

    scanf("%19s", newNode->address);
    

    您应该对结构中的所有 char 数组做同样的事情。

  • printf("\nEnter Data Of Join(dd/mm/yyyy):\n"); scanf("%d %d %d", &newNode->day, &newNode->mounth, &newNode->year);

    您要求格式为dd/mm/yyyy 的值,但不要将/ 设置为读取格式。而且您无法控制 scanf 的返回值:如果出现问题,您不会在 struct 成员中加载正确的值,但不会收到警告。最后这句话对你所有的scanf 来说都是通用的,但在这里你有格式错误,返回值的控制会警告你。假设 cr 是一个 int 变量,该行应该是:

    cr = scanf("%d/%d/%d", &newNode->day, &newNode->mounth, &newNode->year);
    if (cr != 3) {
        // wrong input ...
    }
    
  • validDate 中返回一个自动数组 (char buffer[80];)。永远不要在 C 中这样做:您只能返回静态数组或动态分配的数组(使用 malloc)。因为自动数组是在堆栈上分配的,并且会在函数返回后立即释放,给您留下一个悬空指针。

  • validDate 中,您在未初始化的值上调用 localtime。你不使用返回值,但你甚至不应该调用localtime而直接使用t
  • validDate 中,您使用读取的月份初始化tm_mon 成员。错了:tm_mon 从 0 到 11 不等。你应该有 info->tm_mon = mm - 1;
  • 你写newNode->doj = validDate(newNode->day, newNode->mounth, newNode->year);,而dojchar[15]。你不能这样做:正如我已经说过的,数组不是可修改的值。您可以使用 strncpy 复制字符串:

    strncpy(newNode->doj, validDate(newNode->day, newNode->mounth, newNode->year), 15);
    

    或将doj 设为指针:

    struct node{
    ...
    char *doj;
    ...
    };
    

总结:

  • 数组不可修改
  • 在 scanf 字符数组中不应使用&
  • 数组不是指针(如果它们衰减到)
  • 总是测试scanf返回值
  • 注意struct tmtm_mon 属性,从0 到11 变化

【讨论】:

    【解决方案2】:

    除了Serge Ballesta 在他的answer 中提到的问题,我明白了:

    printf("\nEnter Data Of Join(dd/mm/yyyy):\n");
    scanf("%d %d %d", &newNode->day, &newNode->mounth, &newNode->year);
    

    您要求用斜线分隔日期,但格式只接受空格。您的用户会感到困惑!也许你需要类似的东西:

    if (scanf("%d%*[-/. ]%d%*[-/. ]%d", &newNode->day, &newNode->mounth, &newNode->year) != 3)
        …report error entering date and recover somehow…
    

    这允许任何空白、/-. 作为日期组件之间的分隔符。接受替代标点符号(例如 2015-04-15)但拒绝混合标点符号(例如 2015-04/15)并不容易。困难的方法是读取这两个标点字符,而不是用* 抑制分配,然后在读取成功后比较它们(但是您有5个项目被扫描)。

    (顺便说一下,月份的拼写通常不带“u”,但你是一致的,所以它在形式上并不重要。)

    那么你就有了代码:

    char *validDate(int dd, int mm, int yy)
    {
        struct tm t;
        struct tm *info;
        time_t rawtime;
        info = localtime(&rawtime);
        char buffer[80];
    
        info->tm_mday   = dd;
        info->tm_mon    = mm;
        info->tm_year   = yy;
    
        strftime(buffer, 80, "%x", info);
        return buffer;
    }
    

    问题:

    1. 您需要先初始化rawtime,然后再使用localtime()进行分析。

    2. tm_montm_yearstruct tm 中的编码是奇数:

      • tm_mon 是 0 代表 1 月到 11 代表 12 月。
      • tm_year 是当前年份减去 1900。

      你需要在你的作业中补偿这些:

    3. 您正在返回一个指向局部变量的指针。

    4. 你根本不使用t

    可能的修复:

    char *validDate(int dd, int mm, int yy, char *buffer, size_t buflen)
    {
        time_t rawtime = time(0);
        struct tm *info = localtime(&rawtime);
    
        info->tm_mday   = dd;
        info->tm_mon    = mm - 1;
        info->tm_year   = yy - 1900;
    
        strftime(buffer, buflen, "%x", info);
        return buffer;
    }
    

    有了这个,你将缓冲区及其大小传递给函数;你会得到一个指向你传入的缓冲区的指针。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-14
      • 2011-05-15
      • 1970-01-01
      • 2023-04-05
      相关资源
      最近更新 更多