繁体   English   中英

如何从文本文件中读取虚数数据,使用 C

[英]How to read imaginary data from text file, with C

我无法从文本文件中读取虚数数据。 这是 my.txt 文件

abc.txt

0.2e-3+0.3*I   0.1+0.1*I
0.3+0.1*I      0.1+0.4*I

我想将这些数据读入矩阵并打印出来。

我在这里这里使用C++找到了解决方案。 我不知道如何在 C 中做同样的事情。

我能够读取十进制和 integer 数据 in.txt 并打印它们。 我还可以使用complex.h header 打印在声明中初始化的虚数数据。这是我编写的程序

#include<stdio.h>
#include<stdlib.h>
#include<complex.h>
#include<math.h>
int M,N,i,j,k,l,p,q;
int b[2];
int main(void)
{
    FILE* ptr = fopen("abc.txt", "r");
        if (ptr == NULL) {
            printf("no such file.");
            return 0;
        }
    long double d=0.2e-3+0.3*I;
    long double c=0.0000000600415046630252;
    double matrixA[2][2];
    for(i=0;i<2; i++)
        for(j=0;j<2; j++)
            fscanf(ptr,"%lf+i%lf\n", creal(&matrixA[i][j]), cimag(&matrixA[i][j])); 
            //fscanf(ptr, "%lf", &matrixA[i][j]) for reading non-imainary data, It worked. 

    for(i=0;i<2; i++)
            for(j=0;j<2; j++)
                printf("%f+i%f\n", creal(matrixA[i][j]), cimag(matrixA[i][j]));
              //printf("%lf\n", matrixA[i][j]);  for printing non-imainary data, It worked. 

    printf("%f+i%f\n", creal(d), cimag(d));
    printf("%Lg\n",c);

    fclose(ptr);

    return 0;
}

但是我想从文本中读取它,因为我有一个更大的数组,由于它的大小,我无法在声明时对其进行初始化。

您的代码有两个主要问题:

  • 您需要将complex添加到包含复杂值的变量中。
  • scanf()需要指向对象的指针以在其中存储扫描值。 但是creal()返回一个值,该值是从其参数的内容中复制而来的。 它既不是指针,也不能得到复数参数对应部分的地址。

因此,您需要为接收扫描值的scanf()提供临时对象。 成功扫描后,将这些值组合成一个复值并分配给索引矩阵单元格。

不会导致核心问题的次要问题是:

  • 给定的源是用不需要的#include s、未使用的变量、全局变量和常量实验“扩充”的。 我将它们全部移除以查看真实的东西。

  • 说明符"%f" (和许多其他说明符一样)允许scanf()跳过空格,如空格、制表符、换行符等。 提供一个"\n"通常比人们预期的危害更大。

    我保留了"*I"来检查正确的格式。 但是,只有在下次调用scanf()无法扫描下一个数字时才会发现错误。

  • 您需要始终检查scanf()的返回值。 它返回成功的转换次数。

  • 让编译器计算数组中元素的数量是一个常见的好习惯。 将总大小除以元素的大小。

    哦, sizeof是一个运算符,而不是 function。

  • 最好向调用者返回符号值,而不是幻数。 幸运的是,标准库定义了这些EXIT_...宏。

  • 这些标志已由scanf()正确处理。 无需多说。 但是对于带有printf()的漂亮 output ,您使用"+"作为标志始终将 output 标记为一个标志。

  • 由于符号现在直接放在数字之前,我将乘以I (如果需要,可以将其更改为小写)移到虚部的后面。 这也匹配输入格式。

  • 错误 output 是通过stderr而不是stdout完成的。 例如,这使您能够将标准 output 重定向到 pipe 或文件,而不会遗漏潜在错误。 您还可以将错误重定向到其他地方。 这是一个广为人知和赞赏的标准。

这是一个可能的解决方案:

#include <stdio.h>
#include <stdlib.h>
#include <complex.h>

int main(void)
{
    FILE* ptr = fopen("abc.txt", "r");
    if (ptr == NULL) {
        perror("\"abc.txt\"");
        return EXIT_FAILURE;
    }

    double complex matrixA[2][2];

    for (size_t i = 0; i < sizeof matrixA / sizeof matrixA[0]; i++)
        for (size_t j = 0; j < sizeof matrixA[0] / sizeof matrixA[0][0]; j++) {
            double real;
            double imag;
            if (fscanf(ptr, "%lf%lf*I", &real, &imag) != 2) {
                fclose(ptr);
                fprintf(stderr, "Wrong input format\n");
                return EXIT_FAILURE;
            }
            matrixA[i][j] = real + imag * I;
        }

    fclose(ptr);

    for (size_t i = 0; i < sizeof matrixA / sizeof matrixA[0]; i++)
        for (size_t j = 0; j < sizeof matrixA[0] / sizeof matrixA[0][0]; j++)
            printf("%+f%+f*I\n", creal(matrixA[i][j]), cimag(matrixA[i][j]));
    return EXIT_SUCCESS;
}

