【问题标题】:How to put values into array structs?如何将值放入数组结构中?
【发布时间】:2017-04-08 03:32:56
【问题描述】:

我正在尝试在 C 中制作帐户系统。 我正在尝试通过这种方式对结构数组进行输入。

struct account {                  // Account Structure
int id;
int money;
char *name[30];
};
account * accountarray[50];
int number;


void MakeAccount() {
int id;
int input_money;
char name[50];

printf("--Make Account--\n");
printf("Input ID : ");
scanf("%d", &id);
printf("Insert Money : ");
scanf("%d", &input_money);
printf("Your Name? : ");
scanf("%s", name);

accountarray[number++] = NULL;                // I think there's a problem in this side
accountarray[number++]->id = id;
accountarray[number++]->money = input_money;
*accountarray[number++]->name = name;
}

当我输入值时它会停止...我认为下面的 4 个代码有问题.. 有没有好办法让它变得更好?

【问题讨论】:

  • 问题不清楚
  • 更多地学习指针和数组。您有一个 struct account 类型,其中包含一个包含 30 个指向 char 的指针(不是 char 数组,是一个指向 char 的数组)作为成员的数组,以及一个包含 50 个指向 account 的指针的全局数组.在所有这一切中,只有一件事实际上有任何这些指针指向,它是一个临时的 (name)。您在每个字段分配之间重复增加 number 看起来也非常错误。
  • @WhozCraig 好的,谢谢。我想我在本节中不需要指针。解决了放置值并检查它是好的。看到其他人为此使用了指针,尝试了这种方式并没有用。我想我真的需要学习更多的指针lol
  • 确实,WhozCraig 是对的。 accountarray[number++] = NULL; 后跟accountarray[number++]->id = id;... 这个错误(空指针取消引用)应该很明显如果您正在阅读一本书。你在看书吗?
  • 你不能通过无指导的反复试验安全地学习 C;你需要一个指南(例如一本书),或者你冒着依赖诸如此类的不可移植的未定义行为的风险。未定义行为的问题是它并不总是保证会产生崩溃。事实上,在这种情况下你很幸运,因为未定义行为的定义意味着没有保证。许多与未定义行为有关的问题非常难以调试,例如竞态条件、缓冲区溢出、序列点滥用......这些也可能导致安全问题。 停止猜测,开始阅读!

标签: c pointers struct


【解决方案1】:

