C初学者,我得到了一个家庭作业,我们将使用gedit设计一个程序,从命令行读取文件名,并设计一个getNextWord方法。我们只需在时间和时间打开每个文件并返回单词,忽略除字母数字字符之外的所有内容(并将大写字母转换为低位字母)。我挂断的是我的导师给了我们strdup()函数来帮助我们以及isspace,alnum等。无论如何,在查找本网站上的strdup()以及C基础知识和网站和其他人必须有一些我不理解的东西。我的程序编译(我使用gcc -Wall -pedantic -std = c99 words.c -o words)并且只编译一个警告,即隐式使用strdup()。在同一目录中运行带有一些文本文件的程序让它打印出来,就像它在堆的边界上运行一样,然后给出一个分段错误(核心转储)。我以为我也给它正确的检查,例如在返回指针的strdup之前将\ 0放在字符数组的末尾,等等。这是我的代码;我不希望任何人为我做我的hw,也许观察会有所帮助,因为我整天都在研究,无法找到问题所在。感谢您阅读此内容(它没有显示,但我包含了stdio,stdlib.h,string.h,ctype.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_WORD_SIZE 256
char* getNextWord(FILE* fd)
{
int index = 0;
int c;
char str[MAX_WORD_SIZE];
while((c = fgetc(fd)) != EOF){
c = fgetc(fd);
if (isspace(c)){
str[index] = '\0';
return (char*) strdup(str);
}
if (((index+1) != (MAX_WORD_SIZE-1)) && (isalnum(c))){
c = tolower(c);
str[index] = c;
index++;
}
else {
index++;
str[index] = '\0';
return (char*) strdup(str);
}
}
return NULL;
}
int main(int argc, char* argv[])
{
char** current = argv;
char* heapedString = NULL;
while (*current)
{
char* filename = *current;
FILE* fd = fopen(filename, "r");
if (fd == NULL)
{
fprintf(stderr,"can't read the file\n");
exit(-1);
}
while ((heapedString = getNextWord(fd)) != NULL)
{
heapedString = getNextWord(fd);
printf("%s\n", heapedString);
free(heapedString);
}
fclose(fd);
current++;
}
return 0;
}
答案 0 :(得分:4)
也许是因为你丢弃了所有其他角色和单词。两种情况都有同样的错误:
while((c = fgetc(fd)) != EOF){
c = fgetc(fd);
....
}
每次循环都应该调用fgetc(或getNextWord)。你应该这样做:
while((c = fgetc(fd)) != EOF){
....
}
或者这个:
while(1){
c = fgetc(fd);
if (c == EOF) break;
....
}
但不是两者的结合
答案 1 :(得分:3)
这只是一种预感,但我相信以下两行是造成错误的原因。
while((c = fgetc(fd)) != EOF){
c = fgetc(fd);
内部文件位置指示器在每次使用时前进到下一个字符。所以它是在调用while循环时进行的。这可能会弄乱你想要的结果。
查看此处找到的代码,并注意使用do while代替。祝你好运!
http://www.cplusplus.com/reference/cstdio/fgetc/
答案 2 :(得分:1)
你在每次迭代中调用fgetc两次 - 一次在while()条件下和之后。调用getNextWord时也会犯同样的错误。
答案 3 :(得分:1)
至于strdup
部分问题的隐式声明:strdup
与许多其他常用函数一样,不是C99标准库的一部分。如果您查看man strdup
并查看“glibc的功能测试宏要求”部分,您将在包含库之前看到#define
所需的内容。例如:
#define _POSIX_C_SOURCE 200809L
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char *foo = "foo";
char *bar = strdup(foo);
puts(bar);
free(bar);
}
如果您想使用POSIX功能并同时使用-std = c99选项以保持ISO C99标准,则会遇到此问题。
答案 4 :(得分:0)
小问题但你为什么要使用
if (((index+1) != (MAX_WORD_SIZE-1)) && (isalnum(c)))
作为您的支票?我认为,从索引中删除+1应该足够了。对于我的代码,我正在使用
if ( isalnum( c ) && ( j <= ( MAX_WORD_SIZE - 1 ) ) )
并且它完全按照AFAICT的任务要求工作(显然我将j作为我的'索引'并且顺序无关紧要)
你需要在main中添加一个check来查看heapedString [0] =='\ 0',或者你打算打印很多空行。虽然这可能仍然可以满足作业,但最好不要将它们打印出来。