对不起我的代码差,但是当我在Mac终端运行时,我不明白为什么此代码会导致segmentation fault 11
。我想通过使用链接列表来使程序读取完整的句子完整,但行不通。我猜some.txt
中的句子未插入linkNode
中。我该如何修复?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_NUMBER 1024
typedef struct linkNode {
char *element;
struct linkNode *link;
} linkNode;
typedef struct {
linkNode *top;
int element_number;
} linkType;
void error(char* message) {
fprintf(stderr, "%s", message);
}
void init(linkType *L) {
L->top = NULL;
L->element_number = 0;
}
linkNode *createStack() {
linkNode *temp = (linkNode *) malloc(sizeof(linkNode));
temp->element = (char *) malloc(sizeof(char) * MAX_NUMBER + 1);
return temp;
}
void insert(linkType *L, char* new_data) {
linkNode *temp = createStack();
//temp->element = new_data;
strcpy(temp->element, new_data);
temp->link = L->top;
L->element_number++;
L->top = temp->link;
}
char *delete(linkType *L) {
if (L->element_number == 0) {
error("list emptyn");
}
linkNode *temp = L->top;
char * temp_element;
//temp->element = L->top->element;
strcpy(temp_element, L->top->element);
L->top = L->top->link;
L->element_number--;
free(temp);
return temp_element;
}
char *buffer_making() {
char *buffer = (char *) malloc(sizeof(char) * MAX_NUMBER + 1);
return buffer;
}
char *buffer_erase(char *buffer) {
free(buffer);
return NULL;
}
int main() {
linkType *q = (linkType *) malloc(sizeof(linkType));
init(q);
FILE *file_pointer;
char *file1;
file1 = (char *) malloc(sizeof(file1) + 1);
char *file2;
file2 = (char *) malloc(sizeof(file2) + 1);
printf("input file names:n");
scanf("%s", file1);
getchar();
file_pointer = fopen(file1, "r");
while (!feof(file_pointer)) {
char *buffer1 = buffer_making();
fscanf(file_pointer,"%s",buffer1);
///////////
printf("%sn",buffer1);
insert(q,buffer1);
buffer_erase(buffer1);
}
printf("point3n");
while (!(q->element_number == 0)) {
printf("%sn", delete(q));
}
free(file1);
free(file2);
return 0;
}
//printf("point1n");
您的代码有很多不同的问题。让我们一对一地通过它们:
bottom
的linkNode
指针添加到您的linkType
结构中:
typedef struct {
linkNode *top;
linkNode *bottom;
int element_number;
} linkType;
和init
功能中的bottom
初始化:
void init(linkType *L) {
L->top = NULL;
L->bottom = NULL;
L->element_number = 0;
}
insert
函数中,temp
是要附加到列表末尾的新节点(如果我正确理解您的问题(,因此您需要将其link
指向NULL
而不是top
。另外,您不应将top
指向temp->link
。如果这是您插入的第一个节点,则top
和bottom
都应指向temp
,否则top
将继续指向第一个节点,并且需要更新bottom
,以便它指向temp
:
> void insert(linkType *L, char *new_data) {
linkNode *temp = createStack();
strcpy(temp->element, new_data);
temp->link = NULL;
L->element_number++;
if (L->top == NULL) {
L->top = temp;
L->bottom = temp;
} else {
L->bottom->link = temp;
L->bottom = temp;
}
}
delete
功能中,您无需将整个字符串从element
复制到temp_element
;您可以将temp_element
指向element
。另外,您无法正确降低element_number
。delete
功能应该看起来像:
char *delete(linkType *L) {
if (L->element_number == 0) {
error("list emptyn");
}
linkNode *temp = L->top;
char *temp_element;
temp->element = L->top->element;
L->top = L->top->link;
(L->element_number)--;
free(temp);
return temp_element;
}
main
功能中,您没有正确读取输入文件。fscanf
扫描单词,但是由于您想提取句子而不是单词,因此fgetc
将是一种更好的方法。while
读取的循环应该看起来像:
int isEof = 0;
int isEndOfSentence = 0;
int index = 0;
while (!isEof) {
char *buffer1 = buffer_making();
isEndOfSentence = 0;
index = 0;
while (!isEndOfSentence) {
char c = fgetc(file_pointer);
if (c == EOF) {
isEndOfSentence = 1;
isEof = 1;
} else if (c == '.') {
isEndOfSentence = 1;
}
// Skip leading whitespace
if ((isEof || c == ' ' || c == 'n') && index == 0) {
continue;
}
buffer1[index++] = c;
}
// Skip empty sentence
if (index == 0) {
continue;
}
buffer1[index] = ' ';
printf("%sn", buffer1);
insert(q, buffer1);
buffer_erase(buffer1);
}
这不是实现阅读句子的最佳方法,但它有效。另外,此代码假定句子以.
结束。您可以更新此代码以使其适用于?
,!
等结尾的句子
element
的while
循环似乎存在一些问题。您可以使用以下while
循环:
while (!(q->element_number == 0)) {
printf("%sn", q->top->element);
delete(q);
}
希望这会有所帮助。我已经测试了这些更改,它们对我有用。
来自 valgrind
:
==18918== Conditional jump or move depends on uninitialised value(s)
==18918== at 0x4C2E119: strlen (vg_replace_strmem.c:458)
==18918== by 0x4EA4E81: puts (in /lib64/libc-2.25.so)
==18918== by 0x108BE8: main (ll.c:74)
==18918==
==18918== Conditional jump or move depends on uninitialised value(s)
==18918== at 0x4C2E1FB: strcpy (vg_replace_strmem.c:510)
==18918== by 0x108A49: insert (ll.c:31)
==18918== by 0x108BFB: main (ll.c:75)
==18918==
==18918== Invalid read of size 8
==18918== at 0x108AB1: delete (ll.c:44)
==18918== by 0x108C31: main (ll.c:82)
==18918== Address 0x0 is not stack'd, malloc'd or (recently) free'd
GCC还报告了-Wall
的问题:
ll.c: In function ‘delete’:
ll.c:44:5: warning: ‘temp_element’ is used uninitialized in this function [-Wuninitialized]
strcpy(temp_element,L->top->element);
一个问题是您正在调用strcpy
而不为目的地分配内存。另一个问题是您在不验证其非NULL
的情况下取消L->top
。
与我的朋友的帮助,我可以在终端中正确打印出来!特别感谢那些回答我问题的人!谢谢你!
实际上我真正想要的只是链接列表,仅由linkNode *top表示,我编辑了我的预期。:)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_NUMBER 1024
typedef struct linkNode{
char * element;
struct linkNode * link;
}linkNode;
typedef struct{
linkNode *top;
int element_number;
}linkType;
void error(char* message){
fprintf(stderr,"%s", message);
}
void init(linkType *L){
L->top=NULL;
L->element_number = 0;
}
linkNode * createStack(){
linkNode * temp = (linkNode *)malloc(sizeof(linkNode));
temp->element = (char *)malloc(sizeof(char)*MAX_NUMBER+1);
return temp;
}
void insert(linkType *L,char* new_data){
linkNode *temp = createStack();
//temp->element = new_data;
strcpy(temp->element,new_data);
temp -> link = NULL;
L->element_number++;
if(L->top ==NULL){
L->top =temp;
}
else{
temp->link = L->top;
L->top = temp;
}
}
char * delete(linkType *L){
if(L->element_number ==0)
{
error("list emptyn");
}
linkNode *temp = NULL;
temp = L->top;
char * temp_element;
temp->element = L->top->element;
L->top = L->top->link;
(L->element_number)--;
free(temp);
return temp_element;
}
char * buffer_making(){
char* buffer = (char *)malloc(sizeof(char)*MAX_NUMBER+1);
return buffer;
}
char * buffer_erase(char * buffer){
free(buffer);
return NULL;
}
int main(){
linkType q ;
init(&q);
FILE *file_pointer;
char * file1;
file1 = (char*)malloc(sizeof(file1)+1);
char * file2;
file2 = (char*)malloc(sizeof(file2)+1);
printf("input file names:n");
scanf("%s",file1);
getchar();
file_pointer=fopen(file1,"r");
while(1){
char * buffer1 = buffer_making();
if(fscanf(file_pointer,"%s",buffer1)==EOF) break;
///////////
printf("%sn",buffer1);
insert(&q,buffer1);
buffer_erase(buffer1);
}
printf("point3n");
while(!(q.element_number==0))
{
printf("%sn", q.top->element);
delete(&q);
}
free(file1);
free(file2);
return 0;
}