linux C段错误

ocean_whut 2010-06-30 10:39:39
写一个文本格式化程序可以处理一个输入文件,它按照用户指定的下列版面规格参数重排版面:实现页内调整、分段、分页等文本处理功能,排版结果存入输出文本文件中。
(1)输出文件中字与字之间只留一个空格符,即实现多余空格符的压缩。
(2)输出文件中,任何完整的字不能分割在两行,行尾可以不齐,但行首要对齐。
(3)将页号印在页底空行中第2行的中间位置上。
(4) 版面要求的参数要包含:
页长(Page Length)——每页内文字(不计页号)的行数。
页宽(Page Wedth)——每行内文字所占最大字符数。
左空白(Left Margin)——每行文字前的固定格数。
头长(Heading Length)——每页页顶所空行数。
脚长(Footing Length)——每页页底所空行数(含页号行)
起始页号(Starting Page Number)——首页的页号。
我写的程序老是段错误,但代码看了好多遍看不出问题出在哪里,请大家指教:

#include<stdio.h>
#define WORD_MAX 20

int main()
{int foot_length;
int head_length;
int page_wedth;
int page_length;
int left_margin;
char start_num;
int c;
char word[WORD_MAX];
int i;
int j;
int char_counter=0;
int line_counter=0;
foot_length=3;
head_length=2;
page_wedth=70;
page_length=5;
left_margin=2;
start_num=1+'0';

FILE *fp1=NULL;
FILE *fp2=NULL;
fp1=fopen("old","r");
fp2=fopen("formatone","w");

for(j=0;j<head_length;j++) //输出头长
fputc('\n',fp2);

for(j=0;j<left_margin;j++) //输出左空白
{fputc(' ',fp2);
char_counter++;
}
c=fgetc(fp1);
while(c!=EOF)
{
i=0;

while(c==' ' || c=='\n')
c=fgetc(fp1);
while(c!=' ' && c!='\n') //将一个单词放入数组word[]
{word[i++]=c;
c=fgetc(fp1);
}

if(i<=page_wedth-char_counter) //如果剩余长度足够输出单词,则输出
{for(j=0;j<i;j++)
{fputc(word[j],fp2);
char_counter++;
}
fputc(' ',fp2);
char_counter++;
}

else //剩余长度不够输出单词
{
fputc('\n',fp2);
line_counter++;
char_counter=0;
if(line_counter<page_length) //此页未结束。
{ for(j=0;j<left_margin;j++)
{fputc(' ',fp2);
char_counter++;
}
for(j=0;j<i;j++)
{fputc(word[j],fp2);
char_counter++;
}
fputc(' ',fp2);
char_counter++;
}
else //此页已结束。

{fputc('\n',fp2);
for(j=0;j<(page_wedth/2);j++)
fputc(' ',fp2);
fputc(start_num++,fp2);
for(j=2;j<foot_length;j++)
fputc('\n',fp2);

line_counter=0;
for(j=0;j<head_length;j++)
fputc('\n',fp2);

for(j=0;j<left_margin;j++)
{fputc(' ',fp2);
char_counter++;
}
for(j=0;j<i;j++)
{fputc(word[j],fp2);
char_counter++;
}
fputc(' ',fp2);
char_counter++;

} //small else,此页已结束那个。


} //big else

c=fgetc(fp1);
} //while(c!=EOF)


printf("its the end!\n");
fclose(fp1);
fclose(fp2);
return 0;
}