这是一个使用scanf()和示例中显示的格式的简单解决方案。 它以与读取它们相同的格式写入值——程序可以扫描 output 作为输入。

/* SO 7438-4793 */
#include <stdio.h>

static int read_complex(FILE *fp, double *r, double *i)
{
    int offset = 0;
    char sign[2];
    if (fscanf(fp, "%lg%[-+]%lg*%*[iI]%n", r, sign, i, &offset) != 3 || offset == 0)
        return EOF;
    if (sign[0] == '-')
        *i = -*i;
    return 0;
}

int main(void)
{
    double r;
    double i;

    while (read_complex(stdin, &r, &i) == 0)
        printf("%g%+g*I\n", r, i);

    return 0;
}

示例输入:

0.2e-3+0.3*I   0.1+0.1*I
0.3+0.1*I      0.1+0.4*I
-1.2-3.6*I     -6.02214076e23-6.62607015E-34*I

Output 来自示例输入:

0.0002+0.3*I
0.1+0.1*I
0.3+0.1*I
0.1+0.4*I
-1.2-3.6*I
-6.02214e+23-6.62607e-34*I

大指数末尾的数字是阿伏伽德罗数和普朗克常数。

该格式与您可以使用scanf()制作的一样严格,但是,尽管它需要在实部和虚部之间有一个符号( +- )并且要求*I紧跟在虚部之后(和如果缺少*I ,转换将失败),并接受iI来表示虚数:

  • 它不会停止具有第二个符号的虚数(因此它将读取诸如“ -6+-4*I ”的值)。
  • 它不会停止在强制性符号之后出现空格(因此它会读取诸如“ -6+ 24*I ”之类的值。
  • 它不会阻止实部位于一行而虚部位于下一行。
  • 它不会正确处理纯实数或纯虚数。

scanf()函数对空白非常灵活,很难阻止它们接受空白。 它需要一个自定义解析器来防止不需要的空格。 您可以通过分别读取数字和标记作为字符串,然后验证没有空格等来做到这一点。 这可能是最好的处理方式。 在确保没有嵌入的空格但格式正确后,您将使用sscanf()转换读取的字符串。


我不知道你用的是哪个 IDE 作为 C,所以我不明白这个./testprog <test.data

我还没有找到一个不会让我发疯的 IDE。 我使用 Unix shell 在终端 window 中运行。假设您的程序名称是testprog并且数据文件是test.data ,键入./testprog < test.data运行程序并将test.data的内容作为其标准输入. 在 Windows 上,这将是命令 window(我认为 PowerShell 的工作方式大致相同)。

我使用fgets读取文本文件的每一行。 虽然我知道sscanf的功能,但我不知道如何解析整行,每行大约有 23 个元素。 如果一行中的元素数量很少,我知道如何解析它。 你能帮我一下吗?

正如我在评论中指出的那样,SO Q&A How to use sscanf() in loops? 解释了如何使用sscanf()从一行中读取多个条目。 在这种情况下,您将需要从一行中读取多个复数。 这是一些代码,显示它在工作中。 它使用 POSIX getline() function 来读取任意长的行。 如果它对您不可用,您可以改用fgets() ,但您需要预先分配一个足够大的行缓冲区。

#include <stdio.h>
#include <stdlib.h>
#include <complex.h>

#ifndef CMPLX
#define CMPLX(r, i)     ((double complex)((double)(r) + I * (double)(i)))
#endif

static size_t scan_multi_complex(const char *string, size_t nvalues,
                                 complex double *v, const char **eoc)
{
    size_t nread = 0;
    const char *buffer = string;
    while (nread < nvalues)
    {
        int offset = 0;
        char sign[2];
        double r, i;
        if (sscanf(buffer, "%lg%[-+]%lg*%*[iI]%n", &r, sign, &i, &offset) != 3 || offset == 0)
            break;
        if (sign[0] == '-')
            i = -i;
        v[nread++] = CMPLX(r, i);
        buffer += offset;
    }

    *eoc = buffer;
    return nread;
}

static void dump_complex(size_t nvalues, complex double values[nvalues])
{
    for (size_t i = 0; i < nvalues; i++)
        printf("%g%+g*I\n", creal(values[i]), cimag(values[i]));
}

enum { NUM_VALUES = 128 };

int main(void)
{
    double complex values[NUM_VALUES];
    size_t nvalues = 0;
    char *buffer = 0;
    size_t buflen = 0;
    int length;
    size_t lineno = 0;

    while ((length = getline(&buffer, &buflen, stdin)) > 0 && nvalues < NUM_VALUES)
    {
        const char *eoc;
        printf("Line: %zu [[%.*s]]\n", ++lineno, length - 1, buffer);
        size_t nread = scan_multi_complex(buffer, NUM_VALUES - nvalues, &values[nvalues], &eoc);
        if (*eoc != '\0' && *eoc != '\n')
            printf("EOC:  [[%s]]\n", eoc);
        if (nread == 0)
            break;
        dump_complex(nread, &values[nvalues]);
        nvalues += nread;
    }
    free(buffer);

    printf("All done:\n");
    dump_complex(nvalues, values);

    return 0;
}

这是一个包含 8 行的数据文件,每行 10 个复数):

