1

下面创建一个随机数表并将其打印到控制台上。如何修改我做的createtxt函数,让控制台上的输出同时生成一个文本文件。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>


FILE* createtxt(char* fnam){
    FILE* ofp;
    ofp = fopen(fnam, "w");
    if (ofp == NULL) {
        printf("Cannot open output file %s\n", fnam);
        exit(EXIT_FAILURE);
}

void closetxt(FILE* ofp){
    fclose(ofp);
}

int main (void){
    printf("Table of random numbers for drawing geometric shapes in different     colours, sizes and opacities\n");

int rn = 0;
unsigned int seed = (unsigned int)time(NULL);
srand(seed);

int k = 0;
printf("shape#\tRSCE\tx\ty\twidth\theight\tred\tgreen\tblue\tgreen\topacity\n");
while (k < NO_SHAPES){
    printf("%6d", k);
    rn = rand() % SHAPE_RANGE;
    printf( "\t%4d",rn);
    rn = rand() % X_RANGE;
    printf("\t%d",rn);
    rn = rand() % Y_RANGE;
    printf("\t%d",rn);
    rn = rand() % WIDTH_RANGE;
    printf("\t%5d",rn);
    rn = rand() % HEIGHT_RANGE;
    printf("\t%6d",rn);
    rn = rand() % RED_RANGE;
    printf("\t%3d",rn);
    rn = rand() % GREEN_RANGE;
    printf("\t%5d",rn);
    rn = rand() % BLUE_RANGE;
    printf("\t%4d",rn);
    rn = rand() % OPACITY_RANGE;
    printf("\t%.1f\n",rn/100.0);
    k++;
    }

    FILE* ofp = createtxt("myrandom.txt")
    closetxt(ofp);

    return EXIT_SUCCESS;
}
4

2 回答 2

1

我可能会考虑创建一个ffprintf()函数:

#include <assert.h>
#include <stdarg.h>
#include <stdio.h>

extern int ffprintf(FILE *fp1, FILE *fp2, char const *fmt, ...);

int ffprintf(FILE *fp1, FILE *fp2, char const *fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    int rc1 = vfprintf(fp1, fmt, args);
    va_end(args);
    va_start(args, fmt);
    int rc2 = vfprintf(fp2, fmt, args);
    va_end(args);
    assert(rc1 == rc2);
    return rc1;
}

那么主要代码可以是:

FILE* ofp = createtxt("myrandom.txt")

ffprintf(stdout, ofp, "shape#\tRSCE\tx\ty\twidth\theight\tred\tgreen\tblue\tgreen\topacity\n");
while (k < NO_SHAPES)
{
    ffprintf(stdout, ofp, "%6d", k);
    rn = rand() % SHAPE_RANGE;
    ffprintf(stdout, ofp, "\t%4d", rn);
    ...
}

closetxt(ofp);

如果您不习惯使用可变长度参数列表,您可以编写一个更简单的函数版本:

extern int ffprintf(FILE *fp1, FILE *fp2, char const *fmt, int value);

int ffprintf(FILE *fp1, FILE *fp2, char const *fmt, value)
{
    int rc1 = fprintf(fp1, fmt, value);
    int rc2 = vfprintf(fp2, fmt, value);
    assert(rc1 == rc2);
    return rc1;
}

现在你必须写两次标题:

char const header[] =
     "shape#\tRSCE\tx\ty\twidth\theight\tred\tgreen\tblue\tgreen\topacity\n";

fputs(header, stdout);
fputs(header, ofp);

其余大部分可以保持不变,但不透明度(浮动)需要特别处理以及标题行。

显然,如果您不喜欢它侵犯函数的标准名称,函数名称是可以更改的。如果您使用更简单的方法,则函数名称应更改为类似的名称,ffprint_int()因为它一次只打印一个int

的使用assert()是惰性的,但它确实确保两个打印操作都成功(或都失败)。如果您对此感到担心,请将该断言更改为:

if (rc2 < rc1)
    rc1 = rc2;

这将返回两个值中较小的一个;如果一个是-1(完全失败),那就是将返回的值。当然,由于我编写的代码忽略了 from 的返回值ffprintf(),就像您的代码忽略了 from 的返回值一样printf(),这是一个在很大程度上不会引起注意的细微差别。

于 2013-10-28T03:53:12.810 回答
0

此版本与 printf() 语句一致地完成:(请参阅下面的在createtxt()
printf 语句之前打开文件:

FILE* ofp = createtxt("myrandom.txt");
char buf[20];


rn = rand() % SHAPE_RANGE;
sprintf(buf, "\t%4d",rn);//use sprintf() to put information into buf
printf(buf);             //output to stdout
fputs(buf, ofp );        //output to file
/// repeat lines for X_RANGE, Y_RANGE, etc.

fclose(ofp);     

如果来自 createtxt:

将原型更改为int createtxt(char *fnam, char *buf)

而不是使用

sprintf(buf, "\t%4d",rn);//use sprintf() to put information into buf
printf(buf);             //output to stdout  

使用:
//创建并初始化一个更大的缓冲区。

char buf[1000];  //or some other appropriately sized buffer

buf[0]=0;  //set NULL to first position of buf
//then, between all the printf statements in main, call this:      
sprintf(buf, %s\t%4d", buf, rn);//will concatenate all bufs until end  

然后将 buf 作为参数传递给createtxt().

void createtxt(char* fnam, char *buf)
{
    FILE* ofp;
    ofp = fopen(fnam, "w");
    if (ofp == NULL) {
        printf("Cannot open output file %s\n", fnam);
        exit(EXIT_FAILURE);
    {
    fputs(buf, ofp);
    fclose(ofp);
}
于 2013-10-28T03:14:52.433 回答