简体   繁体   English

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

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

I am unable to read imaginary data from text file.我无法从文本文件中读取虚数数据。 Here is my.txt file这是 my.txt 文件

abc.txt abc.txt

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

I want to read this data into a matrix and print it.我想将这些数据读入矩阵并打印出来。

I found the solutions using C++ here and here .我在这里这里使用C++找到了解决方案。 I don't know how to do the same in C.我不知道如何在 C 中做同样的事情。

I am able to read decimal and integer data in.txt and print them.我能够读取十进制和 integer 数据 in.txt 并打印它们。 I am also able to print imaginary data initialized at the declaration, using complex.h header. This is the program I have writtern我还可以使用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;
}

But I want to read it from the text, because I have an array of larger size, which I can't initialize at declaration, because of it's size.但是我想从文本中读取它,因为我有一个更大的数组,由于它的大小,我无法在声明时对其进行初始化。

There are two main issues with your code:您的代码有两个主要问题:

  • You need to add complex to the variables that hold complex values.您需要将complex添加到包含复杂值的变量中。
  • scanf() needs pointers to objects to store scanned values in them. scanf()需要指向对象的指针以在其中存储扫描值。 But creal() returns a value, copied from its argument's contents.但是creal()返回一个值,该值是从其参数的内容中复制而来的。 It is neither a pointer, nor could you get the address of the corresponding part of the complex argument.它既不是指针,也不能得到复数参数对应部分的地址。

Therefore, you need to provide temporary objects to scanf() which receive the scanned values.因此,您需要为接收扫描值的scanf()提供临时对象。 After successfully scanning, these values are combined to a complex value and assigned to the indexed matrix cell.成功扫描后,将这些值组合成一个复值并分配给索引矩阵单元格。

Minor issues not contributing to the core problem are:不会导致核心问题的次要问题是:

  • The given source is "augmented" with unneeded #include s, unused variables, global variables, and experiments with constants.给定的源是用不需要的#include s、未使用的变量、全局变量和常量实验“扩充”的。 I removed them all to see the real thing.我将它们全部移除以查看真实的东西。

  • The specifier "%f" (as many others) lets scanf() skip whitespace like blanks, tabs, newlines, and so on.说明符"%f" (和许多其他说明符一样)允许scanf()跳过空格,如空格、制表符、换行符等。 Providing a "\n" mostly does more harm than one would expect.提供一个"\n"通常比人们预期的危害更大。

    I kept the "*I" to check the correct format.我保留了"*I"来检查正确的格式。 However, an error will only be found on the next call of scanf() , when it cannot scan the next number.但是,只有在下次调用scanf()无法扫描下一个数字时才会发现错误。

  • You need to check the return value of scanf() , always.您需要始终检查scanf()的返回值。 It returns the number of conversions that were successful.它返回成功的转换次数。

  • It is a common and good habit to let the compiler calculate the number of elements in an array.让编译器计算数组中元素的数量是一个常见的好习惯。 Divide the total size by an element's size.将总大小除以元素的大小。

    Oh, and sizeof is an operator, not a function.哦, sizeof是一个运算符,而不是 function。

  • It is also best to return symbolic values to the caller, instead of magic numbers.最好向调用者返回符号值,而不是幻数。 Fortunately, the standard library defines these EXIT_... macros.幸运的是,标准库定义了这些EXIT_...宏。

  • The signs are correctly handled by scanf() already.这些标志已由scanf()正确处理。 There is no need to tell it more.无需多说。 But for a nice output with printf() , you use the "+" as a flag to always output a sign.但是对于带有printf()的漂亮 output ,您使用"+"作为标志始终将 output 标记为一个标志。

  • Since the sign is now placed directly before the number, I moved the multiplication by I (you can change it to lower case, if you want) to the back of the imaginary part.由于符号现在直接放在数字之前,我将乘以I (如果需要,可以将其更改为小写)移到虚部的后面。 This also matches the input format.这也匹配输入格式。

  • Error output is done via stderr instead of stdout .错误 output 是通过stderr而不是stdout完成的。 For example, this enables you to redirect the standard output to a pipe or file, without missing potential errors.例如,这使您能够将标准 output 重定向到 pipe 或文件,而不会遗漏潜在错误。 You can also redirect errors somewhere else.您还可以将错误重定向到其他地方。 And it is a well-known and appreciated standard.这是一个广为人知和赞赏的标准。

This is a possible solution:这是一个可能的解决方案:

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

