2

Cに行列(2D配列)があるとします。

行列をCの文字列に出力するにはどうすればよいでしょうか。

たとえば、私が持っている場合

double M[2][2]={{1.2,3.4},{3.14,2.718}}

次のような文字列を取得したい:

"1.200  3.400\n3.140  2.718"

次のように印刷できます

1.200 3.400
3.140 2.718

画面に印刷する場合、バッファサイズを考慮する必要がないため、問題が発生しやすくなります。ただし、文字列に出力する場合、「sprintf」のような関数を使用する場合、文字列バッファの大きさを知るのは難しいようです。

私はグーグルとスタックオーバーフローを検索しましたが、私が得るもののほとんどすべては文字列を数値に変換する方法についてです...

Cでこれを行う方法は?ライブラリはありますか?

手伝ってもらえますか?ありがとうございました!

編集:「snprintf」ソリューションは、1つの数値の状況でうまく機能します。ただし、マトリックスの場合は、ループを使用してすべての要素を通過することになっています。次に、各ループの文字列に少し追加します。これは「snprintf」で機能しますか?

4

6 に答える 6

1

snprintf最初に必要なバッファ長を取得してから、それに割り当てて印刷するために使用できます。

char* PrettyPrint(const char* format, ...)
{
  va_args va;
  va_start(va, format);

  char c[1] = {};
  int len = vsnprintf(c, 1, format, va);
  char* s = malloc(len + 1);
  vsnprintf(s, len + 1, format, va);

  va_end(va);

  return s;
}
于 2012-05-05T08:04:38.267 に答える
1

これは2つのステップで行う必要があります。最初に文字列を保持するための合計サイズを計算し、次にそれを割り当てて文字列を作成します。次のような関数で実行できます。

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

#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a))

static char * matrix2D_to_string(const double *matrix, size_t rows, size_t columns)
{
    const char format[] = "%f";
    const char column_separator[] = "  ";
    const char row_separator[] = "\n";

    int *column_widths = NULL;
    size_t r = 0, c = 0;
    char *buffer = NULL, *p = NULL;
    size_t size = 0;

    if (!rows || ! columns) {
        errno = EINVAL;
        return NULL;
    }

    // calculate maximum width for each column
    column_widths = (int *)calloc(columns, sizeof(*column_widths));
    for (r = 0; r < rows; ++r) {
        for (c = 0; c < columns; ++c) {
            char buf[256];
            int width = sprintf(buf, format, matrix[r * columns + c]);
            if (width > column_widths[c]) {
                column_widths[c] = width;
            }
        }
    }

    // calculate total buffer size...

    // ... values
    for (c = 0; c < columns; ++c) {
        size += column_widths[c] * rows;
    }
    // ... column separators
    size += (columns - 1) * strlen(column_separator);
    // ... row separators
    size += (rows - 1) * strlen(row_separator);
    // ... nul terminator
    ++size;

    // make the string
    buffer = (char *)malloc(size);
    p = buffer;
    for (r = 0; r < rows; ++r) {
        if (r) {
            strcpy(p, row_separator);
            p += strlen(row_separator);
        }
        for (c = 0; c < columns; ++c) {
            if (c) {
                strcpy(p, column_separator);
                p += strlen(column_separator);
            }
            int width = sprintf(p, format, matrix[r * columns + c]);
            p += width;
            if (width < column_widths[c]) {
                width = column_widths[c] - width;
                memset(p, ' ', width);
                p += width;
            }
        }
    }
    *p = '\0';

    // cleanup
    free(column_widths);

    return buffer;
}

int main()
{
    double M[3][2]={{1.2,3.4},{3.14,2.718},{100.999,0.000005}};

    char *s = matrix2D_to_string((const double *)M, ARRAY_SIZE(M), ARRAY_SIZE(M[0]));

    puts(s);

    free(s);

    return 0;
}

これは印刷します:

1.200000    3.400000
3.140000    2.718000
100.999000  0.000005
于 2012-05-05T09:25:47.697 に答える
0

いくつかの推定サイズから始めて、reallocそれが十分でない場合に使用することができます。

snprintf残りのバッファサイズよりも多くを返す場合は、十分なスペースがなかったことを意味します。この場合、再割り当てして、同じことを再試行する必要がありますsnprintf

于 2012-05-05T07:47:33.877 に答える
0

その配列。

フロート値を考慮します。

for(i=0;i<2;i++)
{
   for(j=0;j<2;j++)
   {
       printf("%f \t",M[i][j]);
   }
   printf("\n");

}

これがお役に立てば幸いです。

于 2012-05-05T07:52:19.690 に答える
0
for(i=0;i<2;i++)
{
   for(j=0;j<2;j++)
   {
       printf("%f \t",M[i][j]);
   }
   printf("\\n");//Change printf("\n") as printf("\\n")
}
于 2012-05-05T08:31:34.847 に答える
0
#include <stdio.h>
#include <stdlib.h>

long GetFileSize(FILE *fp){
    long fsize = 0;

    fseek(fp,0,SEEK_END);
    fsize = ftell(fp); 
    fseek(fp,0,SEEK_SET);//reset stream position!!

    return fsize;
}

char *ReadToEnd(const char *filepath){
    FILE *fp;
    long fsize;
    char *buff;

    if(NULL==(fp=fopen(filepath, "rb"))){
        perror("file cannot open at ReadToEnd\n");
        return NULL;
    }
    fsize=GetFileSize(fp);
    buff=(char*)malloc(sizeof(char)*fsize+1);
    fread(buff, sizeof(char), fsize, fp);
    fclose(fp);
    buff[fsize]='\0';

    return buff;
}

char *printStrMatrix(const char *fmt, const int col, const int row, const double* matrix ){
    FILE *fp;
    int c,r;
    char *str;

    if(NULL==(fp=fopen("printStr.tmp", "wb"))){//use tmpnam() better
        perror("temporary file cannot open at printStr\n");
        return NULL;
    }
    for(r=0;r<row;++r){
        for(c=0;c<col;++c){
            fprintf(fp, fmt, *matrix++);
            if(c != col-1)
                fprintf(fp, " ");
        }
        fprintf(fp, "\n");
    }
    fflush(fp);
    fclose(fp);
    str=ReadToEnd("printStr.tmp");
    remove("printStr.tmp");
    return str;
}

int main(void){
    double M[2][2]={{1.2,3.4},{3.14,2.718}};
    char *str;
    str=printStrMatrix("%1.3lf", 2, 2, &M[0][0]);
    printf("%s", str);
    free(str);
    return 0;
}
于 2012-05-05T09:57:07.957 に答える