[英]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);
}
當我編譯代碼時,輸入如下:
因此它不會在第二個循環中吃掉學生的名字,而且還會將成績和第二個測試移到新行。
我使用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.