在c中从文件中阅读会在开头添加奇怪的字符

9njqaruj  于 2023-11-16  发布在  其他
关注(0)|答案(2)|浏览(78)

我必须从一个文件中读取两个字母,然后从同一文件的下一行读取一个文本(两个字母之间用空格隔开)。现在我需要在整个文本中用第二个字母替换第一个字母。
这是我的输入:

a x
abecedar avion nuca

字符串
所以字母a将被替换为x
这是我的代码:

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

int main()
{
    FILE *in;
    in = fopen("in.txt", "r+");
    char litera1 = 0, litera2 = 0, s[100], aux[100] = "";

    fscanf(in, " %c", &litera1);
    fgetc(in);
    fscanf(in, " %c", &litera2);
    strcpy(aux, "");
    printf("%c %c\n", litera1, litera2);

    while (fscanf(in, "%s", aux) != EOF)
    {
        strcat(s, aux);
        strcat(s, " ");
    }
    s[strlen(s) - 1] = NULL;
    printf("%s\n", s);
    for (int i = 0; i < 9; i++)
        printf("%c\n", s[i]);

    for (int i = 0; i < strlen(s); i++)
    {
        if (s[i] == litera1)
            s[i] = litera2;
    }

    /*
    rewind(in);
    fprintf(in,"%s", s);    i have to overwrite in the same file
    fflush(in);
    fclose(in); */
    return 0;
}


这是我的输出:

a x
@§@abecedar avion nuca
@
§
@
a
b
e
c
e
d


在另一个程序中,我需要将大写字母改为小写字母,反之亦然,交换工作正常,但我在文本前面得到了这个:
如何删除前三个字符?我一个字母一个字母地显示它来检查问题,但我无法解决。我怀疑这是因为移动到新行,但我不知道如何修复它。提前感谢。

e7arh2l6

e7arh2l61#

1.你需要初始化s,否则strcat(s, ...)将是未定义的行为。要么使用char s[LEN+1] = "",然后以不同的方式处理fscanf()的返回值,或者像下面这样需要输入。
1.如果while-循环不运行,s[strlen(s)-1] = ...将导致缓冲区下溢。
1.始终检查fopen()的返回值,否则对文件句柄的后续函数调用可能会失败。
1.始终检查scanf()的返回值,否则您可能正在对未初始化的数据进行操作。
1.使用scanf()阅读字符串时,始终使用最大字段宽度。
1.总是检查你在结果数组中有足够的空间。如果输入的第二行小于9个字节,你的print语句将打印未初始化的数据。
1.这是一个很好的做法,当完成fclose()
1.考虑使用fgets()getline()来获取一行而不是单词。如果连续或尾随空格是一个问题,您可以随后修补该行。

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

#define LEN 100
#define str(s) str2(s)
#define str2(s) #s

int main(void) {
    FILE *in = fopen("in.txt", "r+");
    if(!in) goto err;

    char litera1;
    char litera2;
    if(fscanf(in, " %c %c", &litera1, &litera2) != 2) goto err;
    printf("%c %c\n", litera1, litera2);

    char s[LEN+1];
    char aux[LEN+1];
    if(fscanf(in, "%" str(LEN) "s", s) != 1) goto err;
    while(fscanf(in, "%" str(LEN) "s", aux) == 1) {
        if(LEN - strlen(s) < strlen(aux) + 1) {
            fprintf(stderr, "full: s=\"%s\", aux=\"%s\"\n", s, aux);
            break;
        }
        strcat(s, " ");
        strcat(s, aux);
    }
    printf("%s\n", s);
    size_t n = 9 < LEN ? 9 : LEN;
    for(size_t i=0; i<n && s[i]; i++)
        printf("%c\n", s[i]);

    fclose(in);
    return 0;
err:
    perror("");
    fclose(in);
    return 1;
}

字符串
输出为:

a x
abecedar avion nuca
a
b
e
c
e
d
a
r

jogvjijk

jogvjijk2#

问题来自于s未初始化,因此在for循环的开始可能不包含空字符串,并且此随机内容出现在输出中。
您可以通过每次阅读一个字节并在需要时替换字母来大大简化代码。
您在注解中指定您 * 必须在同一个文件中覆盖 *:以这种方式更改文件内容似乎是您的任务,但通常更倾向于使用修改后的内容生成一个新文件,这也更简单,更不容易出错。
要修改文件的位置,您可以使用fseek()查找回写入修改内容的位置,也可以从写入切换回阅读。但是请注意,在旧平台上查找文本文件有限制:要移动当前位置,您只能查找到ftell()之前返回的位置。
以下是修改后的版本:

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

int main() {
    FILE *in = fopen("in.txt", "r+");
    if (in == NULL) {
        fprintf(stderr, "cannot open %s: %s\n", "in.txt", strerror(errno));
        return 1;
    }
    int literal1 = fgetc(in);
    int space = fgetc(in);
    int literal2 = fgetc(in);
    int newline = fgetc(in);
    if (literal1 == EOF || space != ' ' || literal2 == EOF || newline != '\n') {
        fprintf(stderr, "invalid format: need 2 characters separated by a space\n");
        fclose(in);
        return 1;
    }
    for (;;) {
        long pos = ftell(in);   
        int c = fgetc(in);
        if (c == EOF)
            break;
        if (c == literal1) {
            // need to replace the letter:
            // seek back to the previous position
            fseek(in, pos, SEEK_SET);
            // overwrite the character with the replacement
            fputc(literal2, in);
            // seek to the current position to allow switching back
            //   to reading from `in`
            fseek(in, 0L, SEEK_CUR);
        }
    }
    fclose(in);
    return 0;
}

字符串

相关问题