从文件中读取 int 和 char 数组,然后调整数组大小
read int and char array from file, then resize array
我正在学习操作数组。我将从文件读取的逐个元素数据存储到 main() 外部名为 readInput() 的函数中的 char 和 int 数组中。读取数据:
D E D D E E D E E E D E
21 32 35 59 58 16 11 29
我尝试调整两个数组的大小以使用 realloc 排除数组中的垃圾:我的问题:
在 main() 中打印 char 数组时,它包含正确的元素,但在数组末尾打印垃圾。我注意到它在 readInput() 中正确打印。我做错了什么?
在realloc前后的readInput()和main()中,int数组的文件读取的元素都是正确的,只是后面跟着垃圾。我做错了什么?
输出:
从 readInput() 打印 - 重新分配之前的字符数组:D E D D E E E D E E E D E
从 readInput() 打印 - 重新分配之前的 Int 数组:21 32 35 59 58 16 11 29 -8421
50451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -8421504
51 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451
从 readInput() 打印 - 重新分配后的字符数组:D E D D E E E D E E E D E
从 readInput() 打印 - Int After realloc:21 32 35 59 58 16 11 29 -336860
19 -842150451 739749649 37763 4849560 4849264 -842150451 -842150451 -842150451 -
842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842
从 main() 打印 - 字符数组(重新分配后): D E D D E E D E E E D E ═ ═ ═ ═ ═ ═ ═ ═ ═ ═
═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ² ² ² ` ² w ³
É · y É V t ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ = ²= ²
Print from main() - Int Array (after realloc): 21 32 35 59 58 16 11 29 -33686019 -842150451 874388096 31426 6946712 6946416 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 继续
节目背景:
读取的数据存储在 main() 外部的函数中,名为 readInput(),char by char/int by int 分别为 char 和 int 数组,它们通过 main() 中的 malloc 声明和初始大小。
在数组中存储数据后,我需要将数组的大小调整为文件中读取的数据的大小。
最后,为了验证 main 也可以访问数组,在 main() 和 readInput() 中分别写入 char 和 int 数组。
感谢您的帮助。
编辑更正的工作代码,谢谢!
#include <stdio.h>
#include <ctype.h>
#include <string.h>
//prototypes
void openFile(char *fileNames, FILE **inputFilePointer);
void closeFile(FILE **inputFilePointer);
void readInput(char *choiceArray, int *valueArray, int *charArraySize, int *intArraySize, FILE **inputFilePointer);
void memCharReallocation(char **choiceArray, int requiredArraySize);//resize char array to what's actually required after reading the file
void memIntReallocation(int **valueArray, int intSize);//resize int array to what's actually required after reading the file
void main()
{
char *charArray =NULL;
int *valueArray;
int inputSize;
int charInputSize = 0;//size of elements read from file
int intInputSize = 0;//size of elements read from file
//file read/write variables
FILE *iFilePointer;//file pointer
char *filename = "inputFileTest.txt";
//open and read Files
openFile(filename, &iFilePointer);
//initial mem allocation to size char and int array
valueArray = (int*)malloc(sizeof(int) * 100);
if (valueArray == NULL)
{
printf("\nCould not allocate memory, exiting.\n");
exit(1);
}
charArray = (char*)malloc(sizeof(char) * 100);
if (charArray == NULL)
{
printf("\nCould not allocate memory, exiting.\n");
exit(1);
}
//read file and allocate to array
readInput(charArray, valueArray, &charInputSize, &intInputSize, &iFilePointer);
//print char array: Test I can read it here too
printf("\nPrint from main() - Char Array: ");
for (int j = 0; j<charInputSize; j++)
{
printf("%c ", charArray[j]);
}
//Print int array
printf("\nPrint from main() - Int Array: ");
for (int j = 0; j<intInputSize; j++)
{
printf("%d ", valueArray[j]);
}
}
//read data from file
void readInput(char *readCharArray, int *readValueArray, int *charArraySize, int *intArraySize, FILE **inputFilePointer)
{
int i, j = 0;//loop variables
char *pbuffer = NULL;//buffer to read input file
int bufferSize = 200;//max initial size for buffer
char *token = NULL;////tonize
char ch = NULL;//convert string char to char
int readingChar = 0;//flag we are reading char from file
//alloc memory to pbuffer
pbuffer = (char*)malloc(sizeof(char)*bufferSize);
if (pbuffer == NULL)
{
printf("\nCould not allocate memory, exiting.\n");
exit(1);
}
printf("Read Input From File: \n");
//store each element from file in struct variable
while (fgets(pbuffer, bufferSize, *inputFilePointer) != NULL)//read each line from file
{
j = 0;//reset array to subscript zero on each pass
//tokenize file data
for (token = strtok(pbuffer, " "); token != NULL; token = strtok(NULL, " "))
{
//char token
if (isalpha(token[0]))
{
ch = token[0];
readCharArray[j++] = ch;
readingChar = 1;//flag we are reading char from file to get length of array excl array garbage
}
//int token
else if (isdigit(token[0]))
{
readValueArray[j++] = atoi(token);
(*intArraySize)++;
}
else
{
printf("\nCan't read file\n");
exit(1);
}
}
if (readingChar)
{
readCharArray[j] = '[=10=]';//remove excess cells on array
*charArraySize = strlen(readCharArray);//size of array
readingChar = 0;//end of reading char from file
}
}
//print char array: Test 1
printf("\nPrint from readInput() - Char Array before realloc: ");
for (int j = 0; j < *charArraySize; j++)
{
printf("%c ", readCharArray[j]);
}
//Print int array
printf("\nPrint from readInput() - Int Array before realloc: ");
for (int j = 0; j < *intArraySize; j++)
{
printf("%d ", readValueArray[j]);
}
memCharReallocation(&readCharArray, charArraySize);
memIntReallocation(&readValueArray, intArraySize);
printf("\nPrint from readInput() - Char Array after realloc: ");
for (int j = 0; j < *charArraySize; j++)
{
printf("%c ", readCharArray[j]);
}
printf("\nPrint from readInput() - Int After after realloc:");
for (int j = 0; j < *intArraySize; j++)
{
printf("%d ", readValueArray[j]);
}
}
void memCharReallocation(char **charArray, int requiredArraySize)//resize int array to what's actually required after reading the file
{
char *ptempArray = NULL;
ptempArray = (char*)realloc(*charArray, requiredArraySize * sizeof(char*));
if (ptempArray == NULL)
{
printf("Could not allocate memory, exiting");
exit(1);
}
else
*charArray = ptempArray;
if (ptempArray != *charArray)
free(ptempArray);
}
void memIntReallocation(int **valueArray, int intSize)//resize int array to what's actually required after reading the file
{
int *ptempArray = NULL;
ptempArray = (int*)realloc(*valueArray, intSize* sizeof(int*));
if (ptempArray == NULL)
{
printf("Could not allocate memory, exiting");
exit(1);
}
else
*valueArray = ptempArray;
if (ptempArray != *valueArray)
free(ptempArray);
}
void openFile(char *fileNames, FILE **inputFilePointer)
{
printf("\n\n");
//open files and error mssg
if ((*inputFilePointer = fopen(fileNames, "r")) == NULL) {
printf("Can't open input file %s\n", fileNames[1]);
exit(1);
}
}
void closeFile(FILE **inputFilePointer)
{
//close files
fclose(*inputFilePointer);
}
首先,警告是不容忽视的。
void main(char *argv) {
...
argv = ...;
应该提出一个(CLang 甚至给出错误!)因为它不符合 C。它应该是:
int main() {
...
char *filename = ...;
如果不使用 argv,请不要声明它,并避免将 argv
用于命令行参数以外的任何其他内容。
下一步:for (int j = 0; j < charArray!=NULL; j++)
也应该发出大量警告。您首先比较 j
和 charArray
(已经是未定义的行为)。看到结果后,j < charArray
恰好为真(C 中的值为 1),您将其与 void *
的 NULL 进行比较! 1 != 0
永远是真的,你会得到一个永无止境的循环。
for (int j = 0; j < charSize || readValueArray[j] != NULL; j++)
也应该发出警告:readValueArray[j]
是一个 int
而 NULL
是一个 void *
。另外,测试readValueArray[j]
到0
是没有用的,因为你从来没有初始化分配的内存。
最终调整大小不会从数组中删除垃圾它会在内存中某处重新分配具有要求大小的数组,如果您访问分配的内存,您只需调用未定义的行为。 C 中无法知道数组的大小,关心它是程序员的工作。
所以你有两种可能的方法:
要么将数组的实际大小作为 readInput
的(输出)参数传递:
void readInput(char *choiceArray, int *valueArray, FILE **inputFilePointer,
int *choiceArraySize, int *valueArraySize)
或使用特殊值(例如 0)作为结束标记。
并且请注意警告!
在while (fgets(pbuffer, bufferSize, *inputFilePointer) != NULL)
的正文中
您使用相同的变量 j
作为 readCharArray
和 readValueArray
的数组索引,我认为这会在赋值过程中产生问题,因为它在每次赋值过程中都会递增,一些索引值将不会被使用。 readCharArray
和 readValueArray
.
分别使用两个变量
我正在学习操作数组。我将从文件读取的逐个元素数据存储到 main() 外部名为 readInput() 的函数中的 char 和 int 数组中。读取数据:
D E D D E E D E E E D E
21 32 35 59 58 16 11 29
我尝试调整两个数组的大小以使用 realloc 排除数组中的垃圾:我的问题:
在 main() 中打印 char 数组时,它包含正确的元素,但在数组末尾打印垃圾。我注意到它在 readInput() 中正确打印。我做错了什么?
在realloc前后的readInput()和main()中,int数组的文件读取的元素都是正确的,只是后面跟着垃圾。我做错了什么?
输出:
从 readInput() 打印 - 重新分配之前的字符数组:D E D D E E E D E E E D E
从 readInput() 打印 - 重新分配之前的 Int 数组:21 32 35 59 58 16 11 29 -8421 50451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -8421504 51 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451
从 readInput() 打印 - 重新分配后的字符数组:D E D D E E E D E E E D E
从 readInput() 打印 - Int After realloc:21 32 35 59 58 16 11 29 -336860 19 -842150451 739749649 37763 4849560 4849264 -842150451 -842150451 -842150451 - 842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842
从 main() 打印 - 字符数组(重新分配后): D E D D E E D E E E D E ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ² ² ² ` ² w ³ É · y É V t ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ = ²= ²
Print from main() - Int Array (after realloc): 21 32 35 59 58 16 11 29 -33686019 -842150451 874388096 31426 6946712 6946416 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 继续
节目背景: 读取的数据存储在 main() 外部的函数中,名为 readInput(),char by char/int by int 分别为 char 和 int 数组,它们通过 main() 中的 malloc 声明和初始大小。
在数组中存储数据后,我需要将数组的大小调整为文件中读取的数据的大小。
最后,为了验证 main 也可以访问数组,在 main() 和 readInput() 中分别写入 char 和 int 数组。
感谢您的帮助。 编辑更正的工作代码,谢谢!
#include <stdio.h>
#include <ctype.h>
#include <string.h>
//prototypes
void openFile(char *fileNames, FILE **inputFilePointer);
void closeFile(FILE **inputFilePointer);
void readInput(char *choiceArray, int *valueArray, int *charArraySize, int *intArraySize, FILE **inputFilePointer);
void memCharReallocation(char **choiceArray, int requiredArraySize);//resize char array to what's actually required after reading the file
void memIntReallocation(int **valueArray, int intSize);//resize int array to what's actually required after reading the file
void main()
{
char *charArray =NULL;
int *valueArray;
int inputSize;
int charInputSize = 0;//size of elements read from file
int intInputSize = 0;//size of elements read from file
//file read/write variables
FILE *iFilePointer;//file pointer
char *filename = "inputFileTest.txt";
//open and read Files
openFile(filename, &iFilePointer);
//initial mem allocation to size char and int array
valueArray = (int*)malloc(sizeof(int) * 100);
if (valueArray == NULL)
{
printf("\nCould not allocate memory, exiting.\n");
exit(1);
}
charArray = (char*)malloc(sizeof(char) * 100);
if (charArray == NULL)
{
printf("\nCould not allocate memory, exiting.\n");
exit(1);
}
//read file and allocate to array
readInput(charArray, valueArray, &charInputSize, &intInputSize, &iFilePointer);
//print char array: Test I can read it here too
printf("\nPrint from main() - Char Array: ");
for (int j = 0; j<charInputSize; j++)
{
printf("%c ", charArray[j]);
}
//Print int array
printf("\nPrint from main() - Int Array: ");
for (int j = 0; j<intInputSize; j++)
{
printf("%d ", valueArray[j]);
}
}
//read data from file
void readInput(char *readCharArray, int *readValueArray, int *charArraySize, int *intArraySize, FILE **inputFilePointer)
{
int i, j = 0;//loop variables
char *pbuffer = NULL;//buffer to read input file
int bufferSize = 200;//max initial size for buffer
char *token = NULL;////tonize
char ch = NULL;//convert string char to char
int readingChar = 0;//flag we are reading char from file
//alloc memory to pbuffer
pbuffer = (char*)malloc(sizeof(char)*bufferSize);
if (pbuffer == NULL)
{
printf("\nCould not allocate memory, exiting.\n");
exit(1);
}
printf("Read Input From File: \n");
//store each element from file in struct variable
while (fgets(pbuffer, bufferSize, *inputFilePointer) != NULL)//read each line from file
{
j = 0;//reset array to subscript zero on each pass
//tokenize file data
for (token = strtok(pbuffer, " "); token != NULL; token = strtok(NULL, " "))
{
//char token
if (isalpha(token[0]))
{
ch = token[0];
readCharArray[j++] = ch;
readingChar = 1;//flag we are reading char from file to get length of array excl array garbage
}
//int token
else if (isdigit(token[0]))
{
readValueArray[j++] = atoi(token);
(*intArraySize)++;
}
else
{
printf("\nCan't read file\n");
exit(1);
}
}
if (readingChar)
{
readCharArray[j] = '[=10=]';//remove excess cells on array
*charArraySize = strlen(readCharArray);//size of array
readingChar = 0;//end of reading char from file
}
}
//print char array: Test 1
printf("\nPrint from readInput() - Char Array before realloc: ");
for (int j = 0; j < *charArraySize; j++)
{
printf("%c ", readCharArray[j]);
}
//Print int array
printf("\nPrint from readInput() - Int Array before realloc: ");
for (int j = 0; j < *intArraySize; j++)
{
printf("%d ", readValueArray[j]);
}
memCharReallocation(&readCharArray, charArraySize);
memIntReallocation(&readValueArray, intArraySize);
printf("\nPrint from readInput() - Char Array after realloc: ");
for (int j = 0; j < *charArraySize; j++)
{
printf("%c ", readCharArray[j]);
}
printf("\nPrint from readInput() - Int After after realloc:");
for (int j = 0; j < *intArraySize; j++)
{
printf("%d ", readValueArray[j]);
}
}
void memCharReallocation(char **charArray, int requiredArraySize)//resize int array to what's actually required after reading the file
{
char *ptempArray = NULL;
ptempArray = (char*)realloc(*charArray, requiredArraySize * sizeof(char*));
if (ptempArray == NULL)
{
printf("Could not allocate memory, exiting");
exit(1);
}
else
*charArray = ptempArray;
if (ptempArray != *charArray)
free(ptempArray);
}
void memIntReallocation(int **valueArray, int intSize)//resize int array to what's actually required after reading the file
{
int *ptempArray = NULL;
ptempArray = (int*)realloc(*valueArray, intSize* sizeof(int*));
if (ptempArray == NULL)
{
printf("Could not allocate memory, exiting");
exit(1);
}
else
*valueArray = ptempArray;
if (ptempArray != *valueArray)
free(ptempArray);
}
void openFile(char *fileNames, FILE **inputFilePointer)
{
printf("\n\n");
//open files and error mssg
if ((*inputFilePointer = fopen(fileNames, "r")) == NULL) {
printf("Can't open input file %s\n", fileNames[1]);
exit(1);
}
}
void closeFile(FILE **inputFilePointer)
{
//close files
fclose(*inputFilePointer);
}
首先,警告是不容忽视的。
void main(char *argv) { ... argv = ...;
应该提出一个(CLang 甚至给出错误!)因为它不符合 C。它应该是:
int main() {
...
char *filename = ...;
如果不使用 argv,请不要声明它,并避免将 argv
用于命令行参数以外的任何其他内容。
下一步:for (int j = 0; j < charArray!=NULL; j++)
也应该发出大量警告。您首先比较 j
和 charArray
(已经是未定义的行为)。看到结果后,j < charArray
恰好为真(C 中的值为 1),您将其与 void *
的 NULL 进行比较! 1 != 0
永远是真的,你会得到一个永无止境的循环。
for (int j = 0; j < charSize || readValueArray[j] != NULL; j++)
也应该发出警告:readValueArray[j]
是一个 int
而 NULL
是一个 void *
。另外,测试readValueArray[j]
到0
是没有用的,因为你从来没有初始化分配的内存。
最终调整大小不会从数组中删除垃圾它会在内存中某处重新分配具有要求大小的数组,如果您访问分配的内存,您只需调用未定义的行为。 C 中无法知道数组的大小,关心它是程序员的工作。
所以你有两种可能的方法:
要么将数组的实际大小作为
readInput
的(输出)参数传递:void readInput(char *choiceArray, int *valueArray, FILE **inputFilePointer, int *choiceArraySize, int *valueArraySize)
或使用特殊值(例如 0)作为结束标记。
并且请注意警告!
在while (fgets(pbuffer, bufferSize, *inputFilePointer) != NULL)
的正文中
您使用相同的变量 j
作为 readCharArray
和 readValueArray
的数组索引,我认为这会在赋值过程中产生问题,因为它在每次赋值过程中都会递增,一些索引值将不会被使用。 readCharArray
和 readValueArray
.