这可能很难解释。我正在开发一个程序,它接收一个包含数字的文件。前两个数字是矩阵行和列的维度。其余的数字是矩阵的元素。我遇到麻烦的是,在我创建了一个函数来读取给定c样式字符串中的数字后,程序停止执行任何操作。它编译并运行但没有做任何事情,甚至没有在main之后打印第一行。
proj2.c
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
float readNum(char* buffer, int *pos);
int main(){
char buffer[512];
printf("Enter File Name: ");
//char* fileName = fgets(buffer, sizeof(buffer), stdin);
FILE* file = fopen("matrix.txt", "r");
if(file == NULL){
printf("ERROR COULD NOT OPEN FILE\n");
exit(1);
}
int row = 0;
int col = 0;
int rowcheck = 0;
int colcheck = 0;
int matrixcheck = 0;
while(!feof(file)){
printf("HELLO");
if(fgets(buffer,sizeof(buffer),file) != NULL){
//position of current character
int pos = 0;
//current character
char current;
//loop to determine the dimensions of the matrix
if(colcheck == 0 && rowcheck == 0){
while(colcheck == 0 || rowcheck == 0){
//set current character
current = buffer[pos];
//determine if current character is a number and that the nex character is a space
//for single digit row dimensions
if(current >= '0' && current <= '9' && buffer[pos+1] == ' ' && rowcheck == 0){
row += current - '0';
rowcheck = 1;
}
//if not single digit row dimension add the current character times 10
//and repeat loop to obtain the second digit
else if (buffer[pos+1] >= '0' && buffer[pos+1] <= '9' && rowcheck == 0){
row += (current - '0') * 10;
}
//for columns check if current character is a number and if the next character is space or newline
//and that row has already been checked
else if(current >= '0' && current <= '9' && (buffer[pos+1] == ' ' || buffer[pos+1] == 10) && rowcheck == 1){
col += current - '0';
colcheck = 1;
}
//final check for if columns is double digit so check if next char is a number and that current char is
//not a space
else if(buffer[pos] != ' ' && buffer[pos+1] >= '0' && buffer[pos+1] <= '9' && rowcheck == 1){
col += (current - '0' ) * 10;
}
pos++;
printf("rows: %d cols: %d", row,col);
}
}
//condition to ensure columns and rows have been determined
else if(colcheck == 1 && rowcheck == 1){
//loop to find the elements of the matrix
while(matrixcheck == 0){
current = buffer[pos];
if(buffer[pos + 1] != 10){
if((current >= '0' && current <= '9') || current == '-' || current == '.'){
float num = readNum(buffer, &pos);
printf("number: %f", num);
}
}
}
}
}
}
fclose(file);
}
和readNum.c
#include <stdio.h>
#include <math.h>
float readNum(char* buffer,int *pos){
int negative = 1;
int y = 0;
float number = 0;
if(buffer[*pos] == '-'){
negative = -1;
(*pos)++;
}
while(buffer[*pos + y] >= '0' && buffer[*pos + y] <= '9'){
y++;
}
for(int z = 0; z < y; z++){
number += (buffer[*pos + z] - 48) * pow(10, y - z - 1);
}
*pos += y;
if(buffer[*pos] == '.'){
(*pos)++;
int d = 0;
while(buffer[*pos + d] >= '0' && buffer[*pos + d] <= '9'){
if(buffer[d + *pos] == '.'){
printf("ERROR: multiple decimals in an element");
}
d++;
}
for(int z = 0; z < d; z++){
number += (buffer[z + *pos] - '0') * pow(10, -z - 1);
}
pos += d;
}
return number * negative;
}
评论出行
float num = readNum(buffer, &pos);
printf("number: %f", num);
允许程序正常运行,但取消注释它只是停止做任何事情,在日食控制台只是保持空白运行的东西或其他我稍后终止它因为没有发生任何事情,甚至第一行都没有打印
这是一个正在读取的示例文件 3 2 56 12 98 25 34.5 45
提前谢谢
已找到解决方案,我不确定每个人是否都明白程序中究竟发生了什么。 main根本不会运行,第一行不会打印任何东西。对此的解决方案是在第一个打印语句之后使用fflush(stdout)。
答案 0 :(得分:1)
逐字符解析文件是一种复杂的方式 试图阅读花车。使用标准库提供的功能。
您的代码可能会产生未定义的行为,因为您不检查边界
buffer
的例如:
if(current >= '0' && current <= '9' && buffer[pos+1] == ' ' && rowcheck == 0){
row += current - '0';
rowcheck = 1;
}
您永远不会检查您是否读取'\0'
- 终止字节并继续递增
pos
,buffer[pos+1]
可能超出限制。我也不明白
你是如何解析尺寸的。这就是我告诉你的原因,不要重新发明
轮子,使用你可以使用的工具。
你说尺寸在第一行,那么你可以得到 通过这样做维度:
char buffer[512];
if(fgets(buffer, sizeof buffer, file) == NULL)
{
fprintf(stderr, "File is empty\n");
flcose(file);
return 1;
}
size_t cols,rows;
if(fscanf("%zu %zu", &rows, &cols) != 2)
{
fprintf(stderr, "Invalid file format, cannot get columns and rows\n");
fclose(file);
return 1;
}
if(rows == 0 || cols == 0)
{
fprintf(stderr, "Invalid dimension %zux%zu\n", rows, cols);
fclose(file);
return 1;
}
现在,您可以像这样解析文件:
float matrix[rows][cols] = { 0 };
for(size_t i = 0; i < rows; ++i)
{
if(fgets(buffer, sizeof buffer, file) == NULL)
{
fprintf(stderr, "End of file reached before filling matrix\n");
fclose(file);
return 1;
}
int pos;
char *scan = buffer;
for(size_t j = 0; j < cols; ++j)
{
if(sscanf(scan, "%f%n", matrix[i] + j, &pos) != 1)
{
fprintf(stderr, "Invalid format at line %zu\n", i+2);
break; // continue parsing with the next line
}
scan += pos;
}
}
fclose(file);
printf("matrix[%zu][%zu] = %f\n", rows/2, cols/2, matrix[rows/2][cols/row]);
此代码更健壮,因为它会检查函数是否正常工作 意。如果在填充矩阵之前无法读取更多行,那么您 可以返回错误消息并结束程序。如果线条没有 正确的格式,我忽略该行,同时行也填充0 打印错误消息。如果行数多于行数,则忽略它们 你不会溢出缓冲区。意图也更明确 我更容易理解我在做什么。
正如我在开头说的那样,使用标准C提供的功能 图书馆比试图再次发明轮子更好。你的代码是 复杂而难以阅读。另见why is while(feof)
always wrong。管理结束更容易
使用fgets
时的文件,因为fgets
在没有更多数据时会返回NULL
由于I / O错误或文件达到EOF而被读取。那是
为什么我上面的例子总是检查fgets
的返回值。请注意我的使用方法
%n
格式的scanf
:%n
返回消耗的字符数
远离输入,这在循环中使用sscanf
时是一个很好的信息。我也
检查scanf
是否未返回匹配元素的数量(请注意%n
不会增加匹配元素的数量)。有关的更多信息
这会看到documentation of scanf
。
答案 1 :(得分:0)
这个循环可以永远运行:
while(buffer[*pos] >= '0' && buffer[*pos] <= '9'){
y++;
}
我们如何摆脱这种循环?:
while(matrixcheck == 0){
current = buffer[pos];
if(buffer[pos + 1] != 10){
if((current >= '0' && current <= '9') || current == '-' || current == '.'){
float num = readNum(buffer, &pos);
printf("number: %f", num);
}
}
}
答案 2 :(得分:0)
已找到解决方案,我不确定每个人是否都明白程序中究竟发生了什么。 main根本不会运行,第一行不会打印任何东西。对此的解决方案是在第一个打印语句之后使用fflush(stdout)。