2

假设我们在 C 中有一个矩阵(一个二维数组)。

我想知道如何将矩阵打印成 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”这样的函数,似乎很难知道字符串缓冲区应该有多大。

我搜索了谷歌和stackoverflow,但几乎所有我得到的都是关于如何将字符串转换为数字......

如何在 C 中做到这一点?有库吗?

能否请你帮忙?谢谢!

编辑: 'snprintf' 解决方案适用于只有一个数字的情况。但是对于矩阵,它应该使用循环来遍历每个元素。然后在每个循环中添加一点字符串。这适用于“snprintf”吗?

4

6 回答 6

1

You'll need to do this in two steps, first calculate the total size to hold the string, then allocate it and compose the string. Could be done in a function like this:

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

This prints:

1.200000    3.400000
3.140000    2.718000
100.999000  0.000005
于 2012-05-05T09:25:47.697 回答
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 回答
0

您可以从一些估计的大小开始,realloc如果还不够,请使用。

如果snprintf返回大于剩余缓冲区大小,则意味着它没有足够的空间。在这种情况下,您应该重新分配并重试相同的snprintf.

于 2012-05-05T07:47:33.877 回答
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 回答
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 回答