【发布时间】:2021-11-08 13:50:03
【问题描述】:
我对 C 编程很陌生,我正在编写这个程序以读取文件并打印到自动对齐的表格中。一切正常,但我收到 Valgrind 警告,指出条件跳转或移动取决于未初始化的值。我还需要能够传入任何 .txt 文件,而不仅仅是特定的 .txt 文件。我知道我可以使用 argv 但不知道如何在函数中使用它而不是在 main 中调用它。
代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// constant to store the maximum size of the records that can be read from the file
enum
{
// update MAX_SIZE to if the number of rows is more than 1000
MAX_SIZE = 1024
};
// structure to store a record from the file
typedef struct
{
char define[20];
char octal[26];
char description[1000];
} Record;
// string to store the header of the table
char header1[20], header2[20], header3[20];
// function to read the file and return the maximum length of the descriptions read from the file
void readFile(Record rec[], int *size,int *length, int *length1, int *length2)
{
int i = 0;
int maxLength,maxLength1,maxLength2=0;
// open a file for input
FILE *fp = fopen("input2.txt", "r");
// check if the file opened successfully
if (fp == NULL)
{
printf("File could not be opened!");
exit(1);
}
// read the file
// first we read the header of each column from the file
fscanf(fp, "%s %s %s\n", header1, header2, header3);
// now we read each record from the file
while (fscanf(fp, "%20s ", rec[i].define) == 1)
{
fscanf(fp, "%20s '%[^']'", rec[i].octal, rec[i].description);
// find the length of the description and update the 'maxLength'
if(strlen(rec[i].description) > maxLength)
{
maxLength = strlen(rec[i].description);
}
else if(strlen(rec[i].octal) > maxLength1)
{
maxLength1 = strlen(rec[i].octal);
}
else if(strlen(rec[i].define) > maxLength2)
{
maxLength2 = strlen(rec[i].define);
}
// increment the value of i
i++;
}
printf(" Length: %d \n", maxLength);
// close the input file
fclose(fp);
// update the number of records read from the file
*size = i;
*length = maxLength;
*length1 = maxLength1;
*length2 = maxLength2;
}
void printTable(Record rec[], int size, int length, int length1, int length2)
{
if(length2 >= 15)
{
for (int i = 0; i < length+length1+length2+17; i++)
printf("-");
printf("\n| %-*s | %*s | %-*s |\n", length2,header1, length1, header2, length, header3);
for (int i = 0; i < length+length1+length2+17; i++)
printf("-");
printf("\n");
// print the table data
for (int i = 0; i < size; i++)
printf("| %-*s | %10s | %-*s |\n",length2, rec[i].define, rec[i].octal, length, rec[i].description);
// print the footer
for (int i = 0; i < length+length1+length2+17; i++)
printf("-");
printf("\n");
}
else
{
printf("length: %d \n", length2);
// print the header of the table
for (int i = 0; i < length+length1+length2+10; i++)
printf("-");
printf("\n| %-*s | %*s | %-*s |\n", length2,header1, length1, header2, length, header3);
for (int i = 0; i < length+length1+length2+10; i++)
printf("-");
printf("\n");
// print the table data
for (int i = 0; i < size; i++)
printf("| %-*s | %*s | %-*s |\n",length2, rec[i].define, length1, rec[i].octal, length, rec[i].description);
// print the footer
for (int i = 0; i < length+length1+length2+10; i++)
printf("-");
printf("\n");
}
}
// driver function
int main()
{
// create an array of recors of MAX_SIZE
Record recs[MAX_SIZE];
// initialize size of recs to zero
int size = 0;
int length=0;
int length1=0;
int length2=0;
// call readFile() function to read data from the file and update the size of recs
readFile(recs, &size,&length,&length1,&length2);
// call printTable() function to print the table in a well-formatted manner
printTable(recs, size, length,length1,length2);
return 0;
}
Valgrind 警告:
==1821== Memcheck, a memory error detector
==1821== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1821== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==1821== Command: ./main input2.txt
==1821==
==1821== Conditional jump or move depends on uninitialised value(s)
==1821== at 0x10896F: readFile (main.c:50)
==1821== by 0x108E17: main (main.c:147)
==1821==
==1821== Conditional jump or move depends on uninitialised value(s)
==1821== at 0x1089C2: readFile (main.c:54)
==1821== by 0x108E17: main (main.c:147)
【问题讨论】:
-
代码中另一个可能的疏忽是
maxLength被定义为int,但与size_t相比。最好也将size_t用于 maxLength 变量。 -
除了
maxLength和maxLength1没有被初始化并且是错误的类型以获取strlen()返回值size_t如@Cheatah 提到的那样,您可能仍然会看到此错误来自 valgrind,因为整个rec[i].description字段在被strlen()遍历之前没有在读取时初始化;如果是这种情况,您需要将main()中的Record recs[MAX_SIZE];更改为Record recs[MAX_SIZE] = {0};以初始化所有记录结构内存。