2012-05-05 15 views
2

假設我們有一個C矩陣(二維數組)。如何將數字矩陣打印到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'這樣的函數,似乎很難知道字符串緩衝區應該多大。

我搜索谷歌和計算器,但幾乎我所得到的是關於如何字符串轉換爲數值都...

如何做到這在C?有沒有libs?

你能幫忙嗎?謝謝!

編輯: 'snprintf'解決方案適用於只有一個數字的情況。 但是對於矩陣,它應該使用循環遍歷每個元素。 然後爲每個循環中的字符串添加一點。這將工作與'snprintf'?

回答

1

你需要做這兩個步驟,首先計算總規模保持字符串,然後分配它並組成字符串。可以在一個函數來完成這樣的:

#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 
0

您可以從一些估計的大小開始,如果它不夠用,則使用realloc

如果snprintf返回大於剩餘的緩衝區大小,則表示它沒有足夠的空間。在這種情況下,您應該重新分配,然後重試相同的snprintf

0

它的數組。

考慮浮點值。

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

}

希望這會幫助你。

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; 
} 
+0

的「snprintf的」解決方案非常適用於只是一個數字的情況。 但是對於矩陣,它應該使用循環遍歷每個元素。 然後在每個循環的字符串中添加一點,這將與'snprintf'一起工作嗎? – Roun

+0

你可能會做另外一件事:'char s [80]; sprintf(s,80,「%.2f」,f)'並且與累加器連接,你可以通過重新分配管理你的能力:'int n = strlen(s); if(accumLen + n> accumCap){realloca和copy} strcpy(accum,s); accum + = n; accumLen - = n;' – demi

+0

'char * ftoa(float);' – Feo

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") 
} 
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; 
} 
相關問題