-1.95+11.00*I +21.72+64.12*I -95.16-1.81*I +64.23+64.55*I +28.42-29.29*I -49.25+7.87*I +44.98+79.62*I +69.80-1.24*I +61.99+37.01*I +72.43+56.88*I
-9.15+31.41*I +63.84-15.82*I -0.77-76.80*I -85.59+74.86*I +93.00-35.10*I -93.82+52.80*I +85.45+82.42*I +0.67-55.77*I -58.32+72.63*I -27.66-81.15*I
+87.97+9.03*I +7.05-74.91*I +27.60+65.89*I +49.81+25.08*I +44.33+77.00*I +93.27-7.74*I +61.62-5.01*I +99.33-82.80*I +8.83+62.96*I +7.45+73.70*I
+40.99-12.44*I +53.34+21.74*I +75.77-62.56*I +54.16-26.97*I -37.02-31.93*I +78.20-20.91*I +79.64+74.71*I +67.95-40.73*I +58.19+61.25*I +62.29-22.43*I
+47.36-16.19*I +68.48-15.00*I +6.85+61.50*I -6.62+55.18*I +34.95-69.81*I -88.62-81.15*I +75.92-74.65*I +85.17-3.84*I -37.20-96.98*I +74.97+78.88*I
+56.80+63.63*I +92.83-16.18*I -11.47+8.81*I +90.74+42.86*I +19.11-56.70*I -77.93-70.47*I +6.73+86.12*I +2.70-57.93*I +57.87+29.44*I +6.65-63.09*I
-35.35-70.67*I +8.08-21.82*I +86.72-93.82*I -28.96-24.69*I +68.73-15.36*I +52.85+94.65*I +85.07-84.04*I +9.98+29.56*I -78.01-81.23*I -10.67+13.68*I
+83.10-33.86*I +56.87+30.23*I -78.56+3.73*I +31.41+10.30*I +91.98+29.04*I -9.20+24.59*I +70.82-19.41*I +29.21+84.74*I +56.62+92.29*I +70.66-48.35*I

程序的output为:

