动态内存分配的结构,但它的int或double成员。

时间:2022-09-06 15:32:41

I will be very thankful for looking at my code and telling me whether if I create a structure for which I am dynamically allocating memory, should I dynamically allocate memory also for the structure's elements that are int or double?

我将非常感谢查看我的代码,并告诉我,如果我创建了一个动态分配内存的结构,我是否应该动态地分配内存,以使结构的元素为int或double?

As it can be seen in the example below, I use malloc only for those elements of the structure which size can change, namely strings. I tried to use malloc for int or double variables (elements of the structure), but everything worked fine until I tried to use the function printf on them.

在下面的例子中可以看到,我使用malloc只是为了那些大小可以改变的结构的元素,即字符串。我尝试使用malloc作为int或double变量(结构的元素),但是一切都很好,直到我尝试使用函数printf。

It refused to work because printf("%d", [structure]->[int element]) was not correct.

它拒绝工作,因为printf(“%d”,[结构]->[int元素])是不正确的。

So I changed the code and int and double structure members are processed with the malloc and realloc functions. Is this approach correct?

因此,我修改了代码,int和double结构成员使用malloc和realloc函数处理。这种方法是正确的吗?

Would it be expected and even possible to use malloc and realloc for int or double structure members/elements? How to use printf on them later on?

是否可以使用malloc和realloc作为int或double结构成员/元素?以后如何使用printf ?

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define LICZBA 2
#define SIZE 256

typedef struct ksiazka{
   char * imie;
   char * nazwisko;
   char * tytul;
   int numerkat;
   double cena;
}rekord;

rekord * rekordnew(){
   rekord *r;
   r=malloc(sizeof(rekord));
   r->imie=NULL;
   r->nazwisko=NULL;
   r->tytul=NULL;
   r->numerkat=0;
   r->cena=0;
   return r;
}

void rekordfree(rekord *r){
   if (r->imie) free (r->imie);
   if (r->nazwisko) free (r-> nazwisko);
   if (r-> tytul) free (r-> tytul);
   //if (r-> numerkat) free (r->numerkat);
   //if (r-> cena) free (r-> cena); 
   free (r);
}

void wpiszimie(rekord *pr, char im[SIZE]){
   (*pr).imie=realloc(pr->imie, strlen(im)+1);
   strcpy(pr->imie, im);
}

void wpisznazwisko(rekord *pr, char nazw[SIZE]){
   pr->nazwisko=realloc(pr->nazwisko, strlen(nazw)+1);
   strcpy(pr->nazwisko, nazw);
}

void wpisztytul(rekord *pr, char tyt[SIZE]){
   pr->tytul=realloc(pr->tytul, strlen(tyt)+1);
   strcpy(pr->tytul, tyt);
}

void wpisznumerkat(rekord *pr, int numer){
 //  pr->numerkat=realloc(pr->numerkat, sizeof(int));
   pr->numerkat=numer;
}

void wpiszcena(rekord *pr, double cen){
 //  pr->cena=realloc(pr->cena,sizeof(double));
   pr->cena=cen;
}


int main(){
  rekord *r[LICZBA];
  char bufor[SIZE];
  int i, number;
  double number2;

  for(i=0;i<LICZBA;i++){
     r[i]=rekordnew();
  }

  for(i=0;i<LICZBA;i++){
    printf("Podaj tytuł książki");
    scanf("%s", bufor);
    wpisztytul(r[i],bufor);
    printf("Podaj imię autora książki");
    if (scanf("%s", bufor)==1)wpiszimie(r[i],bufor);
    printf("Podaj nazwisko autora książki");
    if (scanf("%s", bufor)==1)wpisznazwisko(r[i],bufor);
    printf("Podaj numer katalogowy książki");
    if (scanf("%d", &number)==1)wpisznumerkat(r[i],number);
    printf("Podaj cenę książki");
    if (scanf("%lf", &number2)==1)wpiszcena(r[i],number2);
    }

    for(i=0;i<LICZBA;i++){
    printf("Tytuł książki");
    printf("%s", r[i]->tytul);
    printf("Imię autora książki");
    printf("%s", r[i]->imie);
    printf("Nazwisko autora książki");
    printf("%s", r[i]->nazwisko);
    printf("Numer katalogowy książki");
    printf("%d", r[i]->numerkat);
    printf("Cena książki");
    printf("%lf", r[i]->cena);

  } 
 return 0;
}

1 个解决方案

#1


3  

I cannot see any severe errors in your code though reasoning about it would be easier for me if you had written it in English.

我看不出你的代码有什么严重的错误,不过如果你用英语写出来的话,对我来说会更容易一些。

