【问题标题】:c program crashes when a function prints the contents of array of pointers当函数打印指针数组的内容时,c程序崩溃
【发布时间】:2016-04-28 19:27:50
【问题描述】:

我正在学习 C。我编写了程序来从文本文件中读取数据并将其打印出来。在构建过程中编译器没有给出错误。但是,当我尝试运行它时,程序崩溃了。我检查了当printTable 函数被删除时,程序运行并在main() 中打印循环中的内容。我还尝试删除变量“total”,但程序仍然崩溃。有什么问题?

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

typedef struct{
char *country;
int females;
int males;
}person_count;

void printTable(person_count *data[]){
    printf("Country  Females  Males  Total\n");
    int i;
    int total[158];
    for(i=0;i<158;i++){

        total[i]=data[i]->females+data[i]->males;

        printf("%15s  %7i  %7i  %8i\n",data[i]->country,data[i]->females,data[i]->males,total[i]);
    }
}


int main(){
    person_count *data[158];

    FILE *eduData=fopen("SecondaryEd2005.txt","r");
    if(eduData==NULL){
        printf("File not found.");
        exit(1);
    }
    printf("File opened successfully.\n");

    int k;
    for(k=0;k<158;k++){
        data[k]=malloc(sizeof(person_count));
        char place[20];
        fscanf(eduData,"%s %i %i\n",place,&data[k]->females,&data[k]->males);
        data[k]->country=place;
        printf("%s %i %i\n",data[k]->country,data[k]->females,data[k]->males);
    }

    printTable(data);

    fclose(eduData);

    return 0;
}

txt文件内容示例:

比利时 391138 423401 伯利兹 15591 15786 贝宁 154266 281183 百慕大 2494 2262 不丹 19870 22274

【问题讨论】:

  • data[k]-&gt;country=place - 该缓冲区再次用于下一个条目(以及下一个等),每次都悬空,因为一旦达到每个 for 循环范围,place[] 就会丢失迭代。
  • 您输入文件中的任何国家/地区是否超过 19 个字符?
  • 是的,确实有大小为25左右的国家。谢谢,我将 place[] 的大小更改为 30 并且程序运行。但是,printTable 只打印一个国家 - 文件中的最后一个国家。我认为 WhozCraig 对此进行了说明。我怎样才能改变它?

标签: c function crash


【解决方案1】:

我为你修好了你的程序。最重要的是使国家成为一个固定长度的字符数组,而不是指针。此外,请确保释放分配给程序的所有内存,否则会产生内存泄漏。

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

typedef struct{
  char country[20]; //fixed to reflect country field better
  int females;
  int males;
}person_count;

void printTable(person_count *data[],int items){
  items++;
  int i,total[items]; //replaced fixed value with variable to prevent excessive empty rows from printing
  printf("Country  Females  Males  Total\n");
  for(i=0;i<items;i++){
  total[i]=data[i]->females+data[i]->males;
  printf("%15s  %7i  %7i  %8i\n",data[i]->country,data[i]->females,data[i]->males,total[i]);
  }
}


int main(){

  FILE *eduData=fopen("SecondaryEd2005.txt","r");
  if(eduData==NULL){
  printf("File not found.");
  exit(1);
  }
  printf("File opened successfully.\n");

  int k,fscanret;
  person_count* data[159]; //added 1 to prevent out of bounds memory access

  for(k=0;k<158;k++){
data[k]=malloc(sizeof(person_count));
fscanret=fscanf(eduData,"%s %i %i\n",data[k]->country,&data[k]->females,&data[k]->males);
if (fscanret==EOF){ //check return value to avoid going past end of file
  free(data[k]); //discard empty record and free memory if EOF reached
  k--;
  break;
}
printf("%s %i %i\n",data[k]->country,data[k]->females,data[k]->males);
  }
  fclose(eduData);

  printTable(data,k); //print k number of entries.

  while (k>=0){
free(data[k]); //free memory for all entries. DONT FORGET THIS
k--;
  }

  return 0;
}

【讨论】:

  • 谢谢。但是是否可以使用 *country 指针,因为在任务中声明它应该是一个指针?
  • 如果您要将它用作指针,则需要将其设置为指向固定的全局字符数组或指向已分配内存的指针。无论哪种情况,我认为通过将国家声明为指针,它需要处理器做更多的工作才能完成工作。
  • 谢谢您,我尝试按照您和其他人的建议进行更改-释放内存,将“国家/地区”更改为数组类型等。现在该程序可以完全运行。但我想我会尝试国家指针来检查。
【解决方案2】:

你应该改变你的 person_count 结构:

typedef struct{
    char country[20];
    int females;
    int males;
}person_count;

data[k]-&gt;country=place; 行应替换为 memcpy(data[k]-&gt;country, place, 20*sizeof(char));

WhozCraig 在他的评论中给了你答案。您的代码复制了一个指针,该指针在下一次循环迭代中丢失。

请注意,仅当您的所有国家/地区都少于 19 个字符时,此代码才有效。您也可以坚持使用 char* 指针,但在这种情况下,您必须分配内存并在使用后释放它。

【讨论】:

  • 谢谢,尼古拉斯。我将“国家”更改为数组类型并应用了 Mike 建议的更改。现在程序运行良好。唯一的问题是为什么有些输出条目看起来像:“British_Virgin_Islanь 1020 862 1882”(国家条目包括一些奇怪的符号和方块)?
  • 由于您将字母存储在 char 中,因此只有 8 位可以产生 255 种可能性。如果您的文本文件包含特殊字符,它们可能使用 2 个字节,它们将显示为 2 个字符。如果你想处理特殊字符,你应该学习 ascii 和 utf-8。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-20
  • 1970-01-01
  • 2013-10-08
  • 1970-01-01
  • 2012-03-12
  • 1970-01-01
  • 2018-02-22
相关资源
最近更新 更多