Line: 1 [[-1.95+11.00*I +21.72+64.12*I -95.16-1.81*I +64.23+64.55*I +28.42-29.29*I -49.25+7.87*I +44.98+79.62*I +69.80-1.24*I +61.99+37.01*I +72.43+56.88*I]]
-1.95+11*I
21.72+64.12*I
-95.16-1.81*I
64.23+64.55*I
28.42-29.29*I
-49.25+7.87*I
44.98+79.62*I
69.8-1.24*I
61.99+37.01*I
72.43+56.88*I
Line: 2 [[-9.15+31.41*I +63.84-15.82*I -0.77-76.80*I -85.59+74.86*I +93.00-35.10*I -93.82+52.80*I +85.45+82.42*I +0.67-55.77*I -58.32+72.63*I -27.66-81.15*I]]
-9.15+31.41*I
63.84-15.82*I
-0.77-76.8*I
-85.59+74.86*I
93-35.1*I
-93.82+52.8*I
85.45+82.42*I
0.67-55.77*I
-58.32+72.63*I
-27.66-81.15*I
Line: 3 [[+87.97+9.03*I +7.05-74.91*I +27.60+65.89*I +49.81+25.08*I +44.33+77.00*I +93.27-7.74*I +61.62-5.01*I +99.33-82.80*I +8.83+62.96*I +7.45+73.70*I]]
87.97+9.03*I
7.05-74.91*I
27.6+65.89*I
49.81+25.08*I
44.33+77*I
93.27-7.74*I
61.62-5.01*I
99.33-82.8*I
8.83+62.96*I
7.45+73.7*I
Line: 4 [[+40.99-12.44*I +53.34+21.74*I +75.77-62.56*I +54.16-26.97*I -37.02-31.93*I +78.20-20.91*I +79.64+74.71*I +67.95-40.73*I +58.19+61.25*I +62.29-22.43*I]]
40.99-12.44*I
53.34+21.74*I
75.77-62.56*I
54.16-26.97*I
-37.02-31.93*I
78.2-20.91*I
79.64+74.71*I
67.95-40.73*I
58.19+61.25*I
62.29-22.43*I
Line: 5 [[+47.36-16.19*I +68.48-15.00*I +6.85+61.50*I -6.62+55.18*I +34.95-69.81*I -88.62-81.15*I +75.92-74.65*I +85.17-3.84*I -37.20-96.98*I +74.97+78.88*I]]
47.36-16.19*I
68.48-15*I
6.85+61.5*I
-6.62+55.18*I
34.95-69.81*I
-88.62-81.15*I
75.92-74.65*I
85.17-3.84*I
-37.2-96.98*I
74.97+78.88*I
Line: 6 [[+56.80+63.63*I +92.83-16.18*I -11.47+8.81*I +90.74+42.86*I +19.11-56.70*I -77.93-70.47*I +6.73+86.12*I +2.70-57.93*I +57.87+29.44*I +6.65-63.09*I]]
56.8+63.63*I
92.83-16.18*I
-11.47+8.81*I
90.74+42.86*I
19.11-56.7*I
-77.93-70.47*I
6.73+86.12*I
2.7-57.93*I
57.87+29.44*I
6.65-63.09*I
Line: 7 [[-35.35-70.67*I +8.08-21.82*I +86.72-93.82*I -28.96-24.69*I +68.73-15.36*I +52.85+94.65*I +85.07-84.04*I +9.98+29.56*I -78.01-81.23*I -10.67+13.68*I]]
-35.35-70.67*I
8.08-21.82*I
86.72-93.82*I
-28.96-24.69*I
68.73-15.36*I
52.85+94.65*I
85.07-84.04*I
9.98+29.56*I
-78.01-81.23*I
-10.67+13.68*I
Line: 8 [[+83.10-33.86*I +56.87+30.23*I -78.56+3.73*I +31.41+10.30*I +91.98+29.04*I -9.20+24.59*I +70.82-19.41*I +29.21+84.74*I +56.62+92.29*I +70.66-48.35*I]]
83.1-33.86*I
56.87+30.23*I
-78.56+3.73*I
31.41+10.3*I
91.98+29.04*I
-9.2+24.59*I
70.82-19.41*I
29.21+84.74*I
56.62+92.29*I
70.66-48.35*I
All done:
-1.95+11*I
21.72+64.12*I
-95.16-1.81*I
64.23+64.55*I
28.42-29.29*I
-49.25+7.87*I
44.98+79.62*I
69.8-1.24*I
61.99+37.01*I
72.43+56.88*I
-9.15+31.41*I
63.84-15.82*I
-0.77-76.8*I
-85.59+74.86*I
93-35.1*I
-93.82+52.8*I
85.45+82.42*I
0.67-55.77*I
-58.32+72.63*I
-27.66-81.15*I
87.97+9.03*I
7.05-74.91*I
27.6+65.89*I
49.81+25.08*I
44.33+77*I
93.27-7.74*I
61.62-5.01*I
99.33-82.8*I
8.83+62.96*I
7.45+73.7*I
40.99-12.44*I
53.34+21.74*I
75.77-62.56*I
54.16-26.97*I
-37.02-31.93*I
78.2-20.91*I
79.64+74.71*I
67.95-40.73*I
58.19+61.25*I
62.29-22.43*I
47.36-16.19*I
68.48-15*I
6.85+61.5*I
-6.62+55.18*I
34.95-69.81*I
-88.62-81.15*I
75.92-74.65*I
85.17-3.84*I
-37.2-96.98*I
74.97+78.88*I
56.8+63.63*I
92.83-16.18*I
-11.47+8.81*I
90.74+42.86*I
19.11-56.7*I
-77.93-70.47*I
6.73+86.12*I
2.7-57.93*I
57.87+29.44*I
6.65-63.09*I
-35.35-70.67*I
8.08-21.82*I
86.72-93.82*I
-28.96-24.69*I
68.73-15.36*I
52.85+94.65*I
85.07-84.04*I
9.98+29.56*I
-78.01-81.23*I
-10.67+13.68*I
83.1-33.86*I
56.87+30.23*I
-78.56+3.73*I
31.41+10.3*I
91.98+29.04*I
-9.2+24.59*I
70.82-19.41*I
29.21+84.74*I
56.62+92.29*I
70.66-48.35*I

该代码将处理一行中包含任意数量条目的行(由于复数数组大小的限制,总共最多 128 个——但这也可以被修复。

暂无
暂无

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

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