繁体   English   中英

C ++中的结构–从文件中读取错误

[英]Struct in C++ – incorrect reading from file

我的任务是创建一个对结构进行一些处理的程序。 我的结构与学生的成绩(考试成绩)有关。

在我的开关的第一种情况下,该函数创建结构并将其写入文件。 第二个–从文件中读取。 这是我的代码:

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


struct session {
    char name[50];
    int group;
    int exam1;
    int exam2;
    int exam3;
    int exam4;
    char test1[50];
    char test2[50];

};

void create(int);
void show(int);



int main() {

    int i, n;

    int loop = 2, num;

    while(loop > 1) {

        printf("\nChoose menu item(1-4):");
        scanf("%d", &num);

        switch (num) {
            case 1:
                printf("The number of students:\n");
                scanf("%d", &n);

                create(n);
                break;
            case 2:

                show(n);
                break;
            case 3:
                break;
            case 4:
                break;
            default:
                loop = 0;
                break;
        }
    };

    return 0;
}

void create(int n) {

    FILE *fp;
    session *year2017 = new session[n];

    fp = fopen("lab8.txt", "w");

    if(fp == NULL) {
        printf("File can't be opened\n");exit(1);
    }
        for (int i = 0; i < n; i++) {

            printf("Student #%d\n", i + 1);
            printf("Student's family name: ");
            while (getchar() != '\n');

            fgets(year2017 -> name, 50, stdin);
            printf("Group number: ");
            scanf("%d", &year2017->group);
            printf("1st exam grade: ");
            scanf("%d", &year2017->exam1);
            printf("2d exam grade: ");
            scanf("%d", &year2017->exam2);
            printf("3d exam grade: ");
            scanf("%d", &year2017->exam3);
            printf("4th exam grade: ");
            scanf("%d", &year2017->exam4);
            printf("First test (passed or not): ");

            while (getchar() != '\n');

            fgets(year2017 -> test1, 50, stdin);
            printf("Second test (passed or not): ");
            fgets(year2017 -> test2, 50, stdin);
            fwrite(year2017, sizeof(session), 1, fp);


        }

     fclose(fp);

}

void show(int n){

    FILE *fp;
    session *year2017 = new session[n];

    fp = fopen("lab8.txt", "r");

    while(fread(year2017,sizeof(session), 1, fp) != NULL) {
        printf("%s %d %d %d %d %d %s %s", year2017->name, year2017 -> 
group, year2017 -> exam1, year2017 -> exam2, year2017 -> exam3, 
year2017 -> exam4, year2017 -> test1, year2017 -> test2);
    }

 fclose(fp);

 }

当我编译代码时,输​​入如下:

http://take.ms/yoo5U

因此它不会在第二个循环中吃掉学生的名字,而且还会将成绩和第二个测试移到新行。

我使用Clion和Mac OS。

在c ++中,另一种选择是向文件写入数据或从文件读取数据

示例(尝试这样):

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

void writeFile()
{
    ofstream myfile;
    myfile.open("example.txt");
    if (myfile.is_open())
    {
        myfile << "Writing this to a file.\n";
        myfile.close();
    }
    else
        std::cout << "fail" << std::endl;
}    
void readFromFile()
{
    std::ifstream file("example.txt");
    std::string str;
    while (std::getline(file, str))
    {
        std::cout << str << std::endl;
    }
}

int main()
{
    writeFile();
    readFromFile();
    return 0;
}

std::fgets在字符串输入之后保留换行符(假定缓冲区空间足以到达该行)。 结果,您的test成员和name成员包含各自的字符串尾部带有换行符。

准确地解释了您的输出。 最直接的解决方法是简单地删除这些字符串中的换行符(如果存在),并且最合适的时间是在读取它们之后。 语法与此类似:

char *p = strrchr(str, '\n');
if (p)
    *p = 0;

这将找到换行符(如果允许空格,它必须是最后读取的字符),并用终止的nulchar覆盖它。

第二个问题,失去name ,是因为您在循环顶部while (getchar() != '\\n'); )的修剪代码不应该在循环内部。 选择菜单后,可以在那里修剪换行符。 它属于那里 (在菜单选择被读取之后); 不在这个循环中。

综上所述,此代码中有很多事情值得做不同的事情,它们对IO操作的成功有很多假设,并且像筛漏雨一样泄漏内存。 拥抱标准C ++库并利用其许多功能将对大多数功能有所帮助,我鼓励您这样做。

无论如何,以上内容应解决有关奇数输出的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM