Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何交换命令行中指定的文件中的字符(文件名和字符)?_C_File_Command Line_Io - Fatal编程技术网

C 如何交换命令行中指定的文件中的字符(文件名和字符)?

C 如何交换命令行中指定的文件中的字符(文件名和字符)?,c,file,command-line,io,C,File,Command Line,Io,我正在学习文件命令并尝试编写一些程序。我想在命令行中指定两个字符,每次找到第一个字符时,第二个字符将替换第一个字符。命令行输入将是[program\u name].exe[file].txt[old\u char][new\u char]。我遇到了同样的问题,我试图通过查看答案来修复我的代码,但它创建了一个无限循环 int main(int argc, char *argv[]) { FILE *fp; char *string = {"Hellx"};

我正在学习文件命令并尝试编写一些程序。我想在命令行中指定两个字符,每次找到第一个字符时,第二个字符将替换第一个字符。命令行输入将是
[program\u name].exe[file].txt[old\u char][new\u char]
。我遇到了同样的问题,我试图通过查看答案来修复我的代码,但它创建了一个无限循环

int main(int argc, char *argv[])
{
    FILE *fp;
    char *string = {"Hellx"};
    char c;
    if ((fp = fopen(argv[1], "w")) != NULL)
    {
        fputs(string, fp);
        printf("Successfully written.\n");
        fclose(fp);

        if ((fp = fopen(argv[1], "r+")) != NULL)
        {
            while ((c = fgetc(fp)) != EOF)
            {
                if (c == *argv[2])
                {
                    fseek(fp, ftell(fp) - 1, SEEK_SET);
                    fprintf(fp, "%c", *argv[3]);
                    printf("Successfully changed.\n");
                }
            }
            fclose(fp);
        }
        else
            printf("Error on opening!");
    }
    else
        printf("Error on writing!");
    return 0;
}
因此,这个函数的输出是:
helloelloelloello…
,而它应该将
x
更改为
o
。这段代码有什么问题?

在讨论文件打开模式的部分中,for
fopen()
,说

当指定了“r+”、“w+”或“a+”访问类型时,将同时启用读取和写入(文件被称为打开以进行“更新”)。但是,当您从读取切换到写入时,输入操作必须遇到EOF标记。如果没有EOF,则必须使用对文件定位函数的中间调用。文件定位功能包括fsetpos、fseek和rewind从写入切换到读取时,必须使用对fflush或文件定位函数的中间调用。

(我的大胆)

所以我建议加上

fflush(fp);
fprintf()
语句之后,因为不需要重新定位


如前所述,还应将类型更改为

int c;

因此,可以将EOF
-1
与数据
0xFF

区分开来。您的程序失败的原因已经在其他答案和评论中进行了广泛的讨论和解决

没有“r+”和fflush,有没有一种简单的方法可以做到这一点

这里有一个以上的示例,其中打开文件进行读写操作,这样就不需要总是打开和关闭文件,使用
w+
标志,如果文件不存在,它也会创建文件:

#include <stdio.h>

int main(int argc, char *argv[])
{
    FILE *fp;
    int c;
    char *string = {"Hellx"};
    if (argc > 3)
    {
        if ((fp = fopen(argv[1], "w+")) != NULL) // open to write and read
        {

            fputs(string, fp);
            printf("Successfully written.\n");           
            rewind(fp); // back to the beginning of the file
            while ((c = fgetc(fp)) != EOF)
            {
                if(c == argv[2][0]) // if the character exists...
                { 
                    fseek(fp, -1, SEEK_CUR);
                    fprintf(fp, "%c", argv[3][0]); // replace
                    printf("Successfully changed.\n");
                    fseek(fp, 0, SEEK_CUR);
                }
            }
            fclose(fp);
        }
        else
            fprintf(stderr, "Error on writing!");
    }
    else
        fprintf(stderr, "Too few arguments!");
}
#包括
int main(int argc,char*argv[])
{
文件*fp;
INTC;
char*string={“Hellx”};
如果(argc>3)
{
if((fp=fopen(argv[1],“w+”)!=NULL)//打开以进行写入和读取
{
fputs(字符串,fp);
printf(“已成功写入。\n”);
倒带(fp);//返回到文件的开头
而((c=fgetc(fp))!=EOF)
{
if(c==argv[2][0])//如果字符存在。。。
{ 
fseek(fp,-1,SEEK_CUR);
fprintf(fp,“%c”,argv[3][0]);//替换
printf(“已成功更改。\n”);
fseek(fp,0,SEEK_CUR);
}
}
fclose(fp);
}
其他的
fprintf(stderr,“写入错误!”);
}
其他的
fprintf(stderr,“参数太少!”);
}
脚注:
我同意,一种更可靠的方法是使用两个不同的文件。

您的代码不工作,因为在从写回读切换到读时,您没有调用
fseek()
revend()
。还请注意,您不需要调用
ftell()
来后退:您可以使用
-1L
SEEK\u CUR
。对于这种文件修补,以二进制形式打开文件更安全

此外,
fgetc()
返回一个不适合
char
int
值。使用
int
type for
c
可靠地检测
EOF
。还请注意,成功时,
fgetc()
返回的字节值是
无符号字符的值,因此,对于非ASCII字节,将其与
字符进行比较可能会失败

以下是修改后的版本:

#include <stdio.h>

int main(int argc, char *argv[]) {
    FILE *fp;
    const char *string = { "Hellx" };

    if (argc < 4) {
        fprintf("missing command line arguments\n");
        return 1;
    }

    char *filename = argv[1];
    unsigned char c1 = argv[2][0];
    unsigned char c2 = argv[3][0];

    if ((fp = fopen(filename, "w")) == NULL) {
        fprintf(stderr, "cannot open %s for writing\n", filename);
        return 1;
    }
    fputs(string, fp);
    printf("Successfully written.\n");
    fclose(fp);
    
    if ((fp = fopen(filename, "rb+")) == NULL) {
        printf("Cannot reopen %s\n", filename);
        return 1;
    }
    while ((c = fgetc(fp)) != EOF) {
        if (c == c1) {
            fseek(fp, -1L, SEEK_CUR);
            fputc(c2, fp);
            fseek(fp, 0L, SEEK_CUR);
            printf("Successfully changed.\n");
        }
    }
    fclose(fp);
    return 0;
}
#包括
int main(int argc,char*argv[]){
文件*fp;
常量字符*字符串={“Hellx”};
如果(argc<4){
fprintf(“缺少命令行参数\n”);
返回1;
}
char*filename=argv[1];
无符号字符c1=argv[2][0];
无符号字符c2=argv[3][0];
if((fp=fopen(文件名,“w”))==NULL){
fprintf(stderr,“无法打开%s进行写入”,文件名);
返回1;
}
fputs(字符串,fp);
printf(“已成功写入。\n”);
fclose(fp);
如果((fp=fopen(文件名,“rb+”)==NULL){
printf(“无法重新打开%s\n”,文件名);
返回1;
}
而((c=fgetc(fp))!=EOF){
如果(c==c1){
fseek(fp,-1L,SEEK_CUR);
fputc(c2,fp);
fseek(fp、0L、SEEK\u CUR);
printf(“已成功更改。\n”);
}
}
fclose(fp);
返回0;
}

您需要声明
int c
,而不是
char c
您不需要使用
ftell()
。如果要返回1个字符,请使用
fseek(fp,-1,SEEK\u CUR)…但在从写切换回读之前,您需要另一个文件定位操作或
fflush
。@风向标似乎应该是答案。不要这样做。除非是交互式编辑器,否则进程不应打开文件进行读写。(有点自以为是的观点。)与其四处寻找和处理所有其他问题,只需写入另一个文件,然后在完成后重新链接该文件。这使得程序更加健壮(如果它在中间死亡,它不会破坏文件)。谢谢!没有
“r+”
fflush
,有没有一种简单的方法可以做到这一点?我自己对文本文件所做的就是永远不要篡改现有文件(除非在制作副本后作为最后手段)。我将读取旧文件并创建一个新文件,并进行必要的更改。我将使用
fgets()
读取一行,查找字符,覆盖任何字符,并将相同或更改的字符串写入新文件。或者你可以更容易地