ฉันจะพิมพ์ไปที่ stderr ใน C ได้อย่างไร?


121

ใน C, การพิมพ์ที่ stdout เป็นเรื่องง่ายด้วยจากprintfstdio.h

อย่างไรก็ตามสามารถพิมพ์ไปยัง stderr ได้อย่างไร? เราสามารถใช้fprintfเพื่อให้บรรลุได้อย่างชัดเจน แต่ไวยากรณ์ของมันดูแปลก ๆ บางทีเราอาจใช้printfพิมพ์ลง stderr?


5
อะไรที่ "แปลก" เกี่ยวกับไวยากรณ์ของมัน? มันเป็นพิมพ์ที่ , วิธีการและสิ่งที่
ยูจีนช.

5
ฉันกำลังจดจ่ออยู่กับมัน ปัญหาเดียวที่เกิดจากคำถามที่คุณพบทางออก "แปลก" อย่างอื่นไม่มีคำถาม ใช้fprintf.
ยูจีนช.

@Eugene ฉันเห็นด้วยกับคุณ. ฉันคิดว่ามันแปลกเพราะฉันไม่รู้ว่า stderr เป็น FILE :)
wad

คำตอบ:


180

ไวยากรณ์เกือบจะเหมือนกับprintfไฟล์. เมื่อprintfคุณให้รูปแบบสตริงและเนื้อหาเช่น:

printf("my %s has %d chars\n", "string format", 30);

ด้วยfprintfสิ่งนี้เหมือนกันยกเว้นตอนนี้คุณกำลังระบุสถานที่ที่จะพิมพ์ไปยัง:

File *myFile;
...
fprintf( myFile, "my %s has %d chars\n", "string format", 30);

หรือในกรณีของคุณ:

fprintf( stderr, "my %s has %d chars\n", "string format", 30);

35

ตัวอย่าง:

printf("%s", "Hello world\n");              // "Hello world" on stdout (using printf)
fprintf(stdout, "%s", "Hello world\n");     // "Hello world" on stdout (using fprintf)
fprintf(stderr, "%s", "Stack overflow!\n"); // Error message on stderr (using fprintf)

10
#include<stdio.h>

int main ( ) {
    printf( "hello " );
    fprintf( stderr, "HELP!" );
    printf( " world\n" );
    return 0;
}

$ ./a.exe
HELP!hello  world
$ ./a.exe 2> tmp1
hello  world
$ ./a.exe 1> tmp1
HELP!$
  1. stderr มักจะไม่มีบัฟเฟอร์และ stdout มักจะเป็น สิ่งนี้สามารถนำไปสู่ผลลัพธ์ที่ดูแปลก ๆ เช่นนี้ซึ่งแสดงว่าโค้ดกำลังทำงานผิดลำดับ ไม่ได้เป็นเพียงแค่บัฟเฟอร์ stdout ที่ยังไม่ถูกล้าง สตรีมที่เปลี่ยนเส้นทางหรือไปป์จะไม่เห็นการแทรกสอดนี้เนื่องจากโดยปกติจะเห็นเฉพาะเอาต์พุตของ stdout เท่านั้นหรือ stderr เท่านั้น

  2. แม้ว่าในตอนแรกทั้ง stdout และ stderr จะมาที่คอนโซล แต่ทั้งสองอย่างจะแยกกันและสามารถเปลี่ยนเส้นทางทีละรายการได้


5

คุณรู้sprintfหรือไม่? โดยพื้นฐานแล้วมันเป็นสิ่งเดียวกันกับfprintf. อาร์กิวเมนต์แรกคือปลายทาง (ไฟล์ในกรณีfprintfie stderr) อาร์กิวเมนต์ที่สองคือสตริงรูปแบบและส่วนที่เหลือเป็นอาร์กิวเมนต์ตามปกติ

ฉันขอแนะนำข้อมูลอ้างอิงนี้printf(และครอบครัว)ด้วย


5

หากคุณไม่ต้องการแก้ไขรหัสปัจจุบันและเพียงเพื่อแก้จุดบกพร่องการใช้งาน

เพิ่มมาโครนี้:

#define printf(args...) fprintf(stderr, ##args)
//under GCC
#define printf(args...) fprintf(stderr, __VA_ARGS__)
//under MSVC

เปลี่ยนstderrเป็นstdoutถ้าคุณต้องการย้อนกลับ

เป็นประโยชน์สำหรับการดีบัก แต่ไม่ใช่แนวทางปฏิบัติที่ดี


คุณสามารถตั้งชื่อแยกต่างหากeprintfหรือบางอย่างก็ได้ (: O นี่คือตัวอย่างมาโครตัวแปรของ GCC (3.2): gcc.gnu.org/onlinedocs/gcc-3.2/cpp/Variadic-Macros.html )
Solomon Ucko

0

ในการพิมพ์บริบทของคุณคุณสามารถเขียนโค้ดดังนี้:

FILE *fp;
char *of;
sprintf(of,"%s%s",text1,text2);
fp=fopen(of,'w');
fprintf(fp,"your print line");

สิ่งนี้ไม่ได้เพิ่มอะไรให้กับคำตอบก่อนหน้านี้และไม่ได้ตอบคำถามจริงๆ
Fantastic Mr Fox

คำสั่ง sprintf () นั้นทำให้หน่วยความจำเสียหาย! ... ฉันขอแนะนำให้คุณอ่านวิธีการทำงานของพอยน์เตอร์อาร์เรย์และสตริง
BlueChip
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.