c - 使用命令行参数在 C 文件中查找和替换单词

标签 c string file file-io console

我有一个包含一些文本的 txt 文件。我所要做的就是在那个文件中找到一个给定的词,并用一个新的给定词来改变它。这些单词和文本文件名将在命令提示符下以 C> findword <old word> <new word> <filename> 格式提供。其中 findword是可执行文件。一个词将以 '.' 结尾, 一个 ' '或在 '\n' .如果我们有一些额外的空格或换行符,则在单词结束后,我们将忽略它。我为此编写了以下代码并在 r+ 中打开了文件模式。我不想在这里使用临时文件。所有更新都应该在同一个文件上完成。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main(int argc, char *argv[])
{
    if(argc != 4)
    {
        printf("Improper number of arguments\n");
        exit(1);
    }

    FILE *fp = fopen(argv[3], "r+");
    if(fp == NULL)
    {
        printf("Unable to open file\n");
        exit(2);
    }

    char word[25];
    int i, flag = 0, len, k;
    char ch;
    len = strlen(argv[1])+1;//assuming new and old words are of same length
    for(i=0;1;i++)
    {
        word[i] = fgetc(fp);
        if(word[i] == EOF)
        {
            break;
        }

        if((word[i] == ' ' || word[i] == '.' || word[i] == '\n') && (flag == 0))
        {
            word[i] = '\0';
            if(strcmp(argv[1], word) == 0)
            {
                fseek(fp, -(len), SEEK_CUR);//To seek back to the start of the old word
                k = fputs(argv[2], fp);//writing new word n place of old word
            }
            flag = 1;//whenever a word is formed, flag is set to 1

        }
        //Below code is used to check if next charcter is whitespace or alphabet, so that we can start forming a new word
        ch = fgetc(fp);
        if(ch == EOF)
        {
            break;
        }
        if((flag == 1) && (ch != ' ' && ch != '\n'))//if ch is whitespace or newline we have to simply ignore it.
        {
            i = -1;//i will get incremented to 0 in next iteration and we can start forming new word
            flag = 0;//signifies we will be forming a new word from next iteration.
        }
        fseek(fp, -1, SEEK_CUR);
    }
    fclose(fp);
    return 0;
}

现在假设文本文件中有一行写为 This is business. .当我在 cmd 上写命令时 C> findword is zz test.txt其中 is是必须替换的旧词,zz是新词,test.txt是文本文件。执行此命令后,我希望文本文件更新为 This zz business但令我惊讶的是,文本文件被重写为 This zzubusiness. .问题是在更新单词 is 之后, is 之后的空格也在更新。在这种情况下,它被替换为字符 u .我用不同的单词和文本文件尝试了这段代码,发现 is 之后的空格总是被紧接的下一个单词的第二个字符替换。例如:这里的空间被替换为 u这是单词的第二个字符 business .现在我已经花了很多时间调试这段代码,但没有成功。我知道这段代码效率不高,但我特意编写它只是为了用它做一些实验。这段代码有什么问题?与同时使用fgetc()有关吗?和 fputs()在同一个文件上?还是我缺少的其他东西?

最佳答案

来自 man fopen (强调我的)

Reads and writes may be intermixed on read/write streams in any order. Note that ANSI C requires that a file positioning function intervene between output and input, unless an input operation encounters end-of-file. (If this condition is not met, then a read is allowed to return the result of writes other than the most recent.) Therefore it is good practice (and indeed sometimes necessary under Linux) to put an fseek(3) or fgetpos(3) operation between write and read operations on such a stream. This operation may be an apparent no-op (as in fseek(..., 0L, SEEK_CUR) called for its synchronizing side effect).

“确实有时是必要的”是您所经历的,也是为什么 fseek(fp,0,SEEK_CUR);fflush(fp); 之后fputs() 解决问题。

关于c - 使用命令行参数在 C 文件中查找和替换单词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64155061/

相关文章:

C语言命令行参数+读入文件

java - 读取文本文件中的空行

python - 非阻塞文件结束

C - 在没有 strcmp 的情况下测试字符串等价性

c - 标准 C 中的秒表程序

java - 使用正则表达式用修改后的字符替换字符串中的序列

c++ - 在 C++ 中填充 STL 字符串

python - 使用 python 将文件复制到文件列表中指定的目录

c - 神奇的段错误?

c++ - 将 _TCHAR* 转换为 char*