c - 从文件中读取 int 和 char 数组,然后调整数组大小

标签 c arrays windows malloc realloc

我正在学习操作数组。我将从文件读取的逐个元素数据存储到 main() 外部名为 readInput() 的函数中的 char 和 int 数组中。数据读取:

D E D D E 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 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 E D E E E D E ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ² ² ² ` ² w ³ É·yÉVt══════════════════════════════════════════════²

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] = '\0';//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++)还应该提出大量警告。你先比较jcharArray (已经是未定义的行为)。看到结果后,j < charArray恰好为真(C 中的值为 1),您将其与 NULL 进行比较,后者是 void * ! 1 != 0始终为真,您将得到一个永无止境的循环。

for (int j = 0; j < charSize || readValueArray[j] != NULL; j++)还应该发出警告:readValueArray[j]是一个 intNULLvoid * .另外就是没用测试readValueArray[j]0因为您从未初始化分配的内存。

最终调整大小不会从数组中移除垃圾,它会在内存中某处重新分配具有要求大小的数组,如果您访问分配的内存,您只需调用未定义的行为。在 C 中无法知道数组的大小,程序员的工作就是关心它。

所以这里有 2 种可能的方法:

  • 将数组的实际大小作为 readInput 的(输出)参数传递:

    void readInput(char *choiceArray, int *valueArray, FILE **inputFilePointer,
        int *choiceArraySize, int *valueArraySize)
    
  • 或使用特殊值(例如 0)作为结束标记。

注意警告!

关于c - 从文件中读取 int 和 char 数组,然后调整数组大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47787453/

相关文章:

c - 字符串在 Visual Studio 和 gcc 中的打印方式不同

c - C中链表的搜索算法

android - 如何在 Android 应用程序中解析未命名的 JSON 数组

c - 将二进制文件加载到数组中

windows - 无法在 visual studio 11 中构建项目

第三方应用程序的 Windows 集中配置?

windows - 比较windows jq中的 'YYYY-mm-dd HH:MM:SS'格式时间戳

c - ollydbg 中有很多 'printf',但 a.exe 中只有一个 'printf'

c - 为什么 pthread_create 函数将线程函数名作为参数而不是调用它?

javascript - jQuery.parseJSON 无序数组