繁体   English   中英

由于某个函数停止运行的C程序被调用?

[英]C program that stops running due to a function be called?

这可能很难解释。 我正在研究一个程序,该程序在其中包含数字的文件。 前两个数字是矩阵的尺寸,然后是列的尺寸。 其余的数字是矩阵的元素。 我遇到的麻烦是,在创建一个函数以给定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);

允许程序正常运行,但取消注释它们只会停止执行任何操作,在Eclipse中,控制台只是保持空白以运行某项或其他内容,并且我稍后将其终止,因为什么也没发生,甚至没有打印第一行。

这是一个正在读取的示例文件3 2 56 12 98 25 34.5 45

先感谢您

找到了解决方案,我不确定每个人是否都了解程序中到底发生了什么。 main根本不会运行,第一行不会打印任何内容。 解决方案是在第一个print语句之后使用fflush(stdout)。

尝试读取浮点数时,逐个字符地解析文件变得很复杂。 使用标准库提供的功能。

您的代码可能会产生未定义的行为,因为您无需检查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库提供的功能比尝试再次发明轮子要好。 您的代码复杂且难以阅读。

另请参阅为什么while(feof)总是错误的 使用fgets ,管理文件末尾更容易,因为由于I / O错误或文件到达EOF导致无法读取更多数据时, fgets返回NULL 这就是为什么上面的示例始终检查fgets的返回值的原因。 请注意我如何以scanf格式使用%n%n返回到目前为止已远离输入消耗的字符数,这在循环中使用sscanf时是一个很好的信息。 我还检查scanf是否不返回匹配元素的数量(请注意, %n不会增加匹配元素的数量)。 有关此的更多信息,请参见scanf文档

此循环可以永远运行:

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);
                }
            }
        }

找到了解决方案,我不确定每个人是否都了解程序中到底发生了什么。 main根本不会运行,第一行不会打印任何内容。 解决方案是在第一个print语句之后使用fflush(stdout)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM