C使用strdup()等从文件中读取/打印文字

时间:2013-01-20 03:16:31

标签: c segmentation-fault

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

5 个答案:

答案 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',或者你打算打印很多空行。虽然这可能仍然可以满足作业,但最好不要将它们打印出来。