从C

时间:2015-10-07 16:54:19

标签: c arrays fgets scanf

我正在尝试创建一个程序来从文件中读取2D数组,然后将其打印出来。

设置文件,以便第一行具有行数,然后是列数。之后绘制数组。一个例子如下:

3 5
10.4 15.1 18.5 13.3 20.8
76.5 55.3 94.0 48.5 60.3
2.4 4.6 3.5 4.6 8.9

我的问题是我只知道如何使用fgets和sscanf读取每一行的第一个元素,因此忽略以下数字。

#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[]){

FILE* f = fopen("plottestdata", "r");
char size[20];
int height, width,ii=0,cc,jj,kk;
float array[100][100];
char horiz[500];

if(fgets(size, 20, f)!= NULL){

    sscanf(size,"%d %d", &height, &width);
    printf("%d %d\n",height, width);
}
while(fgets(horiz, 500, f)!=NULL)
{

    if(ii<height)
    {
        for(cc=0;cc<width;cc++)
        {
        sscanf(horiz, "%f", &array[ii][cc]);
        }
    ii++;
    }
}
for(jj=0;jj<width;jj++)
    {
        for(kk=0;kk<height;kk++)
        {
        printf("%f ", array[jj][kk]);
        }
    }
fclose(f);
return 0;
}

这给了我多次重复每行第一个元素的输出,我理解为什么但不确定如何解决它。它正在读取的文件实际上是一个20x20阵列,尽管它的格式与示例相同。

另外,为了试图缩短一个长问题,我省略了我的错误检查。

4 个答案:

答案 0 :(得分:1)

我无法拒绝调整和简化您的代码,它非常接近,以避免使用fscanf并使用#include <stdio.h> #include <stdlib.h> #define MWIDTH 100 #define MHEIGHT 100 int main(void){ FILE* f; int height, width, ii, jj; float array[MHEIGHT][MWIDTH]; if((f = fopen("plottestdata.txt", "r")) == NULL) exit(1); if(fscanf(f, "%d%d", &height, &width) != 2) exit(1); if (height < 1 || height > MHEIGHT || width < 1 || width > MWIDTH) exit(1); for(jj=0; jj<height; jj++) for(ii=0; ii<width; ii++) if(fscanf(f, "%f", &array[jj][ii]) != 1) exit(1); fclose(f); for(jj=0; jj<height; jj++){ for(ii=0; ii<width; ii++) printf ("%10.1f", array[jj][ii]); printf("\n"); } return 0; } 直接读取值。加上基本的错误检查。

  10.4      15.1      18.5      13.3      20.8
  76.5      55.3      94.0      48.5      60.3
   2.4       4.6       3.5       4.6       8.9

节目输出:

SingleContinuousDistribution

答案 1 :(得分:1)

#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[]){
    FILE* f = fopen("plottestdata", "r");
    char size[20];
    int height, width,ii=0,cc,jj,kk;
    char horiz[500];

    if(fgets(size, 500, f)!= NULL){

    sscanf(size,"%d %d", &height, &width);
    printf("%d %d\n",height, width);
    }
    float array[height][width];
    while(fgets(horiz, 500, f)!=NULL)
    {

    if(ii<height)
    {
         sscanf(horiz, "%f %f %f %f %f", &array[ii][0],&array[ii][1],
                    &array[ii][2],
                    &array[ii][3],
                    &array[ii][4]);       
              ii++;
        }
    }
    for(ii=0;ii<height;ii++)
    {
        for(kk=0;kk<width;kk++)
        {
            printf("%.2f ", array[ii][kk]);
        }
        printf("\n");
    }
    fclose(f);
    return 0;
}

答案 2 :(得分:0)

为什么不从stdin读取,而不是从具有硬编码文件名的文件中读取?您可以使用fgets(size, sizeof size, stdin)来读取带尺寸的第一行。

然后使用scanf(" %f", &array[ii][cc)逐个读取值。

请务必测试scanf是否返回1,否则添加一些错误处理。

答案 3 :(得分:0)

正如您已经发现的那样,您需要在扫描上一个值后扫描下一个值。不幸的是,Address没有流的属性;它没有记住它的最后位置,如果你传递相同的字符串,它总是重新开始。

Fortunalely,还有很多其他方法可以实现顺序扫描。

标记化您可以标记您的行forst,然后将每个标记解析为浮点数。来自sscanf的{​​{1}}和来自strtok的{​​{1}}将为您完成这项工作。

string.h>

跟踪尾部我 strtod还有另外一个特征:当您提供指向char指针的指针时,它会告诉您解析停止的确切位置。 <stdlib.h>也会跳过领先的空白区域。您可以使用这两个事实来解析由空格分隔的浮点数。

        char *token = strtok(horiz, " \t\n");

        for (cc = 0; cc < width; cc++) {
            if (token) {                
                array[ii][cc] = strtod(token, NULL);
                token = strtok(NULL, " \t\n");
            } else {
                array[ii][cc] = 0.0;
            }
        }

跟踪尾部II strtod有一种特殊格式,可以告诉您在整数中的某个点处已解析了多少个字符。以上内容可以使用strtod

编写
        char *p = horiz;

        for (cc = 0; cc < width; cc++) {
            char *tail;

            array[ii][cc] = strtod(p, &tail);
            p = tail;
        }

所有这些都适用于您的示例,但它们都没有进行正确的错误检查。第一个例子至少做了一个半心半意的尝试来捕捉一条线具有比矩阵具有列更少的令牌的情况。