0

我尝试编写一个词库程序来读取词库文件,例如:drink:beverage quiet:smart,witty 和一个 .txt 文档,更改从词库中找到的单词并使用修改后的文本创建一个新文档。但是似乎有一个错误,我通过检查前后的打印操作将其缩小到 getReplacement() 中的 while 循环。我真的很感谢有人发现它为什么不起作用。

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <iostream>


char* getReplacement(char* original, FILE* file);

int main(int argc, char* argv[])
{

    using namespace std;

    FILE* thes = fopen(argv[1], "r");
    FILE* text = fopen(argv[2], "r+");
    FILE* nText = fopen("temp.txt", "w");
    if(thes == NULL || text == NULL || nText == NULL)
        return 1;
    char word[20] = {};
    char c;
    int bytesW=0;
    while((c = fgetc(text)) != EOF)
    {
        fputc(c, nText);
        bytesW++;
        if(isalpha(c))
        {
            int len = strlen(word);
            word[len] = c;
            word[len + 1] = '\0';
        }

        else
        {
            if(word == "")
                continue;
            cout << 7<<endl;
            char* replacement = getReplacement(word, thes);
            if(replacement == NULL)
                continue;
            fseek(nText,bytesW-1-strlen(word),SEEK_SET);
            for(int i=0;i<strlen(replacement);i++)
                fputc(replacement[i],nText);
            int diff = strlen(word) - strlen(replacement);
            while(diff-- >0)
                fputc(' ', nText);
            bytesW = bytesW-1-strlen(word)+strlen(replacement);
            fseek(nText, bytesW, SEEK_SET);
        }

    }
    fclose(thes);
    fclose(text);
    fclose(nText);


    return 0;
}

char* getReplacement(char* const original, FILE* file)
{
    using namespace std;
    char* line="";
    const short len = strlen(original);
    int numOfOptions=1;
    int toSkip=0; // number of commas to skip over
    outer: while(fgets(line,1000,file) != NULL)
    {
        for(int i=0;i<len;i++)
            if(line[i] != original[i])
            {
                goto outer;
            }
        if(line[len] != ':') 
            goto outer;
        for(int i=0;i<len;i++)
            line++;
        for(int i=0;i<strlen(line);i++)
            if(line[i] == ',')
                numOfOptions++;
        toSkip = rand()%numOfOptions;
        while(toSkip >0)
        {
            if(line[0] == ',')
                toSkip--;
            line++;
        }
        return line;
    }
    return NULL;

}
4

1 回答 1

2
char* line="";
// ... snip ...
outer: while(fgets(line,1000,file) != NULL)

这是你的问题。您正在尝试读入文字字符串;相反,您需要分配一个数组,在堆栈上或通过malloc()读取。

在 C 中用引号括起来的字符串称为文字。这意味着这个字符串会嵌入到程序的代码中,然后在加载程序时加载到内存中。通常它会被加载到标记为只读的内存中,但这取决于平台。你写的那个字符串只有空终止符的空间。但是您正在尝试将最多 1000 个字符读入其中。这将导致分段错误,因为您正在写入只读内存,或者会导致您在其他内存中写入,产生谁知道什么行为。

你想要做的是分配一个你可以读入的缓冲区:

char line[1000];

或者,如果您的堆栈空间有限:

char *line = malloc(1000 * sizeof(char));

此外,在您的main()功能中,您可以:

char c;
while((c = fgetc(text)) != EOF)

fgetc()返回一个int,而不是一个char。这样,如果读取了一个值,它可以返回一个与有效字符相对应的值,或者如果您点击文件末尾,它可以返回一个超出该范围的值。

您不能使用==;比较 C 中的字符串。这样做是比较它们是否是相同的指针,而不是它们是否具有相同的内容。每次重新计算当前单词的长度并没有什么意义;为什么不只是跟踪len自己,每次添加字符时递增它,然后当你想检查单词是否为空时,检查 if len == 0?请记住在单词结束后重置len为 0,以便您从下一个单词重新开始。len如果超过,也记得重置sizeof(word);你不想写太多word,否则你会开始在你的堆栈上乱写乱七八糟的东西,很多东西都会坏掉。

于 2013-09-28T15:38:58.120 回答