这是您的代码的一个版本。

  1. 编译干净
  2. 因为没有main()函数所以不能执行
  3. 它正确地执行错误检查
  4. 它正确地将错误消息输出到stderr
  5. 它正确声明了“帐户”数据数组
  6. 适当地使用空行来对代码块和活动块进行分组
  7. 它正确地使用了一个字符串函数来复制name数组
  8. 发生错误时退出程序
  9. 程序缩进一致,便于阅读
  10. 它为“神奇”数字赋予有意义的名称(并在整个代码中使用这些有意义的名称
  11. 它避免了输入缓冲区溢出的任何可能性
  12. 它包括必要的头文件和为什么要包含每个头文件的 cmets
  13. 它不会消耗用户输入的最终“换行符”序列,但是,对scanf()id 调用将消耗stdin 中剩余的字节作为“%d”输入下一个帐户时输入/转换说明符,将消耗前导white space

现在是代码

#include <stdio.h>    // printf(), scanf(), perror()
#include <stdlib.h>   // exit(), EXIT_FAILURE
#include <string.h>   // strcpy()

// eliminate 'magic' numbers
#define MAX_STR_LEN 30
#define MAX_ACCTS   50

// define the struct
struct account
{                  // Account Structure
    int id;
    int money;
    char name[ MAX_STR_LEN ];
};

// prototypes
void MakeAccount( void );

// === file global data ===
// declare MAX_ACCTS instances of the struct
struct account accountarray[ MAX_ACCTS ];
// declare a counter
int number = 0;


void MakeAccount()
{
    int id;
    int input_money;
    char name[ MAX_STR_LEN ];

    int scanfStatus;

    printf("--Make Account--\n");

    printf("Input ID : ");
    scanfStatus = scanf("%d", &id);

    if( 1 != scanfStatus )
    { // then scanf failed
        // output error message, including the OS reason for the error to 'stderr'
        perror( "scanf for account id failed" );
        exit( EXIT_FAILURE );
    }

    //implied else, scanf successful

    printf("Insert Money : ");
    scanfStatus = scanf("%d", &input_money);

    if( 1 != scanfStatus )
    { // then scanf failed
        // output error message, including the OS reason for the error to 'stderr'
        perror( "scanf for account money failed" );
        exit( EXIT_FAILURE );
    }

    printf("Your Name? : ");
    scanfStatus = scanf("%29s", name); // note MAX CHARACTERS 1 less than length of input buffer

    if( 1 != scanfStatus )
    { // then scanf failed
        // output error message, including the OS reason for the error to 'stderr'
        perror( "scanf for account name failed" );
        exit( EXIT_FAILURE );
    }

    accountarray[number].id = id;
    accountarray[number].money = input_money;
    strcpy( accountarray[number].name, name);
} // end function: MakeAccount

【讨论】:

  • 很棒的代码,完美的学到了很多东西。我应该避免使用幻数
【解决方案2】:

我认为您在这里可能不需要指针,因为您假设名称的最大大小为 30 和 50 个帐户。所以这里是我认为你可以做的修改:

 struct account {                  // Account Structure
   int id;
   int money;
   char name[30];  // an array of characters
 };
 struct account accountarray[50]; // Note: its type is "struct account"
 int number;

 void MakeAccount() {
  int id;
  int input_money;
  char name[30];

  printf("--Make Account--\n");
  printf("Input ID : ");
  scanf("%d", &id);
  printf("Insert Money : ");
  scanf("%d", &input_money);
  printf("Your Name? : ");
  scanf("%s", name);

  accountarray[number++].id = id;
  accountarray[number++].money = input_money;
  memcpy(accountarray[number++].name, name, strlen(name)); // Note I used memcpy to copy one array of characters into another
}

【讨论】:

  • 其实不是一个好的答案,scanf() 的返回值没有被检查,对name 的调用scanf() 允许用户超出输入字段,这将导致未定义的行为,缺少printf()scanf()strlen()memcpy() 所需的所有 #include 语句。使用“神奇”数字。
  • @user3629249 :-) 你错过了一些:没有为30 定义宏。没有为50 定义宏。也许我应该将unsigned 用于idmoney。对于number,绝对是unsigned。更重要的是void MakeAccount(void) 是定义没有参数的函数的正确方法......但这里有一个小问题需要考虑:OP 正在尝试学习数组和指针。 :-)
  • @Arash,我确实提到了“魔术”数字的使用(即 30 和 50)即使 OP 正在尝试学习数组和指针,我相信他不应该忽略其他项目代码。最好现在就学习,而不是养成以后很难改掉的坏习惯。
【解决方案3】:

我认为你试图让事情变得更复杂,我就是这样做的

#include <stdio.h>

struct account {                  // Account Structure
    int id;
    int money;
    char name[30];
};

int number;


int main() {
int id,x,input_money;
char name[50];
struct account accountarray[50];

printf("How many Number of accounts do you want to enter? ");
scanf("%d",&x);
printf("--Make Account--\n");
for (int i = 0; i < x; i++)
{

    printf("Input ID : ");
    scanf("%d", &accountarray[i].id);
    printf("Insert Money : ");
    scanf("%d", &accountarray[i].money);
    printf("Your Name? : ");
    scanf("%s", accountarray[i].name);
    printf("\n");
}
printf("****RECORD INSERTED****\n");
for (int i = 0; i < x; i++)
{
    printf("\nID: %d",accountarray[i].id);
    printf("\nNAME: %s",accountarray[i].name);
    printf("\nMONEY: %d",accountarray[i].money);

}

}

您可以查看https://github.com/ashim888/csit-c 以获取更多信息和代码示例

【讨论】:

  • 这是另一个很好的解决方法。谢谢!我刚刚使用strcpy 更改了name 部分
  • 我真的很喜欢......对不起我的代表点。当我得到足够的时候我会这样做:D
  • @Gomtting 不用担心 :)
  • 关于这一行:void main() {
  • 不是一个好答案,因为:使用“魔术”数字,不分隔代码块,偏离用户给出的逻辑和输出,包含几个未使用的变量,不检查帐户数量用户期望的是 scanf() 的返回值以确保操作成功。不遵循公理:每行只有一个语句,并且(最多)每条语句一个变量声明。
猜你喜欢
  • 1970-01-01
  • 2010-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-26
  • 2013-11-20
  • 2020-07-25
相关资源
最近更新 更多