2013-10-28 3 views
0

Следующее создает и печатает таблицу случайных чисел на консоли. Как я могу изменить функцию 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; 
} 
+0

'printf()' все для файла 'myrandom.txt'. Прочитайте его и распечатайте на' stdout'. (Предположим, это не _simultaneous_) – chux

+0

Невозможно сделать что-то подобное, так как вы не можете делать две вещи, даже если вы используете потоки, они не гарантированно работают одновременно. –

+0

Вам нужно либо захватить его, когда он создается, и чередовать запись на экран с помощью записи в файл, либо вы можете просто сохранить конкатенация новых строк даты в более крупный буфер, а затем передать в качестве аргумента 'createtxt()'. Оба показаны ниже. – ryyker

ответ

0

Эта версия Совершено рядный с Е() заявления: (смотрите ниже в 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); 
} 
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 (полный сбой), это значение, которое будет возвращено. Конечно, поскольку код, который я написал, игнорирует возвращаемое значение от ffprintf(), так же как ваш код игнорировал возвращаемое значение от printf(), это нюанс, который будет в значительной степени незаметным.

+0

Очевидно, решение, более достойное постоянного приложения. – ryyker

Смежные вопросы