3

我正在将一些旧版 Fortran77 代码迁移到 C/C++。在 Fortran77 代码中,如果从一个文件中读入 8 个字符,它们可以毫无问题地存储在一个 real*8 类型的变量中。

是否可以在 C 或 C++ 中做类似的事情?如果是这样,我会怎么做?我一直无法在互联网上找到任何解决方案。我需要使用 C/C++ 读取 8 个字符并将它们存储在 double 类型的变量中,然后将其传递回 Fortran 并对应于原始 real*8 变量。

非常感谢您的帮助。

编辑: 作为对@sixlettervariables 的回应,我将进一步澄清我的用例。我对他的建议的问题是我只知道运行时每行的格式(即哪些字段是字符串,哪些数字),因此我不知道该结构应该静态具有哪些成员。这些字段还需要按照它们被读入的顺序占用一个连续的内存块。

具体来说,在程序的一次运行中,每一行的格式可能是:f1:string, f2:number, f3:number, f4:string,但在另一个f1:string, f2:string, f3:string, f4:number 中, f5:数字. 对于第一种情况,我需要:

struct { char[8] f1; double f2; double f3; char[8] f4}

第二个我需要:

struct { char[8] f1; char[8] f2; char[8] f3; double f4; double f5} 

也许有一些方法可以用模板做到这一点?

4

5 回答 5

6

您不需要将它们存储在 a 中double,因为 Fortran 需要这样做。事实上,你绝对不应该在你的 C/C++ 代码中这样做。

只需将字符数据存储在字符数组中。

如果您混合使用 Fortran 和 C/C++,那么两者在 ABI 之外不知道彼此。在 C 方面,您可以简单地声称Fortran 接口采用字符数组,而实际上它需要一个双精度数组。Fortran 方面也是如此。

从C端:

extern void FCHARS(char* str, int length);

/* ... */
int flength = 0; /* optional: length of the string in Fortran terms */
char str[9]; /* in C/C++ add one for \0 at the end */

/* read in up to a block of 8 */
fgets(str, sizeof(str), fp);

/* At this point if you know the 8 characters are space padded to their end
 * you have no more work to do, otherwise you may need to fill from the right
 * with spaces.
 */
{
    size_t ii = sizeof(str) - 1;
    while (ii > 0 && str[ii - 1] == '\0') {
        str[ii - 1] = ' ';
        flength = ii--;    /* optional: keep track of our unpadded length */
    }
}

/* Once you've space padded the string you can call your Fortran method.
 * If your Fortran method accepts a string of unknown length, supply
 * `flength`. If your Fortran method expects a string of a fixed length, pass
 * the size of `str` (excluding '\0') instead.
 */
FCHARS(str, flength);

只要您从 C/C++ 代码中遵循 Fortran 编译器的 ABI 要求(例如 CDECL、交错传递的隐藏字符串长度),就可以了。

于 2013-05-09T13:43:35.760 回答
3

当然,只需使用演员表。您可能需要添加一个 static_assert 以确保安全:

double d;
char * b = (char*)&d;
static_assert(sizeof(d) == sizeof(char[8]), "Double must be large enough to hold 8 chars");
于 2013-05-09T13:40:58.013 回答
1
union Data{
    char c[8];
    double d;
};

将这 8 个字符保存到c中,然后通过 读取d。例子:

#include <stdio.h>
// #include <stdlib.h>
union Data{
    char c[8];
    double d;
};

int main(){
    int i;
    union Data data;
    for(i = 0; i < 8; i++)
        scanf("%hhd", data.c + i);
    printf("%e\n", data.d);
    // system("pause");
    return 0;
}
于 2013-05-09T13:42:44.223 回答
0

方法一

double a;
char ch;
int i;
for(i=0;i<8;i++)
{
   scanf("%c", &ch);
   a=a+ch;
   if(i!=8)
     a<<8; //left shifts by 8 bits, to accomodate another 8 bits on right.
}

方法二

double a
char *ch;
int i;
ch=&a;
for(i=0;i<8;i++)
{
   scanf("%c", ch);
   ch++;
}
于 2013-05-09T15:53:38.957 回答
0

即使可以在 C 中将多个字符和实数存储在 DOUBLE 变量中,因为 C DOUBLE 等于 REAL*8 因为两者都是双精度浮点数,我强烈建议不要这样做。

这种在 REAL*8 中存储多个字符和实数的“技巧”感觉就像是一种节省空间的技巧。我认为现在不需要这样做,而且我认为这种“技巧”不会生成更快的代码。我建议使用上面提到的 UNION。

您可以将读取字符和实数的 FORTAN 代码发布到 REAL*8 中,这样可以更轻松地为您提供帮助。我必须说我很想知道这是如何完成的。

于 2013-05-09T16:15:39.850 回答