使用 C 打印指向字符串的指针数组,省略最后一个字符串
Printing an array of pointers to strings using C leaves out the last string
我想创建一个指向从 C 文件中读取的字符串的指针数组。但是,当我尝试打印出复制到 stdout
的字符串时,文件的最后一行总是被遗漏.
该程序有时也会遇到 segmentation fault
,我无法完全消除。大约 5 次中有 2 次发生。
这是我的 input.c
代码:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "input.h"
#define MAXLINES 5000
void writelines(char *arr[], int l);
char *read_lines[MAXLINES];
void get_input(const char *fp) {
FILE *contents;
char *line;
char *temp;
size_t len;
ssize_t read;
int i;
i = 0;
contents = fopen(fp, "r");
if (contents == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, contents)) != -1) {
if ((temp = (char *) malloc(strlen(line) + 1)) == NULL) {
printf("Could not allocate required memory.");
exit(EXIT_FAILURE);
}
else {
line[strlen(line) - 1] = '[=10=]';
strcpy(temp, line);
read_lines[i++] = temp;
}
}
fclose(contents);
free(line);
free(temp);
writelines(read_lines, i);
exit(EXIT_SUCCESS);
}
void writelines(char *arr[], int l) {
int i;
for (i = 0; i < l; i++) {
printf("%s\n", arr[i]);
}
}
我的 main.c
文件是:
#include <stdio.h>
#include "input.h"
int main(int argc, char *argv[]) {
if (argc == 1)
printf("Please provide a valid source code file.\n");
else
get_input(*(++argv));
return 0;
}
我使用 gcc main.c input.c -Wall
编译,没有警告或错误。
使用gdb
我可以确认进程正常运行。
当它遇到分段错误时,回溯显示对 strlen
的调用显然失败了。
来自 documentation:
If *lineptr is NULL, then getline() will allocate a buffer for storing the line, which should be freed by the user program. (In this case, the value in *n is ignored.)
但在您的情况下,您是第一次将 未初始化的 值传递给 getline
,因此 getline
认为它可以写入该非法位置这是 未定义的行为(这解释了 "It happens about 2 out of 5 times" 的事情)
第一个修复应该是初始化 line
:
char *line = NULL;
那么,为什么要创建 line
的 copy 而你没有释放 line
(内存泄漏)而且你没有将其重置为 NULL
。所以下次 getline
重用之前的缓冲区,它可能不够长以容纳下一行。
修复只是存储行:
read_lines[i++] = line;
然后设置 line = NULL
以便 getline
为下一行分配适当的长度。并且丢掉malloc
代码,没用。
固定部分(您不需要在 len
上传递指针,它会被忽略):
line = NULL;
while ((read = getline(&line, NULL, contents)) != -1) {
read_lines[i++] = line;
line[strcspn(line, "\n")] = 0; // strip off linefeed if there's one
line = NULL;
}
(改编自 Removing trailing newline character from fgets() input 的换行条)
我想创建一个指向从 C 文件中读取的字符串的指针数组。但是,当我尝试打印出复制到 stdout
的字符串时,文件的最后一行总是被遗漏.
该程序有时也会遇到 segmentation fault
,我无法完全消除。大约 5 次中有 2 次发生。
这是我的 input.c
代码:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "input.h"
#define MAXLINES 5000
void writelines(char *arr[], int l);
char *read_lines[MAXLINES];
void get_input(const char *fp) {
FILE *contents;
char *line;
char *temp;
size_t len;
ssize_t read;
int i;
i = 0;
contents = fopen(fp, "r");
if (contents == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, contents)) != -1) {
if ((temp = (char *) malloc(strlen(line) + 1)) == NULL) {
printf("Could not allocate required memory.");
exit(EXIT_FAILURE);
}
else {
line[strlen(line) - 1] = '[=10=]';
strcpy(temp, line);
read_lines[i++] = temp;
}
}
fclose(contents);
free(line);
free(temp);
writelines(read_lines, i);
exit(EXIT_SUCCESS);
}
void writelines(char *arr[], int l) {
int i;
for (i = 0; i < l; i++) {
printf("%s\n", arr[i]);
}
}
我的 main.c
文件是:
#include <stdio.h>
#include "input.h"
int main(int argc, char *argv[]) {
if (argc == 1)
printf("Please provide a valid source code file.\n");
else
get_input(*(++argv));
return 0;
}
我使用 gcc main.c input.c -Wall
编译,没有警告或错误。
使用gdb
我可以确认进程正常运行。
当它遇到分段错误时,回溯显示对 strlen
的调用显然失败了。
来自 documentation:
If *lineptr is NULL, then getline() will allocate a buffer for storing the line, which should be freed by the user program. (In this case, the value in *n is ignored.)
但在您的情况下,您是第一次将 未初始化的 值传递给 getline
,因此 getline
认为它可以写入该非法位置这是 未定义的行为(这解释了 "It happens about 2 out of 5 times" 的事情)
第一个修复应该是初始化 line
:
char *line = NULL;
那么,为什么要创建 line
的 copy 而你没有释放 line
(内存泄漏)而且你没有将其重置为 NULL
。所以下次 getline
重用之前的缓冲区,它可能不够长以容纳下一行。
修复只是存储行:
read_lines[i++] = line;
然后设置 line = NULL
以便 getline
为下一行分配适当的长度。并且丢掉malloc
代码,没用。
固定部分(您不需要在 len
上传递指针,它会被忽略):
line = NULL;
while ((read = getline(&line, NULL, contents)) != -1) {
read_lines[i++] = line;
line[strcspn(line, "\n")] = 0; // strip off linefeed if there's one
line = NULL;
}
(改编自 Removing trailing newline character from fgets() input 的换行条)