gpt4 book ai didi

c - 从命令行读取最后 10 行的程序中出现段错误

转载 作者:行者123 更新时间:2023-11-30 14:41:40 25 4
gpt4 key购买 nike

我当前正在尝试创建一个程序,用于打印通过命令行传入的另一个文本程序的最后 10 行。函数 read() 应该从文本文件中读取一行,然后返回字符串或 NULL,而主函数应该继续分配 read() 的输出,直到分配 NULL。

我已经尝试过这个程序的许多不同版本,但它总是最终导致段错误。我该如何开始调试段错误?

我已经包含了下面的程序。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *read(){
char *line = (char *) malloc (80 * sizeof(char));
fgets(line,80,stdin);
if (line != NULL) {
line[strlen(line)-1] = '\0';
return line;
}
else {
free(line);
return NULL;
}
}

int main()
{
int i=0,j,k,l;
char **arr = (char **) malloc (100 * sizeof(char *));
for (k = 0; k < 100; k++) {
arr[k] = malloc (80 * sizeof(char));
}

while(1){
strcpy(arr[i],read());
if (arr[i]=NULL) break;
i++;
//printf("%s", arr[i]); //DEBUG
}

for (l = 0; l < 100; l++){
free(arr[l]);
}
free(arr);

for (j = i-11; j < i; j++) {
printf("%s\n", arr[j]);
}
printf("\n");

return 0;
}

最佳答案

while(1){
strcpy(arr[i],read());
if (arr[i]=NULL) break;

你永远不会跳出循环,因为arr[i]=NULL没有理由从read中为真(因为read<中出现错误)/em>),所以你用未定义的行为(你的崩溃)写出arr

您没有很好地管理读取中的文件结尾:

fgets(line,80,stdin);
if (line != NULL) {

您需要检查fgets的结果,而不是line是否为NULL,除了检查malloc成功

并不是说 line[strlen(line)-1] = '\0'; 没有用,因为 fgets 放置了最后一个空字符,幸运的是,否则怎么 strlen 可以工作吗?

所以阅读可以是:

char *read(){
char *line = (char *) malloc (80 * sizeof(char));

if (line != NULL) {
if (fgets(line,80,stdin) == NULL) {
free(line);
return NULL;
}
}

return line;
}

因为读取可能返回 NULL,所以您需要更改

  strcpy(arr[i],read());

这也是为什么您在预分配行的同时也在 read 中分配的原因?目前,您丢失了每次读取时分配的内存

将循环替换为

似乎更好
while((arr[i] == read()) != NULL)
//printf("%s", arr[i]); //DEBUG
i += 1;
}

并删除行的预分配

另一个问题是当文件超过 100 行时(或者可能是某些行在太长时间之前被剪切),在这种情况下,您将写出 arr。事实上你不需要保存那么多行,最多只需要保存10行

<小时/>

建议:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *read() {
char line[80];

if (fgets(line, 80, stdin) == NULL)
return NULL;

return strdup(line);
}

int main()
{
char * arr[10] = { NULL };
char * p;
int i = 0, n = 0;

while((p = read()) != NULL) {
n += 1;
free(arr[i]);
arr[i] = p;
if (++i == 10)
i = 0;
}

/* get older line index and line count to print */
if (n <= 10)
i = 0;
else
n = 10;

while (n-- != 0) {
puts(arr[i]);
free(arr[i]);
if (++i == 10)
i = 0;
}

return 0;
}

Compilation and execution :
pi@raspberrypi:/tmp/d $ gcc -g -pedantic -Wextra q.c
pi@raspberrypi:/tmp/d $ ./a.out < q.c
n = 10;



while (n-- != 0) {

puts(arr[i]);

if (++i == 10)

i = 0;

}



return 0;

}

注意,我没有删除\n是读取行,并且我使用puts,因此会打印空行,而读取行不会因为太长而被剪切

如果文件少于 10 行:

pi@raspberrypi:/tmp/d $ tail -n 5 q.c | ./a.out
i = 0;

}



return 0;

}

valgrind 下:

pi@raspberrypi:/tmp/d $ valgrind ./a.out < q.c
==18496== Memcheck, a memory error detector
==18496== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==18496== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==18496== Command: ./a.out
==18496==


while (n-- != 0) {

puts(arr[i]);

free(arr[i]);

if (++i == 10)

i = 0;

}



return 0;

}

==18496==
==18496== HEAP SUMMARY:
==18496== in use at exit: 0 bytes in 0 blocks
==18496== total heap usage: 43 allocs, 43 frees, 5,699 bytes allocated
==18496==
==18496== All heap blocks were freed -- no leaks are possible
==18496==
==18496== For counts of detected and suppressed errors, rerun with: -v
==18496== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)

关于c - 从命令行读取最后 10 行的程序中出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54845146/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com