本文共 7141 字,大约阅读时间需要 23 分钟。
LaTeX 没有像 Word 那样自带中文字数统计功能,加上 LaTeX 源文件中有许多控制字符,不能通过文件大小获知其中有多少汉字。为此我用C写了一个统计中文字数的小工具,名为 cwc ,即 chinese word counter。这个程序只有 count_files() 函数使用了 Windows API,稍作修改就能移植到 Linux/Unix 下。
#include <stdio.h>#include <wchar.h>#include <windows.h>int total = 0; // total chinese characters// UNICODE version word countervoid word_count_u(FILE* pf){ int w = 0, b = 2; wint_t c;while((c = getwc(pf)) != WEOF) { b += 2; // byte count if (c > 127) { // 中文字符 w++; // char count } } printf("%10d /t %10d/n", w, b); total += w;}// word countervoid word_count(const char* file){ int w = 0, b = 0; int c; int unicode = 0; FILE *pf = fopen(file, "rb"); if (NULL == pf) { return; } printf ("%20s : ", file); // 判断是否为 UNICODE 文件 if ((c = getc(pf)) == 0xff) { int cc; if ((cc = getc(pf)) == 0xfe) { unicode = 1; printf("UNICODE"); word_count_u(pf); } else { fseek(pf, 0, SEEK_SET); } } else { ungetc(c, pf); } if (!unicode) { printf(" "); while((c = getc(pf)) != EOF) { b++; // byte count if (c > 127) { // 中文字符 w++; // char count b++; // 每个中文字符占两字节 if ((c = getc(pf)) == EOF) break; } } printf("%10d /t %10d/n", w, b); total += w; } fclose(pf);}
void count_files(const char* file){ WIN32_FIND_DATA FindFileData; HANDLE hFind = FindFirstFile(file, &FindFileData);
if (INVALID_HANDLE_VALUE == hFind) { fprintf(stderr, "Can't find %s/n", file); return ; }
do { if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) { continue; } if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { // do nothing } else { word_count(FindFileData.cFileName); } } while (FindNextFile(hFind, &FindFileData));
FindClose(hFind);}
int main(int argc, char* argv[]){ if (1 == argc) { // default: count all .tex and .txt files in current dir count_files("*.tex"); count_files("*.txt"); } else { // get filenames from command line arguments while (--argc > 0) { count_files(argv[argc]); } } printf(" Total : %d", total); return 0;}
另外一个常见的问题是,用 dvipdfm 生成 PDF 文件时,经常忘了在 Acrobat 中关闭这个文件,而导致出现以下错误提示:E:/Projects/SlideWindowReport>dvipdfm SlideWindowSlideWindow.dvi -> SlideWindow.pdf
Unable to open SlideWindow.pdf
Output file removed.为此我写了一个专门用来关闭 Acrobat 中的 PDF 文件的小工具,名为 closepdf,原理是通过 DDE 告诉 Acrobat 关闭某个 PDF 文件。这个小工具的灵感来自 WinEdt 的自动关闭功能(我跟踪它的宏代码得知如何用 DDE 控制 Acrobat),代码改自 MSDN 的一篇文章。我完全不懂 DDE,不过这不妨碍程序的正常工作:)有了这个小工具,我就可以写一个 batch file 来编译生成并阅读 PDF 文件:rem this is m.batlatex %1latex %1closepdf %1.pdfdvipdfm %1 %2 %3 %4 %5start %1.pdf代码如下:// close the user specified pdf file in Acrobat Reader// ref. Microsoft Knowledge Base Article - 279721 // HOWTO: Use Dynamic Data Exchange (DDE) with Word and Excel from Visual C++// modified by Solstice 2004/01/2#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers#define STRICT#include <windows.h>#include <ddeml.h>#include <stdio.h>#include <assert.h>#include <stdlib.h>
HDDEDATA CALLBACK DdeCallback( UINT uType, // Transaction type. UINT uFmt, // Clipboard data format. HCONV hconv, // Handle to the conversation. HSZ hsz1, // Handle to a string. HSZ hsz2, // Handle to a string. HDDEDATA hdata, // Handle to a global memory object. DWORD dwData1, // Transaction-specific data. DWORD dwData2) // Transaction-specific data.{ return 0;}
void DDEExecute(DWORD idInst, HCONV hConv, char* szCommand){ HDDEDATA hData = DdeCreateDataHandle(idInst, (LPBYTE)szCommand, lstrlen(szCommand)+1, 0, NULL, CF_TEXT, 0); if (hData==NULL) { printf("Command failed: %s/n", szCommand); } else { DdeClientTransaction((LPBYTE)hData, 0xFFFFFFFF, hConv, 0L, 0, XTYP_EXECUTE, TIMEOUT_ASYNC, NULL); }}
void DDERequest(DWORD idInst, HCONV hConv, char* szItem, char* sDesc){ HSZ hszItem = DdeCreateStringHandle(idInst, szItem, 0); HDDEDATA hData = DdeClientTransaction(NULL,0,hConv,hszItem,CF_TEXT, XTYP_REQUEST,5000 , NULL); if (hData == NULL) { printf("Request failed: %s/n", szItem); } else { char szResult[255]; DdeGetData(hData, (unsigned char *)szResult, 255, 0); printf("%s%s/n", sDesc, szResult); }}
void DDEPoke(DWORD idInst, HCONV hConv, char* szItem, char* szData){ HSZ hszItem = DdeCreateStringHandle(idInst, szItem, 0); DdeClientTransaction((LPBYTE)szData, (DWORD)(lstrlen(szData)+1), hConv, hszItem, CF_TEXT, XTYP_POKE, 3000, NULL); DdeFreeStringHandle(idInst, hszItem);}
int get_error(const char* filename){ HANDLE hFile = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hFile) { return GetLastError(); } else { CloseHandle(hFile); return 0; }}
bool is_file_locked(const char* filename){ return (get_error(filename) == 32);}
bool is_file_exists(const char* filename){ return (get_error(filename) != 2);}
int main(int argc, char* argv[]){ char szApp[] = "acroview"; char szTopic[] = "control"; char szCloseAll[] = "[CloseAllDocs()]"; char full_file_name[MAX_PATH]; const char* file_to_close = argv[1]; if (argc == 1) { // close all pdf files } else { // close the specified file if (!is_file_exists(file_to_close)) { printf("%s doesn't exists./n", file_to_close); return 1; } if (is_file_locked(file_to_close)) { printf("%s is open, trying to close it.../n", file_to_close); } else { printf("%s is closed./n", file_to_close); return 0; } assert (GetFullPathName( file_to_close, sizeof(full_file_name), full_file_name, NULL ) > 0); //printf("Full name : /"%s/"/n", full_file_name); } //[DocOpen(""%P/%N.pdf"")] //[DocClose(""%P/%N.pdf"")]
//DDE Initialization DWORD idInst=0; UINT iReturn; iReturn = DdeInitialize(&idInst, (PFNCALLBACK)DdeCallback, APPCLASS_STANDARD | APPCMD_CLIENTONLY, 0 ); if (iReturn!=DMLERR_NO_ERROR) { printf("DDE Initialization Failed: 0x%04x/n", iReturn); Sleep(1500); return 0; }
//DDE Connect to Server using given AppName and topic. HSZ hszApp, hszTopic; HCONV hConv; hszApp = DdeCreateStringHandle(idInst, szApp, 0); hszTopic = DdeCreateStringHandle(idInst, szTopic, 0); hConv = DdeConnect(idInst, hszApp, hszTopic, NULL); DdeFreeStringHandle(idInst, hszApp); DdeFreeStringHandle(idInst, hszTopic); if (hConv == NULL) { printf("DDE Connection Failed./n"); Sleep(500); DdeUninitialize(idInst); return 0; } else { printf("DDE Connection to Acrobat Reader succeed./n"); Sleep(50); } if (argc == 1) { // close all pdf files //Execute commands/requests specific to the DDE Server. DDEExecute(idInst, hConv, szCloseAll); printf("Closing all PDF documents.../n"); Sleep(50); } else { // close the specified file char cmd_buf[MAX_PATH + 100]; //[DocOpen(""%P/%N.pdf"")] //[DocClose(""%P/%N.pdf"")] printf("Closing %s /n", full_file_name); snprintf(cmd_buf, sizeof(cmd_buf), "[DocOpen(/"%s/")]", full_file_name); DDEExecute(idInst, hConv, cmd_buf); Sleep(50); snprintf(cmd_buf, sizeof(cmd_buf), "[DocClose(/"%s/")]", full_file_name); DDEExecute(idInst, hConv, cmd_buf); Sleep(50); }
//DDE Disconnect and Uninitialize. DdeDisconnect(hConv); DdeUninitialize(idInst); if (argc == 1) { // close all pdf files return (0); }
for (int i = 0; i < 5; ++i) { Sleep(100); if (!is_file_locked(file_to_close)) break; } if (!is_file_locked(file_to_close)) { printf("%s is closed./n", file_to_close); return 0; } else { printf("%s is still open./n", file_to_close); return 1; }}
转载地址:http://nqvpi.baihongyu.com/