这么多的问题和误解;很难提供有用的建议。
据我了解,您的意思是读取一系列矩阵的维度,每行输入有两个数字,第 N 行中的第二个数字应该与第 N+1 行中的第一个数字相同。在到达 EOF 之前,您不知道会有多少行输入。一般来说,数字应该都是一位或两位数(不能更长)。数组的实际数据存储在其他地方,或生成——它不在此代码中处理。
你的代码是:
int *p,i=0;
char str[3],*extra;
FILE * file;
file = fopen("D:/Dump/testcases/matrix.txt", "r");
if (file) {
while (fscanf(file, "%s", str)!=EOF){
switch(i){
case 0: p=(int *)malloc(sizeof(int));
*(p)=atoi(str);
break;
default: *(p+i)=(int)malloc(sizeof(int));
*(p+i)=atoi(str);
break;
}
i++;
}
}
- 文件打开正常;你没有显示关闭,但这是一个小问题。
- 您不限制读取的字符串的大小;您可以使用它
%2s
来确保不会溢出您使用的(相当短的)字符串。
- 您没有检查
fscanf()
实际阅读了 1 个项目。有了字符串就可以了。如果您直接读取整数,那就不行了。您可以转换 0 个整数,这既不是 EOF 也不是 1。您应该使用while (fscanf(file, "%2s", str) == 1)
.
- 没有非常明显的理由不
fscanf()
为您进行转换。
- OTOH,您也不能
fscanf()
在一行中强制要求(仅)两个数字;它会很高兴将所有数字放在一行上,或者每个数字单独放在一行上,每行之间有 2 个空白行包含数字。
这switch
有点奇怪。该default
子句可能应该使用realloc()
而不是malloc()
,并且在中的转换default
存在严重问题。内存分配方案作为一个整体是有很大缺陷的,这是你知道的,因为你问了这个问题。你可以通过写来拯救它:
default:
p = (int *)realloc(p, (i+1) * sizeof(int));
p[i] = atoi(str); /* Or *(p+i) if you prefer */
break;
总的来说,我认为您需要考虑一次读取一行 ( fgets()
),然后使用sscanf()
. 您可能应该考虑一次为数组分配两个整数。
int *p = 0;
int i = 0;
FILE *file = fopen("D:/Dump/testcases/matrix.txt", "r");
if (file != 0)
{
char buffer[4096];
while (fgets(buffer, sizeof(buffer), file) != 0)
{
int d1, d2;
char c;
if (sscanf(buffer, "%d%d%c", &d1, &d2, &c) != 3 || c != '\n')
{
fprintf(stderr, "Badly formatted line: %s", buffer);
break;
}
void *space;
if (i == 0)
space = malloc(2 * (i + 1) * sizeof(int));
else
space = realloc(p, 2 * (i + 1) * sizeof(int));
if (space == 0)
{
fprintf(stderr, "Memory allocation failed (%d bytes)\n", 2 * (i + 1) * sizeof(int));
break;
}
p = (int *)space;
p[2*i + 0] = d1;
p[2*i + 1] = d2;
i++;
}
fclose(file);
}
/* i is the number of lines read (sets of matrix dimensions) */
/* p is the pointer to 2*i array dimensions */
/* ...Use i and p... */
free(p);
代码不会检查一行上的第二个维度是否与下一行上的第一个维度相同。它不检查 1 位或 2 位的正整数(基本上是 1..99);它允许更大的值、零和负值。(测试c == '\n'
确保第二个数字后有换行符;不允许出现尾随空格等。)
鉴于p
(现在)已初始化为 0(空指针),您可以不使用 themalloc()
并简单地realloc()
无条件使用。大多数人不喜欢这样做,但它避免了重复。