结构和malloc代码得到奇怪的输出

时间:2013-10-04 01:04:40

标签: c struct malloc switch-statement

我又来了,并取得了进展......我要感谢所有评论我最后一个问题的人,这非常有帮助。到目前为止,我已经编译了这个,但有一些奇怪的错误,我无法解决。

void addRecord(){//carries users input data

numRecs++;//increments numRecs by 1 

struct record library; //this will hold info for user input

printf ("Please enter your first name:\n");
fgets(library.fName, sizeof(library.fName), stdin);
printf ("Please enter your last name:\n");
fgets(library.lName, sizeof(library.lName), stdin);
printf ("Please enter your hometown:\n");
fgets(library.hometown, sizeof(library.hometown), stdin);


printf("You entered %s for your first name.\n", library.fName);
printf("You entered %s for your last name.\n", library.lName);
printf("You entered %s for your hometown.\n", library.hometown);


struct record *myNewRecord;//creates a new struct pointer to store   all the old data and new data


myNewRecord = malloc(numRecs * sizeof(struct record));      //allocates space to fit all old data plus the new struct data
if (myNewRecord == NULL)
{
fprintf(stderr,"Out of memory\n");
}

*myNewRecord = library;

fprintf(stderr, "You made it here!!\n");

这些是我从终端获得的结果。看起来源代码中的语法都是正确的,但问题是它出于某种原因跳过了名字fgets。此外,当它打印出来时,它会以某种方式执行返回。你们能看到最新情况吗???附:当我消除开关盒并且主体中只有addrecord()时,它不会这样做。

ubuntu@ubuntu:~$ 
ubuntu@ubuntu:~$ gcc lab222.c -o lab222
ubuntu@ubuntu:~$ ./lab222

Please select from the following:
 1. Print all records.
 2. Print number of records.
 3. Print size of database.
 4. Add record.
 5. Delete record.
 6. Print number of accesses to database.
 7. Exit.
Enter a number 1-7:4
Please enter your first name:
Please enter your last name:
Don
Please enter your hometown:
Mega
You entered 
 for your first name.
You entered Don
 for your last name.
You entered Mega
 for your hometown.
You made it here!!

2 个答案:

答案 0 :(得分:2)

变化:

scanf("%d",&sel);
if (scanf("%d", &sel) == 0) {
    fprintf(stderr, "Error, not a valid input. Must be a number from 1 to 7.\n");
    scanf("%s", &c);
    continue;
}

为:

char reponse[MAX];
fgets(response, sizeof response, stdin);
int result = sscanf(response, "%d", &sel);
if (result != 1) {
    fprintf(stderr, "Error, not a valid input. Must be a number from 1 to 7.\n");
    continue;
}

使用fgets()后跟sscanf()解决了在单独使用scanf()时无法读取换行符的问题。您还在scanf()中再次呼叫if,因此它正在读取输入两次。

答案 1 :(得分:1)

一些观察,

  • 保存重新分配数组并复制每条记录的先前值
  • 分配指向新记录的指针数组,并在添加记录时填充该数组
  • 您可以重新分配指针数组,比数据记录便宜得多
  • 将菜单显示和菜单选择确定移至单独的功能
  • 你可能会添加一个链表(head,mover?),所以指针数组很接近
  • 使用fgets读取输入,它比scanf更少抽搐
  • 您仍然可以使用sscanf提取菜单选项(解决了问题)

以下是修订记录存储

#include<stdio.h>
#include<stdlib.h> //needed for malloc, free
#include<string.h> // needed for the memcpy
#define MAX 100

struct record
{
    char fName[MAX];
    char lName[MAX];
    char hometown[MAX];
};             //structure template/declaration
struct record* records[500]; //allow room for 500 (for now)
int numRecords=0;  //stores number of records, used for several tasks

//prototypes
int addRecord();

这里有显示菜单和读取输入(视图)的功能

//********MENU***********
int menushow(FILE* fh)
{
    printf("\nPlease select from the following:\n");
    printf(" 1. Print all records.\n");
    printf(" 2. Print number of records.\n");
    printf(" 3. Print size of database.\n");
    printf(" 4. Add record.\n");
    printf(" 5. Delete record.\n");
    printf(" 6. Print number of accesses to database.\n");
    printf(" 7. Exit.\n");
    printf("Enter a number 1-7:");
    return 0;
}
int menudo(char* line)
{
    int sel;
    int choice;
    if( sscanf(line,"%d",&sel) < 1 ) {
        fprintf(stderr, "Error, not a valid input. Must be a number from 1 to 7.\n");
        return 0;
    }
    switch(choice = atoi(line))
    {

    case 1:

        break;

    case 2:

        break;

    case 3:

        break;

    case 4:
        if( addRecord() < 0 )    //This creates a new record based of input into struct library.
            fprintf(stderr,"addRecord failure\n");
        break;
    case 5:

        break;

    case 6:

        break;

    case 7:
        exit(0);
        break;

    default:
        printf("\nError, not valid input. Please enter a  number from 1 to 7.\n\n");
        break;
    }
    return choice;
}

以下是提取到函数的菜单处理的主要内容,

#define EXITCHOICE 7
int main(void)
{
    char line[MAX+1];
    int action=0;
    while (action<EXITCHOICE)
    {
        menushow(stdout);
        if( !fgets(line,sizeof(line),stdin) ) { break; }
        //printf("entered: %s\n",line);
        if( (action=menudo(line)) < 0 ) break;
    }
    return 0;
}

这里是更简单的addrecord,

//** Beginning of addRecord**
//returns -1 on failure
int
addRecord()
{//carries users input data
    struct record library; //this will hold info for user input
    struct record *myNewRecord; //creates a new struct pointer to store   all the old data and new data

    printf ("Please enter your first name:\n");
    if(!fgets(library.fName, sizeof(library.fName), stdin)) return -1;
    printf ("Please enter your last name:\n");
    if(!fgets(library.lName, sizeof(library.lName), stdin)) return -1;
    printf ("Please enter your hometown:\n");
    if(!fgets(library.hometown, sizeof(library.hometown), stdin)) return -1;

    printf("You entered %s for your first name.\n", library.fName);
    printf("You entered %s for your last name.\n", library.lName);
    printf("You entered %s for your hometown.\n", library.hometown);

    records[numRecords] = (struct record*)malloc(sizeof(struct record));      //allocates space to fit all old data plus the new struct data
    if (records[numRecords] == NULL)
    {
        fprintf(stderr,"error: Out of memory\n");
        return -1;
    }
    memcpy(records[numRecords],&library,sizeof(struct record));
    numRecords++;//increments numRecords by 1 
    fprintf(stderr, "[%d] records!!\n",numRecords);
    return(numRecords);
}