[英]To count the total number of lines in a file using Unix system call in C
我是 C 語言的初學者,unix 沒有太多經驗。 我正在嘗試使用 unix 系統調用計算文件內的總行數,但沒有得到任何結果。 我的 lineCount 總是顯示為 0 我不知道為什么? 如果可能的話,我希望有人幫我算出行數。謝謝
int lineCount = 0;
while (*buffer != '\0') // to check the end of the file
{
read( in_fd, buffer, BUFFERSZ);
if (*buffer == '\n')
{
lineCount++;
}
}
printf("Linecount: %i \n", lineCount );
使用open
、 read
和write
與使用fopen
、 fread
和fwrite
(或fgets
和fprintf
)實際上沒有太大區別,除了任何轉換、字節計數和設置創建的文件權限位的負擔都在你身上。 當write
將諸如1020
的值寫入文件時,它正在寫入您告訴它寫入的bytes
數,並且該數字將以與您的硬件使用的相同字節順序存在於文件中。
例如,如果您有unsigned v = 1020;
( 0x3fc
in hex) 然后write (fd, &v, sizeof v);
, 當您使用hexdump
或od
(或類似)查看您的文件時,它將包含fc 03 00 00
(假設您的硬件是小端)。 這些是您的4-bytes
unsigned
值1020
。 您無法在文本編輯器中打開文件並期望看到 ASCII 字符,因為這不是寫入文件的內容。
要使用open
和read
查找文件中的行數,您基本上要open
文件,將文件一次讀入緩沖區一些合理數量的字節並計算文件中的'\\n'
字符。
(注意:您還需要檢查從文件中讀取的最后一個字符是否不是'\\n'
。如果是,您需要將+1
添加到您的行數以考慮非 POSIX 行最后一行的結尾。)
唯一的其他警告是注意您open
用於寫入的任何新創建文件的mode
(權限)。 否則,您會發現自己無法訪問新創建的文件。 這就是為什么在提供O_CREAT
標志的情況下 open 提供mode_t mode
作為第三個參數的原因。
如果您打算堅持只對程序 I/O 使用open, read, write
,那么您將必須在出現錯誤時向終端STDERR_FILENO
提供錯誤消息輸出。 您可能需要一個簡短的輔助函數來為此目的編寫字符串消息。
將各個部分放在一起,您可以在忠於自己的事業的同時執行以下操作。 以下代碼將infile
和outfile
名稱作為程序的前兩個參數,一次讀取infile
65K bytes
,計算文件中的'\\n'
數,然后將結果寫入outfile
占任何非 POSIX 行文件結束。 writeliteral
作為錯誤消息的幫助程序提供:
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
enum { BUFFERSZ = 1 << 16 }; /* 65K buffer size */
void writeliteral (int fildes, const char *s);
int main (int argc, char **argv) {
if (argc < 3) {
writeliteral (STDERR_FILENO, "error: insufficient input.\n");
writeliteral (STDERR_FILENO, "usage: progname infile outfile\n");
return 1;
}
char buf[BUFFERSZ] = "";
unsigned i = 0, nlines = 0;
ssize_t n = 0;
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
int fd = open (argv[1], O_RDONLY);
if (fd == -1) { /* validate file open for reading */
writeliteral (STDERR_FILENO, "error: infile open failed.\n");
return 1;
}
while ((n = read (fd, buf, sizeof buf)) > 0) /* read 65k chars */
for (i = 0; i < n; i++) /* count newlines in buf */
if (buf[i] == '\n')
nlines++;
if (buf[i - 1] != '\n') /* account for non-POSIX line end */
nlines++;
close (fd); /* close file */
/* open outfile for writing, create if it doesn't exist */
if ((fd = open (argv[2], O_WRONLY | O_CREAT, mode)) == -1) {
writeliteral (STDERR_FILENO, "error: outfile open failed.\n");
return 1;
}
write (fd, &nlines, sizeof nlines); /* write nlines to outfile */
close (fd); /* close file */
return 0;
}
/** write a string literal to 'fildes' */
void writeliteral (int fildes, const char *s)
{
size_t count = 0;
const char *p = s;
for (; *p; p++) {}
count = p - s;
write (fildes, s, count);
}
示例輸入文件
$ nl -ba ../dat/captnjack.txt
1 This is a tale
2 Of Captain Jack Sparrow
3 A Pirate So Brave
4 On the Seven Seas.
示例使用/輸出
$ ./bin/readwrite_lineno ../dat/captnjack.txt ../dat/jacklines.dat
$ hexdump -n 16 -C ../dat/jacklines.dat
00000000 04 00 00 00 |....|
00000004
看看它,如果您有任何問題,請告訴我。 它向您展示了為什么您在完成后可能會更喜歡printf
系列函數格式說明符。
您的代碼只檢查*buffer
的換行符,這是您讀取的每個BUFFERSZ
塊的第一個字符,即您的代碼甚至不查看大部分輸入。 (它也不會正確檢查文件結尾:您需要查看read
的返回值。)
這是一個使用read
模擬fgetc
的簡單解決方案:
size_t lines = 0;
char c;
while (read(in_fd, &c, 1) == 1) {
if (c == '\n') {
lines++;
}
}
printf("Linecount: %zu\n", lines);
如果您也不能使用printf
,一個快速的解決方法是:
static void print_n(size_t n) {
if (n / 10) {
print_n(n / 10);
}
char c = '0' + n % 10;
write(1, &c, 1);
}
...
write(1, "Linecount: ", strlen("Linecount: "));
print_n(lines);
write(1, "\n", 1);
參考: 使用C計算行數使用代碼
FILE *fp = fopen("myfile.txt");
int ch;
int count=0;
do { ch = fgetc(fp);
if( ch== '\n')
count++;
}while( ch != EOF );
printf("Total number of lines %d\n",count);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.