perror()和printf()之间的区别

时间:2015-12-05 09:00:24

标签: c linux stdout stderr

我读过perror()printf()写入终端屏幕。但是perror()写入stderr,而printf()写入stdout。因此,要打印错误,perror()可以在printf()执行此操作时使用 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Add 'general' preferences, defined in the XML file addPreferencesFromResource(R.xml.pref_general); // For all preferences, attach an OnPreferenceChangeListener so the UI summary can be // updated when the preference changes. bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_location_key))); bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_units_key))); }

6 个答案:

答案 0 :(得分:5)

printf()无法写入stderrfprintf()可以。 perror()总是如此。

不要求写入stdoutstderr写入终端屏幕 - 这取决于实现(因为并非所有系统都有终端)。写入stdoutstderr并不要求写入同一设备(例如,一个可以重定向到文件,而另一个被重定向到管道)。

perror()将通过内置的错误代码含义知识实现,由静态errno表示,静态from __future__ import print_function import threading import urllib import urllib2 import time threads = [] # url to open url = "http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4" u = urllib.urlopen(url) # define file file_name = "test.mp4" f = open(file_name, 'wb') # open url and get header info def get_file_size(url): stream_size = u.info()['Content-Length'] end = stream_size return end start = 0 #get stream size end = get_file_size(url) # specify block size block_sz = 512 #algo to divide work among 2 threads def calculate_no_of_bytes_for_thread1(): full_stream_size = end first_thread = {'start':0, 'end':(int(full_stream_size)/2)} print(first_thread) return first_thread #algo to divide work among 2 threads def calculate_no_of_bytes_for_thread2(): full_stream_size = end second_thread= {'start':int(full_stream_size)/2,'end': int(full_stream_size)} print(second_thread) return second_thread # download function def download_thread(url ,id,start,end): current_size = int(float(start)/1024) total_size = int(float(end)/1024) print ("Start at_"+str(current_size) + "Ends at_" + str(total_size)) # specify request range and init stream req = urllib2.Request(url) req.headers['Range'] = 'bytes=%s-%s' % (start, end) data = urllib2.urlopen(req) while True: buffer = u.read(block_sz) if not buffer: break start += len(buffer) f.write(buffer) thread_id = id #percentage = (current_size * 100 / total_size) status = str(thread_id) + "_" + str(current_size) + "_" +str(total_size) print (status) #starts 2 threads def start_threads(): for i in range(2): #if first loop, start thread 1 if(i==1): start = calculate_no_of_bytes_for_thread1().get('start') end = calculate_no_of_bytes_for_thread1().get('end') print("Thread 1 started") t = threading.Thread(target=download_thread, args=(url,i,start,end)) t.start() threads.append( t) #if second loop, start thread 1 if(i==2): start = calculate_no_of_bytes_for_thread2().get('start') end = calculate_no_of_bytes_for_thread2().get('end') print("Thread 2 started") t = threading.Thread(target=download_thread, args=(url,i,start,end)) t.start() threads.append( t) # Join threads back (order doesn't matter, you just want them all) for i in threads: i.join() #start benchmarking start_time = time.clock() start_threads() print ("Finito!") end_time = time.clock() benchmark = str(end_time - start_time) print ("Download took_" +benchmark) f.close() 由标准库中的各种函数用于报告错误情况。特定值的含义是实现定义的(即它们在编译器和库之间有所不同)。

答案 1 :(得分:2)

因为可能存在您希望stderr打印到控制台但其他输出根本不打印的配置(例如,删除详细程度)。在其他情况下,您可能需要重定向stderr以写入文件,这在您进行生产时非常有用,并且该文件可用于了解您无法自行调试的远程计算机上出现的问题。 / p>

通常,您可以根据其类型获得对控制台输出处理方式的更多控制。

请参阅this answer以了解如何在代码中进行流重定向。

或者,请参阅this link,了解如何强制流重定向到文件或忽略已编译程序上的流(在 bash 中调用它时)

答案 2 :(得分:2)

除了其他答案之外,您可以使用stderr上的fprintf(3)errno(3)上的strerror(3)

 fprintf(stderr, "something wrong: %s\n", strerror(errno));

在GNU libc系统(许多Linux系统)上,您可以改为使用%m转换说明符:

fprintf(stderr, "something wrong: %m\n");

您通常应该向stderr输出错误消息(请参阅stderr(3));另请参阅syslog(3)以使用系统日志记录。

不要忘记使用\n结束格式字符串,因为stderr通常是行缓冲的(但有时不是)或者使用fflush(3)

例如,您可能希望在fopen失败时显示错误,文件名和当前目录:

char* filename = somefilepath();
assert (filename != NULL);
FILE* f = fopen(filename, "r");
if (!f) {
   int e = errno; // keep errno, it could be later overwritten
   if (filename[0] == '/') /// absolute path
      fprintf(stderr, "failed to open %s : %s\n", filename, strerror(e));
   else { // we also try to show the current directory since relative path
      char dirbuf[128];
      memset (dirbuf, 0, sizeof(dirbuf));
      if (getcwd(dirbuf, sizeof(dirbuf)-1)) 
         fprintf(stderr, "failed to open %s in %s : %s\n", 
                 filename, dirbuf, sterror(e));
      else // unlikely case when getcwd failed so errno overwritten
         fprintf(stderr, "failed to open %s here : %s\n", 
                 filename, sterror(e));
   };
   exit(EXIT_FAILURE); // in all cases when fopen failed
 }

请记住,errno可能被许多失败所覆盖(因此我们会将其存储在e中,在getcwd失败并覆盖errno的情况下。

如果您的程序是守护程序(例如已调用daemon(3)),您最好使用系统日志(即在调用daemon后调用openlog(3) daemon可以将 stderr 重定向到/dev/null

答案 3 :(得分:1)

有三个标准流stdin stdout stderr。您可以refer了解不同流的重要性。

对于错误消息和诊断,使用stderr在stderr上打印 使用了 Perror 。 printf无法做到这一点。 Perror还用于处理来自系统调用的错误

fd = open (pathname, flags, mode);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}

您可以在书籍The linux programming interface

中详细了解相关信息

void perror(const char *s)

Perror按以下顺序打印消息:

s的参数,冒号,空格,有关错误的短消息,其错误代码目前位于errno和换行符

在标准C中,如果s为空指针,则仅打印消息。其他事情将被忽略

要了解更多信息,您还可以参考The complete reference C

的第332页

答案 4 :(得分:1)

使用perror()的一大优势:

有时将 stdout 重定向到 / dev / null 只能访问错误非常有用,因为stdout的详细程度可能会隐藏我们需要修复的错误

答案 5 :(得分:-1)

PERROR

该函数的一般用途是由于错误而暂停执行过程。 perror生成的错误消息是依赖于平台的。您也可以打印自己的错误消息。

的printf

该功能的一般用途是打印用户定义的消息并继续执行。