As you do malloc(sizeof(rekord)) you allocate memory to hold all members of a rekord. That is three char * pointers, an int and a double. You can write to those members immediately, no further allocation is needed. Of course, writing to a char * member is not really useful unless you are assigning it a pointer to some char buffer which you'd in turn obtain via malloc. For the int and double this is neither needed nor possible. So your code is correct here.

当您使用malloc(sizeof(rekord))时,您分配内存来容纳所有的rekord成员。这是三个char *指针,一个int数和一个double。您可以立即给这些成员写信,不需要进一步的分配。当然,对于char *成员的写入并不是很有用,除非您将它指定为一个指向某个char缓冲区的指针,而这是通过malloc获得的。对于int和double,这既不需要也不可能。所以这里的代码是正确的。

A few minor remarks, though:

不过有几句话:

  • You should check the return value of malloc. If it fails, it will return NULL. You should check for this (rare) event and handle the error if it happens. Usually, terminating the program will be an appropriate action.
  • 您应该检查malloc的返回值。如果失败,它将返回NULL。您应该检查这个(罕见的)事件并处理它发生的错误。通常,终止程序将是一个适当的动作。
  • You forgot to call rekordfree at the end.
  • 你最后忘了给rekordfree打电话。
  • Using non-ASCII characters in your program source code may or may not work. It should be avoided in portable programs.
  • 在程序源代码中使用非ascii字符可能有用,也可能不起作用。在便携式程序中应该避免使用它。
  • Your use of scanf for reading in the strings is a potential security hole as it might overrun the input buffer. Since you are going to store the string in a malloc()ed buffer anyway, I suggest you use getline as a convenient and safe alternative.
  • 在字符串中使用scanf是一个潜在的安全漏洞,因为它可能会超出输入缓冲区。既然您要将字符串存储在malloc()ed缓冲区中,我建议您使用getline作为方便和安全的替代方法。
  • Consider adding more whitespace to your output (eg newlines via \n). I guess that even if I understood the language, the output wouldn't be very easy to read as it's all on one line. Printing a space or a tab (\t) at the end of the input prompts might also help improve the user experience.
  • 考虑在输出中添加更多的空白(如通过\n)。我想,即使我理解了语言,输出也不会很容易读,因为它都在一行上。在输入提示符的末尾打印一个空格或一个制表符(\t)也可以帮助提高用户体验。

#1


3  

I cannot see any severe errors in your code though reasoning about it would be easier for me if you had written it in English.

我看不出你的代码有什么严重的错误,不过如果你用英语写出来的话,对我来说会更容易一些。

As you do malloc(sizeof(rekord)) you allocate memory to hold all members of a rekord. That is three char * pointers, an int and a double. You can write to those members immediately, no further allocation is needed. Of course, writing to a char * member is not really useful unless you are assigning it a pointer to some char buffer which you'd in turn obtain via malloc. For the int and double this is neither needed nor possible. So your code is correct here.

当您使用malloc(sizeof(rekord))时,您分配内存来容纳所有的rekord成员。这是三个char *指针,一个int数和一个double。您可以立即给这些成员写信,不需要进一步的分配。当然,对于char *成员的写入并不是很有用,除非您将它指定为一个指向某个char缓冲区的指针,而这是通过malloc获得的。对于int和double,这既不需要也不可能。所以这里的代码是正确的。

A few minor remarks, though:

不过有几句话:

  • You should check the return value of malloc. If it fails, it will return NULL. You should check for this (rare) event and handle the error if it happens. Usually, terminating the program will be an appropriate action.
  • 您应该检查malloc的返回值。如果失败,它将返回NULL。您应该检查这个(罕见的)事件并处理它发生的错误。通常,终止程序将是一个适当的动作。
  • You forgot to call rekordfree at the end.
  • 你最后忘了给rekordfree打电话。
  • Using non-ASCII characters in your program source code may or may not work. It should be avoided in portable programs.
  • 在程序源代码中使用非ascii字符可能有用,也可能不起作用。在便携式程序中应该避免使用它。
  • Your use of scanf for reading in the strings is a potential security hole as it might overrun the input buffer. Since you are going to store the string in a malloc()ed buffer anyway, I suggest you use getline as a convenient and safe alternative.
  • 在字符串中使用scanf是一个潜在的安全漏洞,因为它可能会超出输入缓冲区。既然您要将字符串存储在malloc()ed缓冲区中,我建议您使用getline作为方便和安全的替代方法。
  • Consider adding more whitespace to your output (eg newlines via \n). I guess that even if I understood the language, the output wouldn't be very easy to read as it's all on one line. Printing a space or a tab (\t) at the end of the input prompts might also help improve the user experience.
  • 考虑在输出中添加更多的空白(如通过\n)。我想,即使我理解了语言,输出也不会很容易读,因为它都在一行上。在输入提示符的末尾打印一个空格或一个制表符(\t)也可以帮助提高用户体验。