gcc可以编译,但执行时显示“段错误”。gdb提示
Program received signal SIGSEGV, Segmentation fault.
0x08048756 in main () at main.c:44
44 {word[i++]=c;
(gdb)
另,若在small else那个}之前加break;让它执行完就跳出,可以正常输出第一页和第二页的第一个单词。
附:我old文本的内容:
The use of silence in communication is different from culture to culture. Silence can communicate agreement, confusion, respect, sadness, or any number of meanings.
In eastern cultures, silence has long been regarded as a virtue. While in western cultures, silence has generally been considered socially disagreeable.
To most people in the United States, silence The use of silence The use of silence in communication is different from culture to culture. Silence can communicate agreement, confusion, respect, sadness, or any number of meanings.
In eastern cultures, silence has long been regarded as a virtue. While in western cultures, silence has generally been considered socially disagreeable.
To most people in the United States, silence The use of silence The use of silence in communication is different from culture to culture. Silence can communicate agreement, confusion, respect, sadness, or any number of meanings.
In eastern cultures, silence has long been regarded as a virtue. While in western cultures, silence has generally been considered socially disagreeable.
To most people in the United States, silence The use of silence The use of silence in communication is different from culture to culture. Silence can communicate agreement, confusion, respect, sadness, or any number of meanings.
In eastern cultures, silence has long been regarded as a virtue. While in western cultures, silence has generally been considered socially disagreeable.
To most people in the United States, silence The use of silence The use of silence in communication is different from culture to culture. Silence can communicate agreement, confusion, respect, sadness, or any number of meanings.
In eastern cultures, silence has long been regarded as a virtue. While in western cultures, silence has generally been considered socially disagreeable.
To most people in the United States, silence The use of silence The use of silence in communication is different from culture to culture. Silence can communicate agreement, confusion, respect, sadness, or any number of meanings.
In eastern cultures, silence has long been regarded as a virtue. While in western cultures, silence has generally been considered socially disagreeable.
To most people in the United States, silence The use of silence The use of silence in communication is different from culture to culture. Silence can communicate agreement, confusion, respect, sadness, or any number of meanings.
In eastern cultures, silence has long been regarded as a virtue. While in western cultures, silence has generally been considered socially disagreeable.
To most people in the United States, silence The use of silence The use of silence in communication is different from culture to culture. Silence can communicate agreement, confusion, respect, sadness, or any number of meanings.
In eastern cultures, silence has long been regarded as a virtue. While in western cultures, silence has generally been considered socially disagreeable.
To most people in the United States, silence The use of silence
...全文
675 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
ocean_whut 2010-07-10
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 ajaxhe 的回复:]
额,好像上面有人已经提出解决方案了,尴尬~就当是过来打打酱油吧~^_^
[/Quote]
thank u all the same~
ajaxhe 2010-07-05
  • 打赏
  • 举报
回复
额,好像上面有人已经提出解决方案了,尴尬~就当是过来打打酱油吧~^_^
ajaxhe 2010-07-05
  • 打赏
  • 举报
回复
还是这句:

while(c!=' ' && c!='\n') //将一个单词放入数组word[]
{word[i++]=c;
c=getc(fp1);
}
的问题,若后面最后一个单词后面还有若干空格或是回车符,这就成了一个死循环了,于是就有了段错误。
解决方案1:格式化old文件,即最后一个单词后面不能接任何空格或回车符,这样不用改程序,程序也会正常运行
解决方案2:将循环改成:
while(c!=' ' && c!='\n' && c!=EOF) //将一个单词放入数组word[]

{word[i++]=c;
c=getc(fp1);
}
问题也可以解决了
easyccoder 2010-07-04
  • 打赏
  • 举报
回复
这个好,学习了。。
durant 2010-07-03
  • 打赏
  • 举报
回复
每天回帖即可获得10分可用分!小技巧:教您如何更快获得可用分
unionxd 2010-07-03
  • 打赏
  • 举报
回复
一般都是访问了NULL~~
cattycat 2010-07-03
  • 打赏
  • 举报
回复
没仔细看代码,如果用的fgetc肯定要判断是否到文件尾部了。所以得加上c!=EOF.
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 ocean_whut 的回复:]
引用 14 楼 huiyongwang1 的回复:

你的程序还有隐含的大错误,那就是如果前一次存储的单词长度如果是20个,这次存储的单词长度是15个,那么按照你的程序,输出到fp2文件中的单词则会是本次15个字符加上上次的后5个字符,如此程序中会有很多重复字符。

我后面输出单词时是按照单词长度i输出的

C/C++ code

{for(j=0;j<i;j++)
……
[/Quote]


好像是你说的这样,不过还是建议你在对数组元素赋值后,一定要加结束符。不然的话,你可以跟踪看看,数组中从单词长度i之后依然有元素存在,虽然你没有访问。
ocean_whut 2010-07-03
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 yanran_hill 的回复:]

