我有一个与本学期编程项目有关的问题。 我有一个具有结构的动态数组,该结构包含字符串的参数。问题是我需要将该字符串从静态更改为动态。 我编写了函数,要求输入字符串并将其存储在动态数组中然后返回它。 在程序的后面,我需要将数组中的信息(存储动态字符串)写入二进制文件。 我怎样才能实现这一目标,如何知道何时以及如何正确释放该动态字符串的内存? 如果我释放存储字符串的数组,是否还要释放存储字符串本身的内存?
我的数组将存储字符串:
inspections *inspectionsArray;
char* dynamicString(){
char *stringPointer = NULL,*paux = NULL, char;
int stringSize = 1,stringEnd = 0,i;
stringPointer = (char*)malloc(sizeof(char));
if (stringPointer == NULL) {
printf("\nError alocating memory");
}else{
printf("\nEnter String: ");
while (char != EOF && char != '\n') {
char = getc(stdin); //Obter o char do stding
paux = realloc(stringPointer, stringSize*sizeof(char));
if (paux != NULL) {
stringPointer = paux;
stringPointer[stringEnd] = char; //meter o char na string
stringSize++; //incrementar o tamanho da string
stringEnd++;
}else{
printf("\nErro a realocar memoria para a string");
}
}
stringPointer[stringEnd] = '\0';
printf("\nString: %s", stringPointer);
}
return stringPointer;
}
我将把我的字符串存储在其中的结构。
typedef struct
{
//A bunch of parameters in here
char *dynamicString;
} inspection;
enter code here
我用来将数据存储到数组的函数:
inspectionArray* registerInspection(inspection *inspectionArray){
char *string;
//I removed a bunch of code to not confuse things
string = dynamicString;
return inspection;
}
保存文件的功能:
void saveBinaryFile(inspection *inspections, int inspectionCounter)
{
FILE * inspectionArrayFile;
fileInspections = fopen("inspections.dat","wb");
if (fileInspections == NULL)
{
perror("\nError opening the file");
}
else
{
fwrite(&inspectionCounter, sizeof (int), 1, inspectionArrayFile);
fwrite(inspections, sizeof(tipoVeiculo), inspectionCounter, inspectionArrayFile);
// I write a bunch of stuff and verify it properly
fclose(inspectionArrayFile);
}
}
如何正确阅读和释放字符串?
我试过了:
void freeArrayStrings(inspections *inspectionsArray,int counter){
int i;
for (i=0; i<counter; i++) {
free(inspectionArray[i].dynamicString);
}
}
答案 0 :(得分:1)
您应该显示您的代码,以增加适当回答的机会。如果你要求释放存储指针到另一个内存的内存,请从malloc
获取,如下例所示:
struct str_wrap
{
char *str;
int strlen;
};
int main()
{
struct str_wrap *sw = malloc(sizeof *sw);
if (sw == NULL) return -1;
sw->str = malloc(strlen);
if (sw->str == NULL)
// handle
sw->strlen = strlen;
// many things with sw...
然后是的,您必须拨打free
两次(注意:您拨打malloc
的次数相同):
// free the memory
free(sw->str);
free(sw);
}
答案 1 :(得分:1)
除非你有一些特定的理由为dynamicString()
函数使用面向字符的输入,否则你可以通过使用面向行的>来大大简化你的生活。 em>标准C库提供的输入函数(例如fgets
或getline
)。另外,在C语言中,您通常会避免使用 camelCase 名称,而是使用小写来表示所有变量和函数名称。
对于dynamicstring()
功能,使用getline
您的功能会缩减为:
char *dynamicstring (inspection *i)
{
char *line = NULL; /* buffer for input */
size_t n = 0; /* alloc size 0 - getline decides */
ssize_t len = 0; /* no. of character read (or EOF) */
printf("\nEnter String: ");
len = getline (&line, &n, stdin); /* read input */
if (len <= 1) { /* line contains only '\n', 0, EOF */
free (line);
return NULL;
}
while (len > 0 && line[len-1] == '\n') /* remove '\n' */
line[--len] = 0;
i->dstring = line; /* assign pointer to dstring */
return line;
}
(注意:以上我对您的dstring
会员使用char *dynamicString;
)
您可以通过获取最终getline
的长度,将内存分配大小从line
分配的默认值精简到仅为输入字符串所需的数量,并分配该内存量(+1对于 nul-terminator ),并将line
复制到新的内存块。您可以使用strdup
功能一次完成所有操作。例如,您可以将以下内容添加到上面的函数中,然后返回str
:
char *str = NULL; /* pointer for final string storage */
...
str = strdup (line); /* refine allocation size */
free (line);
i->dstring = str; /* assign pointer to dstring */
return str;
即使进行了改进,完成的功能也比原始功能简单得多。现在注意:无论你是否分配了返回,因为如果输入不为空,函数只返回一个分配,你的某些inspection
字符串成员可能会有一些成员将被分配,一些空。因此,您需要在释放内存之前进行检查。 e.g:
if (ia->dstring)
free (ia->dstring);
与往常一样,在动态分配内存时,请使用内存错误检查程序(如Linux上的valgrind
)来确认正确使用和释放您分配的内存。使用此输入函数的一个简短示例是:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char *dstring;
} inspection;
char* dynamicstring (inspection *i);
int main (void) {
inspection *ia= NULL;
if (!(ia= malloc (sizeof *ia))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return 1;
}
if (dynamicstring (ia)) {
printf ("\n inspectionArray->dynamicstring : %s\n\n", ia->dstring);
if (ia->dstring)
free (ia->dstring);
}
free (ia);
return 0;
}
char *dynamicstring (inspection *i)
{
char *str = NULL; /* pointer for final string storage */
char *line = NULL; /* buffer for input */
size_t n = 0; /* alloc size 0 - getline decides */
ssize_t len = 0; /* no. of character read (or EOF) */
printf("\nEnter String: ");
len = getline (&line, &n, stdin); /* read input */
if (len <= 1) { /* line contains only '\n', 0, EOF */
free (line);
return NULL;
}
/* using shorthand 'len' instead of 'len > 0'
both test false when 'len' is 0 */
while (len && line[len-1] == '\n') /* remove '\n' */
line[--len] = 0;
str = strdup (line); /* refine allocation size */
free (line);
i->dstring = str; /* assign pointer to dstring */
return str;
}
尝试一下,如果您有疑问,请告诉我。
答案 2 :(得分:0)
您有错误:stringPointer = (char*)malloc(sizeof(char));
你需要stringPointer = (char*)malloc(sizeof(char *));
sizeof(char)可能是1个字节; sizeof(char *)大概是4。
您可能会因为某些内存系统总是分配至少32个字节而侥幸成功...
不要对每个输入字符重新分配。相反,声明char buf [255]或其他一些最大大小,保留一个大小索引,将输入字符分配给结尾,然后最后执行stringPointer = malloc(isize + 1)和strcpy(stringPointer,buf);如果您确实需要一个巨大的输入缓冲区,请从4K或1M开始,然后在填充该空间时重新分配。