Here's a simple solution using scanf() and the format shown in the examples.这是一个使用scanf()和示例中显示的格式的简单解决方案。 It writes the values in the same format that it reads them — the output can be scanned by the program as input.它以与读取它们相同的格式写入值——程序可以扫描 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;
}

Sample input:示例输入:

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 from sample input: 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

The numbers at the end with large exponents are Avogadro's Number and the Planck Constant.大指数末尾的数字是阿伏伽德罗数和普朗克常数。

The format is about as stringent are you can make it with scanf() , but, although it requires a sign ( + or - ) between the real and imaginary parts and requires the * and I to be immediately after the imaginary part (and the conversion will fail if the *I is missing), and accepts either i or I to indicate the imaginary value:该格式与您可以使用scanf()制作的一样严格,但是,尽管它需要在实部和虚部之间有一个符号( +- )并且要求*I紧跟在虚部之后(和如果缺少*I ,转换将失败),并接受iI来表示虚数:

  • It doesn't stop the imaginary number having a second sign (so it will read a value such as " -6+-4*I ").它不会停止具有第二个符号的虚数(因此它将读取诸如“ -6+-4*I ”的值)。
  • It doesn't stop there being white space after the mandatory sign (so it will read a value such as " -6+ 24*I ".它不会停止在强制性符号之后出现空格(因此它会读取诸如“ -6+ 24*I ”之类的值。
  • It doesn't stop the real part being on one line and the imaginary part on the next line.它不会阻止实部位于一行而虚部位于下一行。
  • It won't handle either a pure-real number or a pure-imaginary number properly.它不会正确处理纯实数或纯虚数。

The scanf() functions are very flexible about white space, and it is very hard to prevent them from accepting white space. scanf()函数对空白非常灵活,很难阻止它们接受空白。 It would require a custom parser to prevent unwanted spaces.它需要一个自定义解析器来防止不需要的空格。 You could do that by reading the numbers and the markers separately, as strings, and then verifying that there's no space and so on.您可以通过分别读取数字和标记作为字符串,然后验证没有空格等来做到这一点。 That might be the best way to handle it.这可能是最好的处理方式。 You'd use sscanf() to convert the string read after ensuring there's no embedded white space yet the format is correct.在确保没有嵌入的空格但格式正确后,您将使用sscanf()转换读取的字符串。


I do not know which IDE you are using for C, so I do not understand this ./testprog <test.data .我不知道你用的是哪个 IDE 作为 C,所以我不明白这个./testprog <test.data

I have yet to find an IDE that does not drive me bonkers.我还没有找到一个不会让我发疯的 IDE。 I use a Unix shell running in a terminal window. Assuming that your program name is testprog and the data file is test.data , typing ./testprog < test.data runs the program and feeds the contents of test.data as its standard input.我使用 Unix shell 在终端 window 中运行。假设您的程序名称是testprog并且数据文件是test.data ,键入./testprog < test.data运行程序并将test.data的内容作为其标准输入. On Windows, this would be a command window (and I think PowerShell would work much the same way).在 Windows 上,这将是命令 window(我认为 PowerShell 的工作方式大致相同)。

I used fgets to read each line of the text file.我使用fgets读取文本文件的每一行。 Though I know the functionality of sscanf , I do not know how to parse an entire line, which has about 23 elements per line.虽然我知道sscanf的功能,但我不知道如何解析整行,每行大约有 23 个元素。 If the number of elements in a line are few, I know how to parse it.如果一行中的元素数量很少,我知道如何解析它。 Could you help me about it?你能帮我一下吗?

As I noted in a comment, the SO Q&A How to use sscanf() in loops?正如我在评论中指出的那样,SO Q&A How to use sscanf() in loops? explains how to use sscanf() to read multiple entries from a line.解释了如何使用sscanf()从一行中读取多个条目。 In this case, you will need to read multiple complex numbers from a single line.在这种情况下,您将需要从一行中读取多个复数。 Here is some code that shows it at work.这是一些代码,显示它在工作中。 It uses the POSIX getline() function to read arbitrarily long lines.它使用 POSIX getline() function 来读取任意长的行。 If it isn't available to you, you can use fgets() instead, but you'll need to preallocate a big enough line buffer.如果它对您不可用,您可以改用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;
}

Here is a data file with 8 lines with 10 complex numbers per line):这是一个包含 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

The output of the program is:程序的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

The code would handle lines with any number of entries on a line (up to 128 in total because of the limit on the size of the array of complex numbers — but that can be fixed too.该代码将处理一行中包含任意数量条目的行(由于复数数组大小的限制,总共最多 128 个——但这也可以被修复。

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

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