释放字符串数组的函数
Function for freeing array of strings
在我的程序中,我有一个名为 freeFx() 的函数;
此函数被提供给两个数组和要释放的记录数。
调用此函数时出现无效指针错误。我不太明白这个错误是从哪里来的,任何帮助都会很棒!
代码如下:
/* ---- LIBRARIES ---- */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* ---- PROTOTYPES ---- */
int readFx(char** charArr, int* intArr);
/* int sortFx(char** arr, int arg2);
int printFx(char** arr, int arg2); */
int freeFx(char** charArr, int* intArr, int cnt);
char* getToken(char arr1[], int loc);
void makeRoom(char*** t, int** z, int size);
/* ---- MAIN ---- */
int main(void)
{
char** charPntrArr;
int* intPntrArr;
char* fileText;
int iniArrSize = 10;
int recCnt = 0;
int i = 0;
/* array to store addresses of arrays forming the rows */
charPntrArr = malloc(iniArrSize * sizeof(char*));
intPntrArr = malloc(iniArrSize * sizeof(int));
recCnt = readFx(charPntrArr, intPntrArr);
printf("%d\n", recCnt);
/*sortFx(pntrArr, recCnt);
printFx(pntrArr, recCnt); */
freeFx(charPntrArr, intPntrArr, recCnt);
return;
}
/* ---- FUNCTIONS ---- */
int readFx(char** charArr, int* intArr)
{
/*
input: csv file of string arrays
output: count of records received
purpose: read file, store values in array and populate pointer array
*/
char buffer[350];
char temp[350];
char temp2[350];
char*** reallocTemp;
char* token;
int counter;
int subLoc = 4;
int enrLoc = 9;
int arrSize = 10;
/* Clear headers */
fgets(buffer, sizeof(buffer), stdin);
counter = 0;
/* While file stream is not null */
while (fgets(buffer, sizeof(buffer), stdin) != NULL)
{
/* Populate array within array if pntr arr has room */
if (counter < arrSize)
{
/* buffer copy*/
strcpy(temp, buffer);
strcpy(temp2, buffer);
/* create array for token values*/
charArr[counter] = malloc(10 * sizeof(char));
/* Get first token */
token = getToken(temp, subLoc);
strcpy(charArr[counter], token);
/* Get second token */
token = getToken(temp2, enrLoc);
intArr[counter] = atoi(token);
counter++;
}
else
{
/* Reallocate memory due to necessary expansion */
makeRoom(&charArr, &intArr, arrSize);
/* Realloc was successful */
if (temp != NULL)
{
arrSize = arrSize * 2;
/* Print Reallocation info */
printf("reallocating to %d\n", arrSize);
/* Populate values for current buffer now that you have realloc'd */
/* buffer copy*/
strcpy(temp, buffer);
strcpy(temp2, buffer);
/* create array for token values */
charArr[counter] = malloc(10 * sizeof(char));
/* Get first token */
token = getToken(temp, subLoc);
strcpy(charArr[counter], token);
/* Get second token */
token = getToken(temp2, enrLoc);
intArr[counter] = atoi(token);
counter++;
}
else
{
printf("unable to reallocate\n");
exit(1);
}
}
}
return counter;
}
char* getToken(char arr1[], int loc)
{
/*
input: string array & location of desired string
output: string of token at position
purpose: grab string (char*) of certain position in given array
*/
int loopCnt;
char* del = ",\n";
/* Grab first token */
char* token = strtok(arr1, del);
/* Loop through array to grab value at given location */
for (loopCnt = 1; loopCnt < loc; loopCnt++)
{
token = strtok(NULL, del);
}
return token;
}
int freeFx(char** charArr, int* intArr, int cnt)
{
int i;
printf("INSIDE FREE FX\n");
for (i = 0; i < cnt; i++)
{
printf("%d\n", i);
free(charArr[i]);
}
printf("FREED ARRAYS WITHIN ARRAY\n");
free(charArr);
printf("CHAR ARR FREE\n");
free(intArr);
printf("INT ARR FREE\n");
return 0;
}
void makeRoom(char*** t, int** z, int size)
{
*t = (char**)realloc(*t, size * 2 * sizeof(char*));
*z = (int*)realloc(*z, size * 2 * sizeof(int*));
}
这是文本文件中的示例:
Term Code,Session Code,Campus Code,Subject,Catalog Nbr,Section,Class Nbr,Class Component,Enrollment Total,Enrollment Cap,Enrollment Availability,Waitlist Total,Waitlist Cap,Instructor Name,Instructor Email,Building Code,Room Nbr,Start Time,End Time,M,T,W,Th,F,Sa,Su,Class Start Date,Class End Date
2152,1,MAIN,SOCW,6390,6,22913,IND - Independent Study,0,1,1,0,0,,,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,MUSI,4460,3,21831,PRI - Private Lesson,0,20,20,0,0,Michael J Drake,mjdrake@uta.edu,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,MAE,4301,1,27674,LEC - Lecture,0,5,5,0,3,,,NH,109,7:00 PM,8:20 PM,Y,N,Y,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,EE,2403,101,25557,LAB - Laboratory,11,24,13,0,0,Jonathan W Bredow,jbredow@uta.edu,NH,148A,5:30 PM,8:20 PM,Y,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,SOCW,6451,68,26055,PRA - Practicum,1,1,0,0,0,Laura S Frank,laura.frank@mavs.uta.edu,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,ARCH,3331,1,20182,LEC - Lecture,47,61,14,0,0,Edward R Nelson,nelsone@uta.edu,ARCH,401,5:30 PM,6:50 PM,Y,N,Y,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,BIOL,6291,7,26391,IND - Independent Study,0,5,5,0,0,Matthew Fujita,mkfujita@uta.edu,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,BE,6194,12,30366,IND - Independent Study,6,6,0,0,0,Young-Tae Kim,ykim@uta.edu,,,,,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,BIOL,5698,21,27536,THE - Thesis Research,0,5,5,0,0,Laura D Mydlarz,mydlarz@uta.edu,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,EDAD,6399,7,20089,DTN - Dissertation,2,10,8,0,0,Daniel B Saunders,saunders@uta.edu,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,BE,3344,14,26082,LEC - Lecture,6,10,4,0,0,Baohong Yuan,baohong@uta.edu,ERB,131,11:00 AM,12:20 PM,N,Y,N,Y,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,EDAD,6390,11,26017,LEC - Lecture,0,10,10,0,0,Yi Zhang,lyzhang@uta.edu,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,BIOL,3454,2,20468,LAB - Laboratory,31,30,-1,0,0,Nicholas A Long,nicholas.long@mavs.uta.edu,LS,133,1:00 PM,4:50 PM,Y,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,CHEM,1451,1,22411,LEC - Lecture,118,140,22,0,0,Seiichiro Tanizaki,tanizaki@uta.edu,SH,121,9:00 AM,9:50 AM,Y,N,Y,N,Y,N,N,1/20/2015,5/8/2015
2152,1,MAIN,ME,6297,39,30394,IND - Independent Study,1,5,4,0,0,Ashfaq Adnan,aadnan@uta.edu,,,,,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,MUSI,1243,2,21463,PRI - Private Lesson,1,20,19,0,0,Young-Hyun Cho,yhcho@uta.edu,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,MUSI,4242,2,21728,PRI - Private Lesson,0,20,20,0,0,Young-Hyun Cho,yhcho@uta.edu,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,EVSE,6399,44,25290,DTN - Dissertation,1,5,4,0,0,Merlynd K Nestell,nestell@uta.edu,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
检查 readFx 的 return 值。
post 整个功能可能会更容易。也许计数器不是从 0
开始
据我所知,除了一般代码的脆弱性(我会更改很多)之外,最大的问题是您传递给 reader 函数的按值数组。
您最初在此处调整大小 main()
:
charPntrArr = malloc(iniArrSize * sizeof(char*));
intPntrArr = malloc(iniArrSize * sizeof(int)); // note: fixed this. also fix in your resize fn
然后它们的值(每个指针持有的地址)被传递到你的reader这里:
recCnt = readFx(charPntrArr, intPntrArr);
在不同的时间,reader 可以(并且确实)调整这些缓冲区的大小,包括在需要时重新定位数据。不能保证基地址保持不变。因此,当 readFX
returns 时,指针仍保持原始值,但调整大小的努力早已使这些位置不再定义为可访问。
解决此问题的快速方法是执行以下操作:
- 更改您的
readFX
函数以按地址获取其指针参数(指向指针的指针)。
- 在实际函数中重命名输入参数(看到下面的代码就会明白)
- 声明具有相同原始名称的局部变量,并使用参数的解除引用初始值进行初始化。
- 函数完成后将局部变量保存回取消引用的参数。
像这样:
int readFx(char*** ppCharArr, int** ppIntArr)
{
char **charArr = *ppCharArr;
int *intArr = *ppIntArr;
/*
input: csv file of string arrays
output: count of records received
purpose: read file, store values in array and populate pointer array
*/
char buffer[350];
char temp[350];
char* token;
int counter;
int subLoc = 4;
int enrLoc = 9;
int arrSize = 10;
counter = 0;
/* Clear headers */
fgets(buffer, sizeof(buffer), stdin);
/* While file stream is not null */
while (fgets(buffer, sizeof(buffer), stdin) != NULL)
{
/* Populate array within array if pntr arr has room */
if (counter >= arrSize)
{
/* Reallocate memory due to necessary expansion */
arrSize = makeRoom(&charArr, &intArr, arrSize);
/* Realloc was successful */
if (charArr == NULL || intArr == NULL)
{
printf("unable to reallocate\n");
exit(1);
}
}
/* buffer copy*/
strcpy(temp, buffer);
/* Get first token */
token = getToken(buffer, subLoc);
if (token != NULL)
charArr[subLoc] = strdup(token);
/* Get second token */
token = getToken(temp, enrLoc);
intArr[counter] = atoi(token);
counter++;
}
*ppCharArr = charArr;
*ppIntArr = intArr;
return counter;
}
像这样从 main()
调用:
charPntrArr = malloc(iniArrSize * sizeof *charPntrArr);
intPntrArr = malloc(iniArrSize * sizeof *intPntrArr);
recCnt = readFx(&charPntrArr, &intPntrArr);
freeFX
调用可以保持原样。这是我能为您解决此特定问题的最快方法。 注意: 我对这段代码进行了一些修改,所以有些东西无法通过简单的 cut/paste 返回到您的代码库(我已经 makeRoom
返回例如,新尺寸),但您仍然可以看到根本问题是什么。
希望对您有所帮助。
更新
一个精简版,在读取数组和内容的冒泡排序中集成了分配。我希望 OP 觉得它有用。恕我直言,这比原始版本要干净得多。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* ---- PROTOTYPES ---- */
int readFx(char*** ppCharArr, int** ppIntArr);
int freeFx(char** charArr, int* intArr, int cnt);
void sortFx(char** const charArr, int* const intArr, int cnt);
/* ---- MAIN ---- */
int main(void)
{
char** charPntrArr = NULL;
int* intPntrArr = NULL;
int recCnt = 0;
/* array to store addresses of arrays forming the rows */
/* read file and get record count */
recCnt = readFx(&charPntrArr, &intPntrArr);
sortFx(charPntrArr, intPntrArr, recCnt);
freeFx(charPntrArr, intPntrArr, recCnt);
}
/* ---- FUNCTIONS ---- */
int readFx(char*** ppCharArr, int** ppIntArr)
{
const int subLoc = 4;
const int enrLoc = 9;
char **charArr = *ppCharArr;
int *intArr = *ppIntArr;
char line[350];
char* token = NULL;
int arrSize = 0;
int counter = 0;
int i=0;
/* Clear headers */
fgets(line, sizeof(line), stdin);
while (fgets(line, sizeof(line), stdin) != NULL)
{
// check for reallocation prior to insertion
if (counter == arrSize)
{
// need to expand
int newSize = (arrSize ? (2*arrSize) : 1);
void *tmp = realloc(charArr, newSize * sizeof *charArr);
if (tmp == NULL)
{
fprintf(stderr, "Failed to expand charArr to %d elements", newSize);
exit(1);
}
charArr = tmp;
// expand intArr likewise
tmp = realloc(intArr, newSize * sizeof(*intArr));
if (tmp == NULL)
{
fprintf(stderr, "Failed to expand intArr to %d elements", newSize);
exit(1);
}
intArr = tmp;
arrSize = newSize;
printf("Resized arrays to %d slots\n", newSize);
}
// get tokens
for (token = strtok(line, ",\n"), i=1; token && (i<subLoc); ++i)
token = strtok(NULL, ",\n");
if (token)
{
charArr[counter] = strdup(token);
// next token
for (; token && i<enrLoc; ++i)
token = strtok(NULL, ",\n");
if (token)
{
intArr[counter] = atoi(token);
printf("%s %d\n", charArr[counter], intArr[counter]);
++counter;
}
else
{
free(charArr[counter]);
}
}
}
*ppCharArr = charArr;
*ppIntArr = intArr;
return counter;
}
int freeFx(char** charArr, int* intArr, int cnt)
{
while (cnt--)
free(charArr[cnt]);
free(charArr);
free(intArr);
return 0;
}
void sortFx(char** const charArr, int* const intArr, int cnt)
{
int swapped = 1, i, j=cnt;
// simple bubblesort algorithm. note there is no string copying cone here
// we compare strings, and if swapping is needed, swap *pointers* in the
// charArr pointer array (and intArr side by side, but that is unrelated)
while (swapped && j--)
{
swapped = 0; // reset swap detection
for (i = 0; i < j; ++i)
{
int cmp = strcmp(charArr[i], charArr[i+1]);
if ( cmp > 0)
{
char *strTmp = charArr[i];
int intTemp = intArr[i];
// do the swaps
charArr[i] = charArr[i+1];
charArr[i+1] = strTmp;
intArr[i] = intArr[i+1];
intArr[i+1] = intTemp;
// something swapped so set flag
swapped = 1;
}
else if (cmp == 0 && intArr[i] > intArr[i+1])
{
int intTemp = intArr[i];
intArr[i] = intArr[i+1];
intArr[i+1] = intTemp;
// something swapped so set flag
swapped = 1;
}
}
}
printf("\nSORTED RESULTS\n");
for (i=0; i<cnt; ++i)
printf("%s %d\n", charArr[i], intArr[i]);
}
输出
以下输出来自粘贴的样本数据。
Resized arrays to 1 slots
SOCW 0
Resized arrays to 2 slots
MUSI 0
Resized arrays to 4 slots
MAE 0
EE 11
Resized arrays to 8 slots
SOCW 1
ARCH 47
BIOL 0
BE 6
Resized arrays to 16 slots
BIOL 0
EDAD 2
BE 6
EDAD 0
BIOL 31
CHEM 118
ME 1
MUSI 1
Resized arrays to 32 slots
MUSI 0
EVSE 1
SORTED RESULTS
ARCH 47
BE 6
BE 6
BIOL 0
BIOL 0
BIOL 31
CHEM 118
EDAD 0
EDAD 2
EE 11
EVSE 1
MAE 0
ME 1
MUSI 0
MUSI 0
MUSI 1
SOCW 0
SOCW 1
在我的程序中,我有一个名为 freeFx() 的函数;
此函数被提供给两个数组和要释放的记录数。
调用此函数时出现无效指针错误。我不太明白这个错误是从哪里来的,任何帮助都会很棒!
代码如下:
/* ---- LIBRARIES ---- */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* ---- PROTOTYPES ---- */
int readFx(char** charArr, int* intArr);
/* int sortFx(char** arr, int arg2);
int printFx(char** arr, int arg2); */
int freeFx(char** charArr, int* intArr, int cnt);
char* getToken(char arr1[], int loc);
void makeRoom(char*** t, int** z, int size);
/* ---- MAIN ---- */
int main(void)
{
char** charPntrArr;
int* intPntrArr;
char* fileText;
int iniArrSize = 10;
int recCnt = 0;
int i = 0;
/* array to store addresses of arrays forming the rows */
charPntrArr = malloc(iniArrSize * sizeof(char*));
intPntrArr = malloc(iniArrSize * sizeof(int));
recCnt = readFx(charPntrArr, intPntrArr);
printf("%d\n", recCnt);
/*sortFx(pntrArr, recCnt);
printFx(pntrArr, recCnt); */
freeFx(charPntrArr, intPntrArr, recCnt);
return;
}
/* ---- FUNCTIONS ---- */
int readFx(char** charArr, int* intArr)
{
/*
input: csv file of string arrays
output: count of records received
purpose: read file, store values in array and populate pointer array
*/
char buffer[350];
char temp[350];
char temp2[350];
char*** reallocTemp;
char* token;
int counter;
int subLoc = 4;
int enrLoc = 9;
int arrSize = 10;
/* Clear headers */
fgets(buffer, sizeof(buffer), stdin);
counter = 0;
/* While file stream is not null */
while (fgets(buffer, sizeof(buffer), stdin) != NULL)
{
/* Populate array within array if pntr arr has room */
if (counter < arrSize)
{
/* buffer copy*/
strcpy(temp, buffer);
strcpy(temp2, buffer);
/* create array for token values*/
charArr[counter] = malloc(10 * sizeof(char));
/* Get first token */
token = getToken(temp, subLoc);
strcpy(charArr[counter], token);
/* Get second token */
token = getToken(temp2, enrLoc);
intArr[counter] = atoi(token);
counter++;
}
else
{
/* Reallocate memory due to necessary expansion */
makeRoom(&charArr, &intArr, arrSize);
/* Realloc was successful */
if (temp != NULL)
{
arrSize = arrSize * 2;
/* Print Reallocation info */
printf("reallocating to %d\n", arrSize);
/* Populate values for current buffer now that you have realloc'd */
/* buffer copy*/
strcpy(temp, buffer);
strcpy(temp2, buffer);
/* create array for token values */
charArr[counter] = malloc(10 * sizeof(char));
/* Get first token */
token = getToken(temp, subLoc);
strcpy(charArr[counter], token);
/* Get second token */
token = getToken(temp2, enrLoc);
intArr[counter] = atoi(token);
counter++;
}
else
{
printf("unable to reallocate\n");
exit(1);
}
}
}
return counter;
}
char* getToken(char arr1[], int loc)
{
/*
input: string array & location of desired string
output: string of token at position
purpose: grab string (char*) of certain position in given array
*/
int loopCnt;
char* del = ",\n";
/* Grab first token */
char* token = strtok(arr1, del);
/* Loop through array to grab value at given location */
for (loopCnt = 1; loopCnt < loc; loopCnt++)
{
token = strtok(NULL, del);
}
return token;
}
int freeFx(char** charArr, int* intArr, int cnt)
{
int i;
printf("INSIDE FREE FX\n");
for (i = 0; i < cnt; i++)
{
printf("%d\n", i);
free(charArr[i]);
}
printf("FREED ARRAYS WITHIN ARRAY\n");
free(charArr);
printf("CHAR ARR FREE\n");
free(intArr);
printf("INT ARR FREE\n");
return 0;
}
void makeRoom(char*** t, int** z, int size)
{
*t = (char**)realloc(*t, size * 2 * sizeof(char*));
*z = (int*)realloc(*z, size * 2 * sizeof(int*));
}
这是文本文件中的示例:
Term Code,Session Code,Campus Code,Subject,Catalog Nbr,Section,Class Nbr,Class Component,Enrollment Total,Enrollment Cap,Enrollment Availability,Waitlist Total,Waitlist Cap,Instructor Name,Instructor Email,Building Code,Room Nbr,Start Time,End Time,M,T,W,Th,F,Sa,Su,Class Start Date,Class End Date
2152,1,MAIN,SOCW,6390,6,22913,IND - Independent Study,0,1,1,0,0,,,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,MUSI,4460,3,21831,PRI - Private Lesson,0,20,20,0,0,Michael J Drake,mjdrake@uta.edu,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,MAE,4301,1,27674,LEC - Lecture,0,5,5,0,3,,,NH,109,7:00 PM,8:20 PM,Y,N,Y,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,EE,2403,101,25557,LAB - Laboratory,11,24,13,0,0,Jonathan W Bredow,jbredow@uta.edu,NH,148A,5:30 PM,8:20 PM,Y,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,SOCW,6451,68,26055,PRA - Practicum,1,1,0,0,0,Laura S Frank,laura.frank@mavs.uta.edu,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,ARCH,3331,1,20182,LEC - Lecture,47,61,14,0,0,Edward R Nelson,nelsone@uta.edu,ARCH,401,5:30 PM,6:50 PM,Y,N,Y,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,BIOL,6291,7,26391,IND - Independent Study,0,5,5,0,0,Matthew Fujita,mkfujita@uta.edu,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,BE,6194,12,30366,IND - Independent Study,6,6,0,0,0,Young-Tae Kim,ykim@uta.edu,,,,,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,BIOL,5698,21,27536,THE - Thesis Research,0,5,5,0,0,Laura D Mydlarz,mydlarz@uta.edu,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,EDAD,6399,7,20089,DTN - Dissertation,2,10,8,0,0,Daniel B Saunders,saunders@uta.edu,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,BE,3344,14,26082,LEC - Lecture,6,10,4,0,0,Baohong Yuan,baohong@uta.edu,ERB,131,11:00 AM,12:20 PM,N,Y,N,Y,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,EDAD,6390,11,26017,LEC - Lecture,0,10,10,0,0,Yi Zhang,lyzhang@uta.edu,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,BIOL,3454,2,20468,LAB - Laboratory,31,30,-1,0,0,Nicholas A Long,nicholas.long@mavs.uta.edu,LS,133,1:00 PM,4:50 PM,Y,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,CHEM,1451,1,22411,LEC - Lecture,118,140,22,0,0,Seiichiro Tanizaki,tanizaki@uta.edu,SH,121,9:00 AM,9:50 AM,Y,N,Y,N,Y,N,N,1/20/2015,5/8/2015
2152,1,MAIN,ME,6297,39,30394,IND - Independent Study,1,5,4,0,0,Ashfaq Adnan,aadnan@uta.edu,,,,,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,MUSI,1243,2,21463,PRI - Private Lesson,1,20,19,0,0,Young-Hyun Cho,yhcho@uta.edu,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,MUSI,4242,2,21728,PRI - Private Lesson,0,20,20,0,0,Young-Hyun Cho,yhcho@uta.edu,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
2152,1,MAIN,EVSE,6399,44,25290,DTN - Dissertation,1,5,4,0,0,Merlynd K Nestell,nestell@uta.edu,,,12:00 AM,12:00 AM,N,N,N,N,N,N,N,1/20/2015,5/8/2015
检查 readFx 的 return 值。
post 整个功能可能会更容易。也许计数器不是从 0
开始据我所知,除了一般代码的脆弱性(我会更改很多)之外,最大的问题是您传递给 reader 函数的按值数组。
您最初在此处调整大小 main()
:
charPntrArr = malloc(iniArrSize * sizeof(char*));
intPntrArr = malloc(iniArrSize * sizeof(int)); // note: fixed this. also fix in your resize fn
然后它们的值(每个指针持有的地址)被传递到你的reader这里:
recCnt = readFx(charPntrArr, intPntrArr);
在不同的时间,reader 可以(并且确实)调整这些缓冲区的大小,包括在需要时重新定位数据。不能保证基地址保持不变。因此,当 readFX
returns 时,指针仍保持原始值,但调整大小的努力早已使这些位置不再定义为可访问。
解决此问题的快速方法是执行以下操作:
- 更改您的
readFX
函数以按地址获取其指针参数(指向指针的指针)。 - 在实际函数中重命名输入参数(看到下面的代码就会明白)
- 声明具有相同原始名称的局部变量,并使用参数的解除引用初始值进行初始化。
- 函数完成后将局部变量保存回取消引用的参数。
像这样:
int readFx(char*** ppCharArr, int** ppIntArr)
{
char **charArr = *ppCharArr;
int *intArr = *ppIntArr;
/*
input: csv file of string arrays
output: count of records received
purpose: read file, store values in array and populate pointer array
*/
char buffer[350];
char temp[350];
char* token;
int counter;
int subLoc = 4;
int enrLoc = 9;
int arrSize = 10;
counter = 0;
/* Clear headers */
fgets(buffer, sizeof(buffer), stdin);
/* While file stream is not null */
while (fgets(buffer, sizeof(buffer), stdin) != NULL)
{
/* Populate array within array if pntr arr has room */
if (counter >= arrSize)
{
/* Reallocate memory due to necessary expansion */
arrSize = makeRoom(&charArr, &intArr, arrSize);
/* Realloc was successful */
if (charArr == NULL || intArr == NULL)
{
printf("unable to reallocate\n");
exit(1);
}
}
/* buffer copy*/
strcpy(temp, buffer);
/* Get first token */
token = getToken(buffer, subLoc);
if (token != NULL)
charArr[subLoc] = strdup(token);
/* Get second token */
token = getToken(temp, enrLoc);
intArr[counter] = atoi(token);
counter++;
}
*ppCharArr = charArr;
*ppIntArr = intArr;
return counter;
}
像这样从 main()
调用:
charPntrArr = malloc(iniArrSize * sizeof *charPntrArr);
intPntrArr = malloc(iniArrSize * sizeof *intPntrArr);
recCnt = readFx(&charPntrArr, &intPntrArr);
freeFX
调用可以保持原样。这是我能为您解决此特定问题的最快方法。 注意: 我对这段代码进行了一些修改,所以有些东西无法通过简单的 cut/paste 返回到您的代码库(我已经 makeRoom
返回例如,新尺寸),但您仍然可以看到根本问题是什么。
希望对您有所帮助。
更新
一个精简版,在读取数组和内容的冒泡排序中集成了分配。我希望 OP 觉得它有用。恕我直言,这比原始版本要干净得多。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* ---- PROTOTYPES ---- */
int readFx(char*** ppCharArr, int** ppIntArr);
int freeFx(char** charArr, int* intArr, int cnt);
void sortFx(char** const charArr, int* const intArr, int cnt);
/* ---- MAIN ---- */
int main(void)
{
char** charPntrArr = NULL;
int* intPntrArr = NULL;
int recCnt = 0;
/* array to store addresses of arrays forming the rows */
/* read file and get record count */
recCnt = readFx(&charPntrArr, &intPntrArr);
sortFx(charPntrArr, intPntrArr, recCnt);
freeFx(charPntrArr, intPntrArr, recCnt);
}
/* ---- FUNCTIONS ---- */
int readFx(char*** ppCharArr, int** ppIntArr)
{
const int subLoc = 4;
const int enrLoc = 9;
char **charArr = *ppCharArr;
int *intArr = *ppIntArr;
char line[350];
char* token = NULL;
int arrSize = 0;
int counter = 0;
int i=0;
/* Clear headers */
fgets(line, sizeof(line), stdin);
while (fgets(line, sizeof(line), stdin) != NULL)
{
// check for reallocation prior to insertion
if (counter == arrSize)
{
// need to expand
int newSize = (arrSize ? (2*arrSize) : 1);
void *tmp = realloc(charArr, newSize * sizeof *charArr);
if (tmp == NULL)
{
fprintf(stderr, "Failed to expand charArr to %d elements", newSize);
exit(1);
}
charArr = tmp;
// expand intArr likewise
tmp = realloc(intArr, newSize * sizeof(*intArr));
if (tmp == NULL)
{
fprintf(stderr, "Failed to expand intArr to %d elements", newSize);
exit(1);
}
intArr = tmp;
arrSize = newSize;
printf("Resized arrays to %d slots\n", newSize);
}
// get tokens
for (token = strtok(line, ",\n"), i=1; token && (i<subLoc); ++i)
token = strtok(NULL, ",\n");
if (token)
{
charArr[counter] = strdup(token);
// next token
for (; token && i<enrLoc; ++i)
token = strtok(NULL, ",\n");
if (token)
{
intArr[counter] = atoi(token);
printf("%s %d\n", charArr[counter], intArr[counter]);
++counter;
}
else
{
free(charArr[counter]);
}
}
}
*ppCharArr = charArr;
*ppIntArr = intArr;
return counter;
}
int freeFx(char** charArr, int* intArr, int cnt)
{
while (cnt--)
free(charArr[cnt]);
free(charArr);
free(intArr);
return 0;
}
void sortFx(char** const charArr, int* const intArr, int cnt)
{
int swapped = 1, i, j=cnt;
// simple bubblesort algorithm. note there is no string copying cone here
// we compare strings, and if swapping is needed, swap *pointers* in the
// charArr pointer array (and intArr side by side, but that is unrelated)
while (swapped && j--)
{
swapped = 0; // reset swap detection
for (i = 0; i < j; ++i)
{
int cmp = strcmp(charArr[i], charArr[i+1]);
if ( cmp > 0)
{
char *strTmp = charArr[i];
int intTemp = intArr[i];
// do the swaps
charArr[i] = charArr[i+1];
charArr[i+1] = strTmp;
intArr[i] = intArr[i+1];
intArr[i+1] = intTemp;
// something swapped so set flag
swapped = 1;
}
else if (cmp == 0 && intArr[i] > intArr[i+1])
{
int intTemp = intArr[i];
intArr[i] = intArr[i+1];
intArr[i+1] = intTemp;
// something swapped so set flag
swapped = 1;
}
}
}
printf("\nSORTED RESULTS\n");
for (i=0; i<cnt; ++i)
printf("%s %d\n", charArr[i], intArr[i]);
}
输出
以下输出来自粘贴的样本数据。
Resized arrays to 1 slots
SOCW 0
Resized arrays to 2 slots
MUSI 0
Resized arrays to 4 slots
MAE 0
EE 11
Resized arrays to 8 slots
SOCW 1
ARCH 47
BIOL 0
BE 6
Resized arrays to 16 slots
BIOL 0
EDAD 2
BE 6
EDAD 0
BIOL 31
CHEM 118
ME 1
MUSI 1
Resized arrays to 32 slots
MUSI 0
EVSE 1
SORTED RESULTS
ARCH 47
BE 6
BE 6
BIOL 0
BIOL 0
BIOL 31
CHEM 118
EDAD 0
EDAD 2
EE 11
EVSE 1
MAE 0
ME 1
MUSI 0
MUSI 0
MUSI 1
SOCW 0
SOCW 1