1

在这里的 C 初学者,我得到了一个家庭作业,我们将使用 gedit 设计一个程序来从命令行读取文件名并设计一个 getNextWord 方法。我们将简单地每次打开每个文件并返回单词,忽略除字母数字字符之外的所有内容(并将大写字母转换为小写字母)。我挂断的事情是我的导师给了我们 strdup() 函数来帮助我们以及 isspace、alnum 等。无论如何,在这个网站上查找 strdup() 以及 C 基础知识和网站和其他人一定有一些我不理解的东西。我的程序编译(我使用 gcc -Wall -pedantic -std=c99 words.c -o words)并且它编译时只是警告 strdup() 被隐式使用。在同一目录中运行带有几个文本文件的程序,它会打印 gobbly gook,就好像它超出了堆的边界,然后给出了分段错误(核心转储)。我想我也给了它正确的检查,例如在返回指针的 strdup 之前将 \0 放在字符数组的末尾等。这是我的代码;我不指望任何人为我做我的硬件,也许观察会有所帮助,因为我已经研究了一整天并且找不到问题。感谢您阅读本文(它没有显示,但我包括了 stdio、stdlib.h、string.h、ctype.h 也许观察会有所帮助,因为我已经研究了一整天并且找不到问题。感谢您阅读本文(它没有显示,但我包括了 stdio、stdlib.h、string.h、ctype.h 也许观察会有所帮助,因为我已经研究了一整天并且找不到问题。感谢您阅读本文(它没有显示,但我包括了 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;
}
4

5 回答 5

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;
    ....
}

但不是两者的结合

于 2013-01-20T03:27:42.073 回答
3

这只是一种预感,但我相信以下两行是导致错误的原因。

while((c = fgetc(fd)) != EOF){
c = fgetc(fd);

每次使用时,内部文件位置指示器都会前进到下一个字符。所以它在调用while循环时被推进。这可能会弄乱您想要的结果。

查看此处找到的代码,并注意使用了 do while。祝你好运!
http://www.cplusplus.com/reference/cstdio/fgetc/

于 2013-01-20T03:27:51.997 回答
1

您在每次迭代中调用 fgetc 两次 - 偶尔 () 条件和之后。调用 getNextWord 时也会犯同样的错误。

于 2013-01-20T03:25:42.453 回答
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 兼容,您会遇到这种情况。

于 2013-01-20T09:16:44.703 回答
0

小问题,但你为什么要使用

if (((index+1) != (MAX_WORD_SIZE-1)) && (isalnum(c)))

作为你的支票?我认为从索引中删除 +1 就足够了。对于我正在使用的此作业的代码

if ( isalnum( c ) && ( j <= ( MAX_WORD_SIZE - 1 ) ) )

并且它完全按照作业 AFAICT 的要求工作(显然我有 j 作为我的“索引”并且顺序无关紧要)

您需要在 main 中添加一个检查以查看 heapedString[0] == '\0' 是否也是如此,否则您将打印出很多空行。虽然这可能仍然可以满足任务,但最好不要将它们打印出来。

于 2013-01-22T03:34:27.523 回答