我試圖用 C 語言編譯這段代碼,它的目的是從一個 .dat 檔案中積累資料,該檔案的結構包含有關標記、年齡、性別的資訊。當我編譯它時,一個錯誤顯示說“分段錯誤”,我寫了一個 printf 來顯示 i、j 和 k 的值;因為我認為它們是問題所在,這里是代碼和失敗的照片:`
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
struct persona {
int edad; //EDAD DE 12-65//
int notas; //NOTAS DE 0-10//
char sexo; //SEXO 1=MASCULINO Y 2=FEMENINO//
char exi; //EXI 1=SI 2=NO
};
struct reg {
int notas;
int contex;
int cont;
};
const int imax = 7;
const int jmax = 6;
const int kmax = 3;
struct reg A[imax][jmax][kmax];
void retardo() {
for(int i=0; i < 11000; i ) {
for(int j=0; j < 11000; j ) {
}
}
}
void processbar() {
system("pause");
system("cls");
int i, j;
for(i=0; i < 20 ; i ) {
printf("Cargando... \n");
printf("====================\n");
for(j=0; j < i ; j ) {
printf("X");
}
printf("\n====================\n");
retardo();
system("cls");
}
}
void etario(int j, char grupoed[10]) //ASIGNAMOS LOS RANGOS ETARIOS//
{
switch(j)
{
case(1):
grupoed ="12-15";
break;
case(2):
grupoed ="16-25";
break;
case(3):
grupoed ="26-35";
break;
case(4):
grupoed ="36-45";
break;
case(5):
grupoed ="46-55";
break;
case(6):
grupoed = "56-65";
default:
printf("\nHa ocurrido un error");
}
}
void grupoed(struct persona p, int j) {
if( p.edad < 12) {
printf("\nexiste un error en la edad");
}
if(p.edad < 16) {
j = 1;
}
if(p.edad < 26) {
j = 2;
}
if(p.edad < 36) {
j = 3;
}
if(p.edad < 46) {
j = 4;
}
if(p.edad < 56) {
j = 5;
}
if(p.edad < 66) {
j = 6;
}
else {
printf("\nexists un error en la edad");
}
}
void niveling(struct persona p, int i) {
if(p.notas < 2) {
i = 1;
}
if(p.notas < 4) {
i = 2;
}
if(p.notas < 6) {
i = 3;
}
if(p.notas < 8) {
i = 4;
}
if(p.notas < 10) {
i = 5;
}
}
void femasc(struct persona p, int k) {
if(p.sexo = 'M') {
k = 1;
}
else {
if(p.sexo = 'F') {
k = 2;
}
}
}
void matrizcero(struct reg A[imax][jmax][kmax], int i, int j, int k) {
for (i = 1; i < 7; i )
{
for (j = 1; i < 6; j )
{
for (k = 1; i < 3; k )
{
A[i][j][k] = {0,0,0};
}
}
}
}
int main() {
struct reg A[imax][jmax][kmax];
void processbar();
void matrizcero(struct reg A[imax][jmax][kmax], int i, int j, int k);
struct persona p;
struct reg;
int i, j, k,rangomay, rangomen, rangointmay, resmay, resmen, jex, jmay, jmen, NIV, GRUPOET, sexo, cantidadM, califM, cantidadF, califF, grupoetario;
char grupoed[10];
float prom_m, prom_f;
FILE *entrada; //ABRO ARCHIVO
entrada=fopen("datospersonas.dat","rb");
if (entrada == NULL){
exit(1);
printf("\nError al abrir el archivo");
}
else {
printf("\nArchivo abierto exitosamente!");
}
while(!(feof(entrada))){
void niveling(struct persona p, int i);
void grupoedad(struct persona p, int j);
void femasc(struct persona p, int k);
printf("\n%d",i);
printf("\n%d",j);
printf("\n%d",k);
A[i][j][k].notas = A[i][j][k].notas p.notas;
A[i][j][k].cont = A[i][j][k].cont;
if(p.exi = 'S') {
A[i][j][k].contex = A[i][j][k].contex 1;
}
fread(&p,sizeof(p),1,entrada); //LEO ARCHIVO
}
for(i = 1; i < 6; i ) { //TOTALIZO HOMBRES Y MUJERES
for(j = 1; i < 7; i ) {
A[i][j][3].notas = A[i][j][3].notas A[i][j][2].notas;
A[i][j][3].cont = A[i][j][3].cont A[i][j][2].cont;
A[i][j][3].contex = A[i][j][3].contex A[i][j][2].contex;
}
}
for(j = 1; j < 7; j ) {
for(i = 1; i < 6; i ) {
cantidadM = cantidadM A[i][j][1].cont;
califM = califM A[i][j][1].notas;
}
}
prom_m = califM / cantidadM; //PROMEDIO DE CALIFICACIONES DE LOS HOMBRES
for(j = 1; j < 7; j ) {
for(i = 1; i < 6; i ) {
cantidadF = cantidadF A[i][j][2].cont;
califF = califF A[i][j][2].notas;
}
}
prom_f = califF / cantidadM; //PROMEDIO DE CALIFICACIONES MUJERES
for(k = 1; k < 3; k ) {
for(i = 1; i < 6; i ) {
for(j = 1; j < 7; j ) {
A[6][j][k].cont = A[6][j][k].cont A[i][j][k].cont;
A[6][j][k].contex = A[6][j][k].contex A[i][j][k].cont;
A[6][j][k].notas = A[6][j][k].notas A[i][j][k].notas;
}
}
}
for(j = 1; j < 7; j ) {
A[6][j][3].cont = A[6][j][1].cont A[6][j][2].cont;
A[6][j][3].cont = A[6][j][1].contex A[6][j][2].contex;
A[6][j][3].notas = A[6][j][1].notas A[6][j][2].notas;
}
resmay = A[6][1][3].contex;
for(j = 1; j < 7; j ) {
if(A[6][j][3].contex > resmay) {
resmay = A[6][j][3].contex;
jex = j;
}
}
for(k = 1; k < 3; k ) {
for(j = 1; j < 7; j ) {
A[7][j][k].notas = A[6][j][k].notas / A[6][j][k].cont;
}
}
resmen = A[7][1][3].notas;
resmay = A[7][1][3].notas;
for(j = 1; j < 7; j ) {
if(A[7][j][3].notas > resmay) {
resmay = A[7][j][3].notas;
jmay = j;
}
else {
if(A[7][j][3].notas < resmen) {
resmen = A[7][j][3].notas;
jmen = j;
}
}
}
void etario(int jmay);
printf("\nEl rango etario con mayor calificacion en promedio fue el comprendido entre: %s", grupoed, " a?os");
void etario(int jmen);
printf("\nEl rango etario con menor calificacion en promedio fue el comprendido entre: %s", grupoed, " a?os");
printf("\nEl promedio de calificaciones en femeninos fue: %f", prom_f);
printf("\nEl promedio de calificaciones en masculinos fue: %f", prom_m);
void etario(int jex);
printf("\nEl rango etario con mayor interes en rendir examenes internacionales es el comprendido entre: %s", grupoed, "a?os");
fclose(entrada);
system("pause");
return 0;
}
` 在此處輸入影像描述
為了以防萬一,這是生成 .dat 檔案的檔案...
`
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
struct persona {
int edad; //EDAD DE 12-65//
int notas; //NOTAS DE 0-10//
char sexo; //SEXO 1=MASCULINO Y 2=FEMENINO//
char exi; //EXI 1=SI 2=NO
};
void generacion()
{
FILE *entrada;
entrada=fopen("datospersonas.dat","w ");
if (entrada == NULL){
exit(1);
}
fclose(entrada);
}
int main()
{
int s;
int exi;
generacion();
persona p;
FILE* entrada;
entrada=fopen("datospersonas.dat","w ");
for (size_t i=0;i<30; i )
{
p.edad =(rand() %53) 12;
p.notas =(rand() %9) 1;
s=(rand() %2) 1;
if(s == 1){
p.sexo='M';
}
else{
p.sexo='F';
}
exi=(rand() %2) 1;
if(exi == 1){
p.exi='S';
}
else{
p.exi='N';
}
fwrite(&p, sizeof(struct persona),1,entrada);
printf("edad: %d\n",p.edad);
printf("nota: %d\n",p.notas);
printf("sexo: %c\n",p.sexo);
printf("esta interesado en rendir examenes internacionales: %c\n",p.exi);
}
fclose(entrada);
return 0;
}
`
我已經嘗試用更少的結構撰寫列印和處理,我開始編譯 500 個結構,現在我試圖用少于 50 個來完成它......
uj5u.com熱心網友回復:
顯示的代碼有兩個主要問題:
- 函式是如何呼叫的?
函式是通過呼叫它們的名稱,然后是引數串列來呼叫的。
這個
fread(&p, sizeof(p), 1, entrada);
fread是被呼叫函式的一個例子。
這些
void processbar();
void matrizcero(struct reg A[imax][jmax][kmax], int i, int j, int k);
還有這些
void niveling(struct persona p, int i);
void grupoedad(struct persona p, int j);
void femasc(struct persona p, int k);
是函式宣告的例子。它們讓編譯器知道一個函式存在,它接受什么型別的引數,以及它回傳什么型別的值。通常,您會在檔案頂部(通常稱為前向宣告)或頭檔案(函式在單獨的源檔案中定義)中找到它們。這讓其他函式所依賴的函式在定義之前公開它們的存在。
例如:
/* function declaration */
int foo(int);
/* function definition, relies on `foo` */
int bar(void)
{
return 4 foo(1);
}
/* finally `foo` is defined */
int foo(int a)
{
return a a;
}
如果沒有 的初始宣告foo,bar將不知道foo接受什么型別的引數,以及它回傳什么型別的值。
- 如何從函式中檢索資料。
C 是一種完全按值傳遞的語言。這意味著函式接收作為引數給出的值的副本。有時函式接受指標作為引數,但這些指標值仍然是副本。正是使用帶有指標值的間接尋址,允許 C 模仿其他語言中的按參考傳遞行為。
函式引數在函式內被視為區域變數。更改函式引數的值不會更改呼叫者作用域中任何變數的值。具有相同名稱但在不同范圍內的變數不指代同一個物件。
例如,這個程式列印0然后1。
#include <stdio.h>
void foo(int a)
{
a = 0;
printf("%d\n", a);
}
int main(void)
{
int a = 1;
foo(a);
printf("%d\n", a);
}
如果在呼叫者的范圍內foo發生了變化a,它會列印0然后0,但我們看到情況并非如此。
從函式中檢索資料的主要方法是使用它的回傳值。一個函式可以使用return關鍵字來回傳一個值給它的呼叫者。
例如,niveling可以更改為回傳一個int:
int niveling(struct persona p)
{
if (p.notas < 2)
return 1;
if (p.notas < 4)
return 2;
if (p.notas < 6)
return 3;
if (p.notas < 8)
return 4;
if (p.notas < 10)
return 5;
return 0;
}
然后將此函式用作:
struct persona per = { .notas = 7 };
int i = niveling(per);
非void函式必須始終回傳適當型別的值。
在 的情況下etario,使用陣列引數呼叫它是正確的,但您必須使用strcpy將字串文字的內容復制到陣列中。
void etario(int j, char grupoed[10])
{
switch (j) {
case 1:
strcpy(grupoed, "12-15")
break;
/* ... */
}
}
使用上述資訊修復您的程式后,仍然存在一些關鍵問題。
您的主回圈格式不正確,因為fread它只在回圈結束時被呼叫,應該在回圈開始時呼叫它。在嘗試使用讀取的資料之前,您還需要檢查 的回傳值fread是否等于預期的位元組數 ( )。sizeof p如果這兩件事都失敗,p要么是未初始化的,要么是不確定的,使用它的值肯定會呼叫Undefined Behavior。
另請參閱:為什么“while( !feof(file) )”總是錯誤的?
越界訪問:如果jmax是,則陣列6第二維中的最后一個有效索引是。A5
有幾種情況下陣列A被越界訪問,例如,
/* `j` reaches `6`, an invalid index */
for(j = 1; j < 7; j ) {
for(i = 1; i < 6; i ) {
cantidadM = cantidadM A[i][j][1].cont;
以及您在哪里使用i而不是j, 或一些類似的印刷錯誤:
for (i = 1; i < 7; i ) {
/* `i` is used in the condition of the inner loop */
for (j = 1; i < 6; j )
如果您創建“常量”,如imax、jmax和kmax,那么您應該在整個代碼中使用它們,而不是在任何地方都使用幻數。常量通常也是大寫的。
例子:
const int IMAX = 7;
const int JMAX = 6;
/* ... */
for (int i = 0; i < IMAX; i )
for (int j = 0; j < JMAX; j )
/* ... */
您還有語法問題,例如:
if (p.sexo = 'M')
=是賦值運算子。==是相等運算子。
結論:具有有效警告級別的良好編譯器會對您有很大幫助,因此您應該提高編譯器警告級別。對于 MSVC,至少使用/W4或/Wall,并可能/Wx執行更好的編碼實踐。請參閱:警告級別。
您還需要更仔細地學習該語言。考慮挑選一本好的C 教科書。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/536330.html
下一篇:python中的檔案名鏈
