C struct 字段赋值覆盖另一个字段

Posted

技术标签:

【中文标题】C struct 字段赋值覆盖另一个字段【英文标题】:C struct field assignment overwrites another field 【发布时间】:2012-08-14 23:40:09 【问题描述】:

为了好玩,我正在编写一个梦幻足球选秀程序。

我遇到了一个奇怪的问题。我为struct 字段分配了一个值,这会发生,但它也会将该值分配给struct 中的另一个字段。为混乱的调试 printf 语句道歉。

我显然不了解struct 字段分配。

代码:

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

#define TRUE 1

int QB_count = 0;
int RB_count = 0;
int WR_count = 0;
int TE_count = 0; 
int DEF_count = 0;

struct Player  
    char *name;
    char *position;
    int age;
    int bye_week;
;

int get_name (struct Player *drafted) 
    char name[20];
    fputs("Enter Player Name: ", stdout);
    fflush(stdout);
    if (fgets(name, sizeof name, stdin) != NULL)
        char *newline = strchr(name, '\n');
        if (newline != NULL)
            *newline = '\0';
        
        drafted->name = name;
        printf("You've drafted: %s\n", drafted->name);
    
    return 0;


int get_position(struct Player *drafted)
    char position[20];
    int depth;
    char *nametemp = drafted->name;
    printf("nametemp: %s\n", nametemp);
    fputs("Enter Player Position in 'QB/RB/WR/TE/DEF' format: ", stdout);
        fflush(stdout);
        if (fgets(position, sizeof position, stdin) != NULL)
                char *newline = strchr(position, '\n');
                if (newline != NULL)
                        *newline = '\0';
                
                drafted->position = position;

        if (strcmp(position, "QB") == 0)
            QB_count++;
            depth = QB_count;

         else if (strcmp(position, "RB") == 0)
                        RB_count++;
                        depth = RB_count;

                 else if (strcmp(position, "WR") == 0)
                WR_count++;
                        depth = WR_count;

                 else if (strcmp(position, "TE") == 0)
                        TE_count++;
                        depth = TE_count;

                 else if (strcmp(position, "DEF") == 0)
                        DEF_count++;
                        depth = DEF_count;

                 else 
            printf("Please re-enter position information using the format 'QB' or 'qb'\n");
            get_position(drafted);
            return 0;
        
        drafted->name = nametemp;
        printf("NAME: %s\n", drafted->name);
        printf("You've drafted %s at: %s%d\n", drafted->name, drafted->position, depth);
        
        return 0;



int get_age (struct Player *drafted)
    return 0;


int get_bye_week (struct Player *drafted)
    return 0;


int main () 
    int stop = 0;
    char text[20];
    while (TRUE)
        struct Player drafted;
        printf("Welcome to the 2012 Draft Day Program\n");
        get_name (&drafted);
        printf("NAME_MAIN: %s\n", drafted.name);
        get_position(&drafted);
        printf("You've drafted %s at: %s\n", drafted.name, drafted.position);
        get_age(&drafted);
        get_bye_week(&drafted);
        fputs("Would you like to draft another player?\n" 
            "Enter '1' for no, '0' for yes\n", stdout);
        fflush(stdout);
        if(fgets(text, sizeof text, stdin))
            int number;
            if (sscanf(text, "%d", &number) == 1)
                if (number == 1)
                    printf("Draft Ended!\n");
                    break;
                       
            
        
    
    return 0;

结果输出是:

Welcome to the 2012 Draft Day Program
Enter Player Name: Aaron Rodgers
You've drafted: Aaron Rodgers
NAME_MAIN: Aaron Rodgers
nametemp: Aaron Rodgers
Enter Player Position in 'QB/RB/WR/TE/DEF' format: QB
NAME: QB
You've drafted QB at: QB1
You've drafted QB at: QB
Would you like to draft another player?
Enter '1' for no, '0' for yes
1
Draft Ended!

为什么drafted.name会变成“QB”?

【问题讨论】:

【参考方案1】:

在您的get_name 函数中,您将分配给struct Playername 字段一个堆栈变量name

在这一行:

drafted->name = name;

name 是在函数中声明的,因此它的范围仅限于 该函数。一旦get_name 返回,变量就会超出范围,并尝试使用该内存调用未定义的行为。

您需要使用mallocdrafted-&gt;name 分配空间,而不是使用简单的赋值,并使用strncpy 复制名称。如果strdup 可用,您可以使用它来分配空间并一步完成复制。或者,您可以在读取名称之前为 drafted-&gt;name 分配空间,并使用它来代替 name 变量。

作为最后一个选项,如果您假设名称的最大长度 - 您当前的代码允许名称的字符串长度不超过 19 - 您可以简单地为每个 struct Player 声明一个该大小的数组:

struct Player
 
    char name[NAME_MAXLEN];

get_position 函数中的 position 字段存在相同的问题。

【讨论】:

一般来说,strncpy 不是你想要的(它的用处非常有限)。如果要复制字符串,最好使用strlen + malloc + memcpy

以上是关于C struct 字段赋值覆盖另一个字段的主要内容,如果未能解决你的问题,请参考以下文章

mysql 查询结果把一个字段的值赋值给另一个字段的键值

BigQuery:如何从重复记录中仅提取某些字段作为另一个重复字段

SQL同一个表的某字段值相加赋值给另一个字段

sql将查询结果的某个字段赋值给另一个字段

结构和类

navicat premium如何将一个字段批量覆盖到另一个字段