如何仅使用1D数组从字符串中提取间隔数字到浮点数组?

时间:2017-02-12 08:28:09

标签: c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 20

int main()
{
  int num;
  float val[SIZE];
  int size_r;
  int size_j;
  int size;
  int i=0;
  int j;
  char mat[SIZE];
  int key;

  printf("Enter size of rows: ");
  scanf("%i",&size_r);
  getchar();
  printf("Enter size of columns: ");
  scanf("%i",&size_j);
  getchar();
  size=size_r*size_j;

  printf("Please input matrix (one row at a time and spaced numbers): ");
  for (num=0;num<size_r;num++)
  {
    fgets(mat,SIZE,stdin);
    for (num=0;num<SIZE;num++)
    {
      if (mat[num]==' ')
      {
         val[i]=atof(mat);
         i++;
      }
    }
  }
  for (num=0;num<SIZE;num++)
  {
    printf("%.2f\t",val[num]);
  }

我已初始化了一些我需要的变量,但由于以下问题,代码尚未完成。例如,当我输入'12 23 34'时,我只能提取12.00而其他每个元素都填充0.00。有什么帮助吗?

2 个答案:

答案 0 :(得分:0)

描述有点令人困惑,所以我会指出一些我在代码中清楚看到的问题。

以下是atof如何运作的定义:

“解析C字符串str,将其内容解释为浮点数,并将其值作为double返回。

该函数首先丢弃尽可能多的空白字符(如在isspace中),直到找到第一个非空白字符。然后,从这个字符开始,根据类似于浮点文字(见下文)的语法,获取尽可能多的有效字符,并将它们解释为数值。最后一个有效字符后的其余字符串将被忽略,并且不会影响此函数的行为。 “

理解定义的最后一句是理解问题的关键。

每次获得输出12.00的原因是由于以下原因: 当你到达第一个空格并调用atof()时,atof函数会看到字符:12+空格,因此12被提取并转换为Float。

随后您找到一个空格时,该函数将看到12(空格)23(空格)和(23空格)段被忽略。循环atof的每次后续迭代将仅返回12.0000。

要解决此问题,您需要定义一个最初设置为mat的第一个数字的char指针,chrPtr = mat。随后当你找到一个空格时,你在char ptr = val [i] = atof(chrNum)上执行atof;

然后,您需要将char ptr碰撞到下一个数字字符前面的空格 chrNum = strchr(mat,'');

当你到达最后一个号码时你也必须要小心,因为没有更多的空格,但回车'\ n'。这种情况也必须处理。

答案 1 :(得分:0)

如果我理解你的要求,有几个方面存在明显的混淆。第一个围绕SIZEsize。如果您同时要求size_rsize_j,那么SIZE只是您检查的数组限制,以查看您的val[SIZE]是否可以保留size_r * size_j元素。在这种情况下,您不能将SIZE用作迭代限制。

但是,如果您只输入一个值(例如size_rsize_j,而不是两者),则可以使用SIZE来修复未输入的值。 SIZE / size_r来修复size_j)您当然还需要确保整数除法不会导致修复比元素更大的尺寸。

接下来,没有魔法模拟具有一维数组值的二维矩阵。您可以找到许多文献,讨论用于从一维数组索引二维矩阵的 stride (或列数)。您可以按如下方式处理模拟2D数组的数组索引(打印示例):

for (i = 0; i < size_r; i++) {   /* output your values in 2D format */
    for (j = 0; j < size_j; j++)
        printf ("%7.2f", val[i * size_j + j]);
    putchar ('\n');    /* for your newline */
}

基本上,您正在模拟以下2D数组:

array[i * size_j][j];

将所有部分组合在一起,并注意在转换为strings之前无需填充float数组,您可以执行以下操作:

#include <stdio.h>

#define SIZE 20

int main (void)
{
    int size_r, size_j, size, i, j;
    float val[SIZE];

    printf ("Enter size of rows: ");
    if (scanf ("%d", &size_r) != 1) {   /* always validate input */
        fprintf (stderr, "error: invalid conversion for rows.\n");
        return 1;
    }

    printf ("Enter size of columns: ");
    if (scanf ("%d", &size_j) != 1) {   /* ditto */
        fprintf (stderr, "error: invalid conversion for rows.\n");
        return 1;
    }

    size = size_r * size_j; /* compute the requires size of array */

    /* you can only use SIZE as a limit unless you only ask for a row   */
    if (size > SIZE) {  /* or col, and set the other with e.g. SIZE/row */
        fprintf (stderr, "error: SIZE (%d) insufficient to hold "
                            "size (%d) elements.\n", SIZE, size);
        return 1;
    }

    printf ("Please input matrix (one row at a time and spaced numbers): ");
    for (i = 0; i < size_r; i++)     /* your indexing is: array[i*size_j][j] */
        for (j = 0; j < size_j; j++)
            if (scanf ("%f", &val[i * size_j + j]) != 1) {
                fprintf (stderr, "error: conversion for val[%d][%d] failed.\n",
                        i * size_j, j);
                return 1;
            }
    putchar ('\n');     /* just to make it look nice piping input to it */

    for (i = 0; i < size_r; i++) {   /* output your values in 2D format */
        for (j = 0; j < size_j; j++)
            printf ("%7.2f", val[i * size_j + j]);
        putchar ('\n');
    }

    return 0;
}

示例使用/输出

指定5-rows4-columns,并输入值1.0 ... 20.0,您可以从1D数组5x4模拟一个漂亮的val矩阵:

$ echo 5 4 {1..20}.0 | ./bin/spcarrayfloats
Enter size of rows: Enter size of columns: Please input matrix <snip>:
   1.00   2.00   3.00   4.00
   5.00   6.00   7.00   8.00
   9.00  10.00  11.00  12.00
  13.00  14.00  15.00  16.00
  17.00  18.00  19.00  20.00

最后,总是,始终检查您用于输入用户输入的任何函数的返回,然后验证输入的值在您的可用范围内。 (对于你所知道的一切,猫可能正踩在键盘上)。如果您始终验证输入(并在启用警告的情况下进行编译,例如-Wall -Wextra),您会发现调试时间大大缩短。

查看所有答案,如果我不确切地了解您的要求,请在评论中告诉我。