【问题标题】:Why my string getting some extra value? (C program)为什么我的字符串得到一些额外的价值? (C程序)
【发布时间】:2019-01-18 23:40:27
【问题描述】:

我正在尝试解决一个 C 程序问题:

用 C 语言创建一个程序,从文本文件中读取字符串,然后以奇偶格式重新排序字符串(先取奇数字母,然后取偶数字母;例如:如果程序读取 elephant,则重新排序的字符串将是eehnlpat)。然后将字符串写入不同的文本文件。为读写提供错误检查机制。

我的代码是:

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

int main() {
    FILE *inputFile;

    inputFile = fopen("inpFile.txt", "r");

    if (inputFile != NULL) {
        FILE *outFile = fopen("outFile.txt", "w");

        if (outFile != NULL) {
            printf("file created successfully\n");

            int i, j = 0;
            char strf1[50];
            fscanf(inputFile, "%s", &strf1);
            char strf2[strlen(strf1)];
            for (i = 0; strf1[i] > 0; i++) {
                if (i % 2 == 0) {
                    strf2[j] = strf1[i];
                    j++;
                }
            }
            for (i = 1; strf1[i] > 0; i++) {
                if (i % 2 == 1) {
                    strf2[j] = strf1[i];
                    j++;
                }
            }
            fprintf(outFile, "%s\n", strf2);

            fclose(outFile);
        } else {
            printf("file could not be created\n");
        }
        fclose(inputFile);
    } else {
        printf("File does not exist.");
    }
    return 0;
}

我觉得一切正常,但问题是如果程序读取elephant,那么我的程序给出的重新排序的字符串是eehnlpatZ0@。额外的Z0@ 是我的问题。我不想要那个额外的东西。但我无法修复它。如果有人可以帮我解决它,那就太好了。

【问题讨论】:

  • char strf2[strlen(strf1)]; 更改为char strf2[strlen(strf1)+1];。在 C 中,字符串是以 null 结尾的,您需要为该字符留出空间。
  • char strf2[strlen(strf1)] - 不会为终止的空字符留出空间(反正你从来没有写过)。使用%s 向任何printf 系列提交未终止的字符串会调用未定义的行为。您不符合该格式说明符的要求。

标签: c algorithm


【解决方案1】:

您的目标字符串太短:char strf2[strlen(strf1)];。您至少应该允许一个空终止符并设置它,或者只是使输出数组与输入数组大小相同:

char strf2[50];

您的代码中还有其他问题:

  • 如果fopen 出错,建议向系统返回非零状态。

  • 您应该将数组传递给fscanf(),而不是指向具有不同类型的数组的指针。

  • 你应该用%49s告诉fscanf()读入数组的最大字符数

  • 您应该测试fscanf() 的返回值,并为空输入文件生成一个空输出文件。在这种情况下,当前代码具有未定义的行为。

  • 测试strf1[i] &gt; 0 不正确:输入文件中的字符可能为负数。您应该计算字符串长度或使用strf1[i] != '\0'

  • 进行测试
  • i = 1 开始第二个循环似乎是个好主意,但它依赖于strf1 不是空字符串的静默假设。在您的示例中,如果 fscanf() 成功,则 strf1 不为空,如果失败,则行为未定义,因为 strf1 未初始化。然而,如果您稍后将代码移至假设可能不成立的通用函数,避免此类优化会更安全。

  • 在将输出字符串传递给fprintf 之前,您必须空终止输出字符串,或者使用%.*s 格式指定长度。

这是一个更正的版本:

#include <stdio.h>

int main() {
    FILE *inputFile, *outFile;
    char strf1[50], strf2[50];
    int i, j;

    inputFile = fopen("inpFile.txt", "r");
    if (inputFile == NULL) {
        printf("Cannot open input file inpFile.txt\n");
        return 1;
    }
    outFile = fopen("outFile.txt", "w");
    if (outFile == NULL) {
        printf("Could not create output file outFile.txt\n");
        fclose(inputFile);
        return 1;
    }
    printf("file created successfully\n");

    if (fscanf(inputFile, "%49s", strf1) == 1) {
        j = 0;
        for (i = 0; strf1[i] != '\0'; i++) {
            if (i % 2 == 0)
                strf2[j++] = strf1[i];
        }
        for (i = 0; strf1[i] != '\0'; i++) {
            if (i % 2 == 1) 
                strf2[j++] = strf1[i];
        }
        strf2[j] = '\0';
        fprintf(outFile, "%s\n", strf2);
    }
    fclose(inputFile);
    fclose(outFile);
    return 0;
}

这里有一个更简单的复制循环的替代方案:

        int len = strlen(strf1);
        j = 0;
        for (i = 0; i < len; i += 2) {
            strf2[j++] = strf1[i];
        }
        for (i = 1; i < len; i += 2) {
            strf2[j++] = strf1[i];
        }
        strf2[j] = '\0';

【讨论】:

    【解决方案2】:

    您必须为空终止符提供一个空间,因为您没有为它提供一个空间,printf 无法知道您的字符串何时终止,因此它会继续从内存中打印出数据。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    
    int main()
    {
        FILE* inputFile;
    
        inputFile=fopen("inpFile.txt", "r");
    
        if (inputFile!=NULL) {
            FILE* outFile=fopen("outFile.txt", "w");
    
            if (outFile!=NULL) {
                printf("file created successfully\n");
    
                int i, j=0;
                char strf1[50];
                fscanf(inputFile, "%s",&strf1);
                int inputLength = strlen(strf1) + 1;
                char strf2[inputLength];
                char strf2[inputLength-1] = '\0';
    
                for(i=0; strf1[i]>0; i++) {
                    if(i%2==0) {
                        strf2[j]=strf1[i];
                        j++;
                    }
                }
                for(i=1; strf1[i]>0; i++) {
                    if(i%2==1) {
                        strf2[j]=strf1[i];
                        j++;
                    }
                }
                fprintf(outFile, "%s\n",strf2);
    
                fclose(outFile);
            }else{
                printf("file could not be created\n");
            }
    
            fclose(inputFile);
        }
        else {
            printf("File does not exist.");
        }
        return 0;
    }
    

    【讨论】:

    • char strf2[inputLength]; char strf2[inputLength-1] = '\0';甚至不编译
    【解决方案3】:

    在 C 中,字符串需要一个空字符“\0”作为最后一个字节才能终止。

    更改以下代码行

    char strf2[strlen(strf1)];
    

    char strf2[strlen(strf1) + 1];
    

    会解决这个问题。

    【讨论】:

      猜你喜欢
      • 2015-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-08
      • 1970-01-01
      相关资源
      最近更新 更多