以下代碼應該讀取檔案“rules.txt”并將其逐行寫入設備。流程應該是:
- 從 rules.txt 讀取行
- 將其回顯到設備
由于 readline,以下代碼總是以段錯誤結尾,我不知道為什么:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>
#define BUFFER_LENGTH 256
int main()
{
char *line;
size_t len = BUFFER_LENGTH;
int fd = open("./rules.txt", O_RDONLY);
if(fd == -1)
{ perror("open failed"); return 0; }
FILE* fout = fopen("/sys/class/Rule_Table_Class/Rule_Table_Class_Rule_Table_Device/sysfs_att", "w ");
if(fout == NULL)
{ close(fd); perror("fopen failed, log.txt is busy!"); return 0; }
while (1)
{
line = (char*) malloc(len*sizeof(char));
if(line==NULL){
perror("malloc failed!"); return 0;
}
int bytesRead = getline(&line, &len, fd);
if (bytesRead == -1)
{
perror("Failed to read the message from the device.");
return errno;
}
sprintf(line,"%s","lala");
printf("line = %s", line);
}
fclose(fout);
close(fd);
return 0;
}
編輯:
我更正了代碼,但仍然出現段錯誤。這是更正后的代碼:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>
#define BUFFER_LENGTH 256
int main()
{
FILE * fp;
char * line = NULL;
size_t len = 0;
ssize_t read;
fp = fopen("./rules.txt", "r");
if(fp == NULL)
{ perror("open failed"); return 0; }
FILE* fout = fopen("/sys/class/Rule_Table_Class/Rule_Table_Class_Rule_Table_Device/sysfs_att", "w ");
if(fout == NULL)
{ perror("fopen failed!"); return 0; }
while (1)
{
ssize_t bytesRead = getline(&line, &len, fp);
if (bytesRead == -1)
{
return 0;
}
printf("line = %s", line);
fprintf(line,"%s",fout);
}
fclose(fout);
fclose(fp);
return 0;
}
uj5u.com熱心網友回復:
首先,正確的核心getline()回圈是
/* FILE *in = fopen(..., "r"); */
char *line = NULL;
size_t size = 0;
while (1) {
ssize_t len = getline(&line, &size, in);
if (len < 0)
break;
/* You have 'len' chars at 'line', with line[len] == '\0'. */
}
因此,這不是getline()導致段錯誤的原因,而是您fprintf(line, "%s", fout);應該是fprintf(fout, "%s", line);或只是fputs(line, fout);,或者fwrite(line, 1, bytesRead, fout);因為該行可以包含嵌入的 NUL 位元組fprintf()并fputs()考慮字串標記的結尾。
如果我們修改代碼,以便將源檔案名和目標檔案名作為命令列引數(-表示標準輸入或標準輸出),這就是我個人希望看到的:
/* SPDX-License-Identifier: CC0-1.0 */
/* This tells the GNU C library to expose POSIX features, including getline(). */
#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
int main(int argc, char *argv[])
{
if (argc != 3 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
const char *self = (argc > 0 && argv && argv[0] && argv[0][0]) ? argv[0] : "(this)";
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [ -h | --help ]\n", self);
fprintf(stderr, " %s SOURCE TARGET\n", self);
fprintf(stderr, "\n");
fprintf(stderr, "This copies all content from SOURCE to TARGET, line by line.\n");
fprintf(stderr, "Use '-' for standard input source or standard output target.\n");
fprintf(stderr, "\n");
return EXIT_SUCCESS;
}
const char *srcpath = argv[1];
const char *dstpath = argv[2];
/* If the path is "-", set it to NULL. */
if (srcpath && !strcmp(srcpath, "-"))
srcpath = NULL;
if (dstpath && !strcmp(dstpath, "-"))
dstpath = NULL;
FILE *src, *dst;
/* Open source for reading. If srcpath is NULL, use stdin. */
if (srcpath) {
src = fopen(srcpath, "r");
if (!src) {
fprintf(stderr, "%s: %s.\n", srcpath, strerror(errno));
return EXIT_FAILURE;
}
} else {
src = stdin;
}
/* Open target for writing. If dstpath is NULL, use stdout. */
if (dstpath) {
dst = fopen(dstpath, "w");
if (!dst) {
fprintf(stderr, "%s: %s.\n", dstpath, strerror(errno));
fclose(src);
return EXIT_FAILURE;
}
} else {
dst = stdout;
}
char *line = NULL;
size_t size = 0;
unsigned long linenum = 0;
while (1) {
ssize_t len = getline(&line, &size, src);
if (len < 0)
break;
linenum ;
if (fwrite(line, 1, len, dst) != (size_t)len) {
fprintf(stderr, "%s: Write error on line %lu.\n", dstpath ? dstpath : "(standard output)", linenum);
fclose(dst);
fclose(src);
return EXIT_FAILURE;
}
}
/* Technically, we don't need to release dynamically allocated (non-shared) memory,
because we're just about to exit, and the OS will automagically do that for us.
We can do this at any point we want during the loop, too. */
free(line);
line = NULL;
size = 0;
/* We do not know why getline() returned -1. Check if an error occurred, and whether we're at end of input. */
if (ferror(src) || !feof(src)) {
fprintf(stderr, "%s: Read error on line %lu.\n", srcpath ? srcpath : "(standard input)", linenum);
fclose(dst);
fclose(src);
return EXIT_FAILURE;
}
/* Check if any write errors have occurred. */
if (ferror(dst)) {
fprintf(stderr, "%s: Write error on line %lu.\n", dstpath ? dstpath : "(standard output)", linenum);
fclose(dst);
fclose(src);
}
/* Read errors should not occur at close time, but it costs very little for us to test anyway. */
if (fclose(src)) {
fprintf(stderr, "%s: Read error on line %lu.\n", srcpath ? srcpath : "(standard input)", linenum);
fclose(dst);
return EXIT_FAILURE;
}
/* Write errors can occur at close time, if the output has been buffered, or the target is on
a remote filesystem. Again, it costs us very little to check. */
if (fclose(dst)) {
fprintf(stderr, "%s: Write error on line %lu.\n", dstpath ? dstpath : "(standard output)", linenum);
return EXIT_FAILURE;
}
/* No errors; target is an identical copy of the source file. */
fprintf(stderr, "%lu lines copied successfully.\n", linenum);
return EXIT_SUCCESS;
}
該SPDX許可證識別符號是指示代碼的許可證的常用方法。我用的是CC0-1.0,基本上就是“隨心所欲使用,只是不要把任何問題都歸咎于作者:沒有保證,沒有保證”。
在#define _POSIX_C_SOURCE 200809L講述了GNU C庫,我們希望它暴露POSIX.1-2008功能,其中包括getline()。如果您查看man 3 getline,您將在概要部分看到 glibc 2.10 及更高版本需要_POSIX_C_SOURCE至少定義為200809L.
大部分代碼是列印用法,從命令列獲取源檔案和目標檔案名,并-作為特殊名稱處理,“標準流”,這樣即使在管道中也可以通過指定-為輸入和/ 或輸出檔案名。
該getline()回圈使用fwrite()寫一行到目標檔案。這樣,如果輸入包含嵌入的 NUL 位元組 ( \0),目標仍將與源檔案相同。
在回圈之后,我們丟棄了行緩沖區,盡管由于程式即將退出,我們可以省略它(因為當我們退出時,作業系統將釋放所有動態分配的(非共享)記憶體)。
我喜歡檢查輸入ferror(src) || !feof(src)是否發生錯誤src或未src到達輸入末尾的代碼;并檢查 的回傳值fclose(),以防報告延遲(寫入)錯誤。當然,fclose()對于只讀檔案應該永遠不會失敗,并且fclose()應該只會對于我們在特定情況下寫入的檔案失敗,但是檢查成本非常低,這樣運行程式的用戶就會被告知是否檢測到程式資料丟失。
我認為忽略對此類錯誤的檢查在道德上應受到譴責(尤其是“因為它們很少發生”),因為此類測驗是人類用戶了解操作是否成功或是否發生一些奇怪問題的唯一方法。由人類來調查任何問題,由我們的程式報告可檢測到的問題。
uj5u.com熱心網友回復:
該getline函式將 aFILE *作為引數,而不是int。替換以下行:
int fd = open("./rules.txt", O_RDONLY);
經過;
FILE *fin = fopen("./rules.txt", "r");
相應地修復以下行中的錯誤檢查,就像您對fout.
然后替換該行:
int bytesRead = getline(&line, &len, fd);
相反,它現在應該使用fin:
ssize_t bytesRead = getline(&line, &len, fin);
請注意,getline回傳ssize_t,而不是int。您也從未寫信給fout,但我想您仍在處理此代碼。
確保啟用編譯器警告,因為您的編譯器肯定會警告您在預期的int地方使用引數FILE *。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/363025.html
上一篇:將決議的元素從文本檔案添加到陣列
下一篇:將二維陣列復制到另一個二維陣列
