Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.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_String_File_Replace_Word - Fatal编程技术网

如何在C中以不同的行将字符串写入文件

如何在C中以不同的行将字符串写入文件,c,string,file,replace,word,C,String,File,Replace,Word,我有一个程序,可以用另一个字替换文件中的一个字,但在新文件中,所有的行都写为一行,而不是按要求写在不同的行和段落中 我尝试在从原始文件读取的每行末尾添加'\n',但它不起作用 这是我的代码: int main() { FILE *f1, *f2; char word[MAX], fname[MAX]; char s[MAX], replace[MAX]; char temp[] = "temp.txt", *p1, *p2; printf("Enter y

我有一个程序,可以用另一个字替换文件中的一个字,但在新文件中,所有的行都写为一行,而不是按要求写在不同的行和段落中

我尝试在从原始文件读取的每行末尾添加
'\n'
,但它不起作用

这是我的代码:

int main() {
    FILE *f1, *f2;
    char word[MAX], fname[MAX];
    char s[MAX], replace[MAX];
    char temp[] = "temp.txt", *p1, *p2;
    printf("Enter your input file name:");
    fgets(fname, MAX, stdin);
    fname[strlen(fname) - 1] = '\0';

    scanf("%s", word);

    scanf("%s", replace);

    f1 = fopen(fname, "r");
    if (!f1) {
        printf("Unable to open the input file!!\n");
        return 0;
    }
    f2 = fopen(temp, "w");
    if (!f2) {
        printf("Unable to open temporary file!!\n");
        return 0;
    }

    while (fscanf(f1,"%[^\n]%*c", &s) != EOF) {
        printf("%s",s); //I wanted to see what happens when I'm reading from the file. Previously I added at the end of string s the char '\n' but it didnt work

        if (strstr(s, word)) {
            p2 = s;
            while (p1 = strstr(p2, word)) {
                while (p2 != p1) {
                    fputc(*p2, f2);
                    p2++;
                }
                p1 = p1 + strlen(word);
                fprintf(f2, "%s", replace);
                p2 = p1;
            }
            while (*p2 != '\0') {
                fputc(*p2, f2);
                p2++;
            }
        } else {
            fputs(s, f2);
        }
    }

    fclose(f1);
    fclose(f2);

    remove(fname);

    rename(temp, fname);
    return 0;
}

第一个错误是将s的地址提供给fscanf,
fscanf(f1,“%[^\n]%*c”,&s)
必须是
fscanf(f1,“%[^\n]%*c”,s)

无论如何,只要用一个简单的FGET替换fscanf,一切都会好起来,不会松动\n


注意:如果你不能确定MAX不足以处理行,你必须处理一行在读取时被切割成几行的情况,并且可能是因为这个原因而在切割中被替换的单词。有几种方法可以做到这一点。

第一个错误是将s的地址提供给fscanf,
fscanf(f1,“%[^\n]%*c”和&s)
必须是
fscanf(f1,“%[^\n]%*c”,s)

无论如何,只要用一个简单的FGET替换fscanf,一切都会好起来,不会松动\n


注意:如果你不能确定MAX不足以处理行,你必须处理一行在读取时被切割成几行的情况,并且可能是因为这个原因而在切割中被替换的单词。有几种方法可以做到这一点。

简单的原因是您没有向文件输出换行符。
fscanf
不包括
s
中的换行符(因为您在
[^\n]
中特别省略了它,这意味着“换行符以外的字符”)

如果只添加
putc('\n',f2)
在外部
的最末端,当
循环时,它工作正常

或者,您可以只使用
fgets
进行读取,其中包含字符串中的换行符。另一个好处是,
fgets
强制您指定最大长度作为参数,而使用
fscanf
防止过长的行长度要求您将长度放入格式字符串本身


(请注意,
printf(“%s”,s);
对进入文件的内容没有影响,因为它输出到
stdout

原因很简单,因为您没有向文件输出换行符。
fscanf
不包括
s
中的换行符(因为您在
[^\n]
中特别省略了它,这意味着“换行符以外的字符”)

如果只添加
putc('\n',f2)
在外部
的最末端,当
循环时,它工作正常

或者,您可以只使用
fgets
进行读取,其中包含字符串中的换行符。另一个好处是,
fgets
强制您指定最大长度作为参数,而使用
fscanf
防止过长的行长度要求您将长度放入格式字符串本身

(请注意,
printf(“%s”,s);
对进入文件的内容没有影响,因为它输出到
stdout

出于多种原因,您应该使用
fgets()
从输入文件中读取,而不是
fscanf(f1,%[^\n]*c],&s)

  • 您没有给
    fscanf()
    指定存储到
    s
    中的最大字符数:输入文件中任何足够长的行都将导致未定义的行为
  • f1
    中读取换行符并显式跳过换行符,这解释了为什么换行符从未写入
    f2
  • fscanf()
    将在空行上失败,因为没有与
    \n
    不同的字符可读入
    s
    s
    未被修改,处理方式与前一行相同(或第一行上未定义的行为),循环在输入文件中的同一位置迭代,有效地永久性地停留在写入
    f2
    上,但毫无用处
以下是一个经过更正和简化的版本:

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

#define MAX  100

int main() {
    FILE *f1, *f2;
    char word[MAX], fname[MAX];
    char s[MAX], replace[MAX];
    char temp[] = "temp.txt";
    char *p1, *p2;

    printf("Enter your input file name: ");
    if (!fgets(fname, sizeof fname, stdin))
        return 1;
    fname[strcspn(fname, "\n")] = '\0';  /* strip the newline if present */

    printf("Enter the word to search: ");
    if (scanf("%99s", word) != 1)
        return 1;

    printf("Enter the replacement word: ");
    if (scanf("%99s", replace) != 1)
        return 1;

    f1 = fopen(fname, "r");
    if (!f1) {
        fprintf(stderr, "Unable to open the input file %s\n", fname);
        return 1;
    }
    f2 = fopen(temp, "w");
    if (!f2) {
        fprintf(stderr, "Unable to open temporary file %s\n", temp);
        return 1;
    }

    while (fgets(s, sizeof s, f1)) {
        p1 = s;
        while ((p2 = strstr(p1, word)) != NULL) {
            while (p1 < p2) {
                fputc(*p1++, f2);
            }
            fputs(replace, f2);
            p1 += strlen(word);
        }
        fputs(p1, f2);
    }

    fclose(f1);
    fclose(f2);

    remove(fname);
    rename(temp, fname);
    return 0;
}
您应该使用
fgets()
来读取输入文件,而不是
fscanf(f1,%[^\n]%*c,&s)
,原因有多种:

  • 您没有给
    fscanf()
    指定存储到
    s
    中的最大字符数:输入文件中任何足够长的行都将导致未定义的行为
  • f1
    中读取换行符并显式跳过换行符,这解释了为什么换行符从未写入
    f2
  • fscanf()
    将在空行上失败,因为没有与
    \n
    不同的字符可读入
    s
    s
    未被修改,处理方式与前一行相同(或第一行上未定义的行为),循环在输入文件中的同一位置迭代,有效地永久性地停留在写入
    f2
    上,但毫无用处
以下是一个经过更正和简化的版本:

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

#define MAX  100

int main() {
    FILE *f1, *f2;
    char word[MAX], fname[MAX];
    char s[MAX], replace[MAX];
    char temp[] = "temp.txt";
    char *p1, *p2;

    printf("Enter your input file name: ");
    if (!fgets(fname, sizeof fname, stdin))
        return 1;
    fname[strcspn(fname, "\n")] = '\0';  /* strip the newline if present */

    printf("Enter the word to search: ");
    if (scanf("%99s", word) != 1)
        return 1;

    printf("Enter the replacement word: ");
    if (scanf("%99s", replace) != 1)
        return 1;

    f1 = fopen(fname, "r");
    if (!f1) {
        fprintf(stderr, "Unable to open the input file %s\n", fname);
        return 1;
    }
    f2 = fopen(temp, "w");
    if (!f2) {
        fprintf(stderr, "Unable to open temporary file %s\n", temp);
        return 1;
    }

    while (fgets(s, sizeof s, f1)) {
        p1 = s;
        while ((p2 = strstr(p1, word)) != NULL) {
            while (p1 < p2) {
                fputc(*p1++, f2);
            }
            fputs(replace, f2);
            p1 += strlen(word);
        }
        fputs(p1, f2);
    }

    fclose(f1);
    fclose(f2);

    remove(fname);
    rename(temp, fname);
    return 0;
}

所以您想修改文件中的单词,但保留所有空白?然后,读写空格是很重要的。使用跳过空白的读取函数不会有多大帮助

下面是读修改循环的通用版本。修复bug并将其扩展到一个程序,包括错误处理,留给读者作为练习

while (1)
  {
    // Read the next character
    int ch = fgetc(infile);
    if (ch == EOF)
       break;  // read error or eof

    if (isspace(ch))
       {
          // The character was a whitespace, so we copy it to the outputstream
          int err = fputc(ch, outfile);
          if (err == EOF)
            break; // error
       }
    else
      {
        // The next character was not a whitespace, so we put it back in the
        //  inputstream for scanf to find it
        ungetc(ch, instream);

        char word[64]; // Just assume for simplicity that no words are longer 
                       // than 63 character.

        // Read the next string, making sure we don't read more than the buffer
        // can handle. A robust program should do something useful if words are
        // actually longer than 63 characters
        int len = fscanf(infile, "%63s", word);

        if (len == EOF)
           break;  // error (should not happen since there is guarantied to be
                     // one non-whitespace character in the stream)

        char mod_word[64];
        modify_word(mod_word, word);

        int err = fputs(mod_word, outfile);
        if (err == EOF)
           break; // error
     }
}

// Check for read-write errors
if (ferror(infile))
  perror("Failure reading from input file");
if (ferror(outfile))
  perror("Failure writing to output file"); 

所以您想修改文件中的单词,但保留所有空白?然后,读写空格是很重要的。使用跳过空白的读取函数不会有多大帮助

下面是读修改循环的通用版本。修复bug并将其扩展到一个程序,包括错误处理,留给读者作为练习

while (1)
  {
    // Read the next character
    int ch = fgetc(infile);
    if (ch == EOF)
       break;  // read error or eof

    if (isspace(ch))
       {
          // The character was a whitespace, so we copy it to the outputstream
          int err = fputc(ch, outfile);
          if (err == EOF)
            break; // error
       }
    else
      {
        // The next character was not a whitespace, so we put it back in the
        //  inputstream for scanf to find it
        ungetc(ch, instream);

        char word[64]; // Just assume for simplicity that no words are longer 
                       // than 63 character.

        // Read the next string, making sure we don't read more than the buffer
        // can handle. A robust program should do something useful if words are
        // actually longer than 63 characters
        int len = fscanf(infile, "%63s", word);

        if (len == EOF)
           break;  // error (should not happen since there is guarantied to be
                     // one non-whitespace character in the stream)

        char mod_word[64];
        modify_word(mod_word, word);

        int err = fputs(mod_word, outfile);
        if (err == EOF)
           break; // error
     }
}

// Check for read-write errors
if (ferror(infile))
  perror("Failure reading from input file");
if (ferror(outfile))
  perror("Failure writing to output file"); 

我试着用没有地址的fscanf替换它,虽然我不明白为什么,但它仍然不起作用。我也尝试过fgets版本,但更糟糕的是,现在,用fgets在一个字符串中读取所有文件并替换单词,最终的文件不完整。要删除&只允许给fscanf一个
char*
而不是
char**
,因为这是