引用楼主 ocean_whut 的回复:
while(c!=EOF)
{
i=0;
word=(char *)malloc(WORD_MAX*sizeof(char));
while(c==' ' || c=='\n')
c=fgetc(fp1);
while(c!=' ' && c!='\n') //将一个单词放入数组word[]
{


……
[/Quote]
第一个while是为了去掉多余的空白,第二个while是往数组里读单词。
ocean_whut 2010-07-03
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 huiyongwang1 的回复:]

你的程序还有隐含的大错误,那就是如果前一次存储的单词长度如果是20个,这次存储的单词长度是15个,那么按照你的程序,输出到fp2文件中的单词则会是本次15个字符加上上次的后5个字符,如此程序中会有很多重复字符。
[/Quote]
我后面输出单词时是按照单词长度i输出的

{for(j=0;j<i;j++)
{fputc(word[j],fp2);
char_counter++;
}

即使前一个长度是20,这次15,因为i是15,还是只会输出这15个字符,不会输出后5个
liutengfeigo 2010-07-03
  • 打赏
  • 举报
回复
接分升星星
ocean_whut 2010-07-03
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 huiyongwang1 的回复:]

错误之处:
while(c!=' ' && c!='\n') //将一个单词放入数组word[]
{word[i++]=c;
c=fgetc(fp1);
}
并没有判断文件结束的情况,这样的话,文件结束的时候依然在进行循环……
[/Quote]
恩,果然,谢谢!
yin138 2010-07-03
  • 打赏
  • 举报
回复
很好,学习一下
  • 打赏
  • 举报
回复
你的程序还有隐含的大错误,那就是如果前一次存储的单词长度如果是20个,这次存储的单词长度是15个,那么按照你的程序,输出到fp2文件中的单词则会是本次15个字符加上上次的后5个字符,如此程序中会有很多重复字符。
问题还是处在我前面给你指出的循环处,即:
while(c!=' ' && c!='\n') //将一个单词放入数组word[]
{word[i++]=c;
c=fgetc(fp1);
}
最后修改成如下:
while(c!=EOF&&c!=' ' && c!='\n') //将一个单词放入数组word[]
{word[i++]=c;
c=fgetc(fp1);
}
word[i]='\0';
ocean_whut 2010-07-01
  • 打赏
  • 举报
回复
为了防止i不断加死循环,我加了句 if(i>20) break;让它跳出去。这样大体能实现要求了(末尾出现了乱码,再解决吧)
while(c==' ' || c=='\n')
c=fgetc(fp1);
while(c!=' ' && c!='\n') //将一个单词放入数组word[]
{printf("i = %d\n",i);
word[i++]=c;
c=fgetc(fp1);
if(i>20) break;
}
但还是想不明白,为什么 word[i++]=c;会陷入死循环呢?
yanran_hill 2010-07-01
  • 打赏
  • 举报
回复
[Quote=引用楼主 ocean_whut 的回复:]
while(c!=EOF)
{
i=0;
word=(char *)malloc(WORD_MAX*sizeof(char));
while(c==' ' || c=='\n')
c=fgetc(fp1);
while(c!=' ' && c!='\n') //将一个单词放入数组word[]
{
[/Quote]

这个逻辑比较奇怪,循环结束条件比较乱,而且多重循环做的工作内容都差不多,建议好好检查一下设计思路
jackyloncoln 2010-07-01
  • 打赏
  • 举报
回复
前两天我在linux下调程序的时候也碰到过这种访问错误

一般都是非法访问内存造成的。

http://www.gter.net/?action-viewthread-tid-1070619

http://wenku.baidu.com/view/8ea6f500bed5b9f3f90f1cb9.html

这两个链接你看下。。。

  • 打赏
  • 举报
回复
我已经帮你找出了错误所在,但是你的程序目前并不能实现要求中的分页功能。
错误之处:
while(c!=' ' && c!='\n') //将一个单词放入数组word[]
{word[i++]=c;
c=fgetc(fp1);
}
并没有判断文件结束的情况,这样的话,文件结束的时候依然在进行循环,这样就导致了word空间溢出,无论你设置成100还是1000。
修改成:while(c!=EOF&&c!=' ' && c!='\n')
icydrop 2010-07-01
  • 打赏
  • 举报
回复
既然你用gdb debug,你可以在seg fault的地方打印变量i看一下i的值是多少:
(gdb)p i //这样就可以打印出i变量的值

你编译你的程序的时候用 gcc -g .c 就行了

我运行你的程序没有出现seg fault, 我的是
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-56)
ocean_whut 2010-06-30
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 cattycat 的回复:]

文本的换行是\n,空格是' '.
可能是你的循环中逻辑处理的有问题吧
[/Quote]
代码检查了很多遍,感觉逻辑上没问题啊~
加载更多回复(7)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