输入文件的示例行:
[email protected] Andee SMITH 1234
ADAM [email protected] Andeee 21654
Anderea [email protected] SAMMY 3524654
[email protected] Andi BROWN 1245
Andie [email protected] KNOWY 2485
Andra [email protected] BRUCE 52445
Andrea [email protected] 246574 DENNIS
2154 Andreana [email protected] CHASE
Andree 21524 SIERRRA [email protected]
Andrei 154 MONDY [email protected]
4564765 Andria MALLE [email protected]
78 Andriana [email protected] WALLS
579874 [email protected] Andriette MOUNT
52445 [email protected] Andromache FRASSER
5478645 [email protected] Andy MCFLY
//This program about scanning names,surnames ext. from disordered txt file and creating new ordered txt file.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct{
char id[50];
char name[50];
char lname[50];
char mail[50];
}Person;
int main(){
char str[250];
int count=0;
char c;
char previous;
int index =0;
int i,m,l;
int j,k=0;
Person person[300];
char str1[250];
char in[1];
char p;
Person temp;
FILE *file= fopen("hw4_disordered_people.txt","r");
while(c!=EOF){ // how many of struct
c= fgetc(file);
if(c=='\n'){
++count;
}
}
fclose(file);
//person *person= (person*)malloc(count+1*sizeof(person));
file = fopen( "hw4_disordered_people.txt" , "r");
while(fgets(str1,sizeof(str1),file)){
++index;
for (j = 0; str1[j] != '\n'; ++j)
{
if (str1[j] != ' ' && str1[j+1] != '\n')
{
str[k] = str1[j];
k++;
}
else if (k > 0 )
{
if (str1[j+1] == '\n')
{
str[k] = str1[j];
k++;
}
str[k] = '\0';
k=0;
if(str[0] >= '0' && str[0] <='9')
{
strcpy(person[index].id,str);
//printf("%s ",person[index].id);
strcpy(str,"");
}
else if (str[1] >= 'A' && str[1] <='Z')
{
if(strlen(person[index].lname) > 0){
//printf(" %s ",str);
strcat(person[index].lname," ");
strcat(person[index].lname,str);
strcpy(str,"");
}
else{
strcpy(person[index].lname,str);
//printf("%s ",person[index].lname);
strcpy(str,"");
}
}
else if ((str[1] >= 'a' && str[1] <='z') && (str[0] >= 'A' && str[0] <='Z'))
{
if(strlen(person[index].name) > 0){
//printf(" %s ",str);
strcat(person[index].name," ");
strcat(person[index].name,str);
strcpy(str,"");
}
else{
strcpy(person[index].name,str);
//printf("%s ",person[index].name);
strcpy(str,"");
}
}
else
{
strcpy(person[index].mail,str);
//printf("%s ",person[index].mail);
strcpy(str,"");
}
}
}
}
FILE *fp;
fp=fopen("OrderedList.txt","w");
for(i=1;i<=count;++i){
fprintf(fp,"%s %s %s %s\n",person[i].name,person[i].lname,person[i].mail,person[i].id);
}
}
答案1
你的程序有很多错误,下面列举几个:
FILE *file= fopen("hw4_disordered_people.txt","r");
while(c!=EOF){ // how many of struct
在这里,您没有检查文件是否打开成功,而是开始使用未初始化的变量c
,从技术上讲,该变量可以分配内存中的任何值。即使使用假定的值,0
这也是错误的,因为这假设文件至少有 1 个字节大,这意味着该程序可能会在传递给它的空文件时做出奇怪的事情。
while(c!=EOF){ // how many of struct
c = fgetc(file);
if(c=='\n'){
++count;
}
}
正确的写法应该更接近于:
while ((c = fgetc(file)) != EOF) {
++count;
}
还值得注意的是,该程序的这一部分可以用命令来替换wc -l
,该命令计算文件中有多少行。
if (str1[j+1] == '\n')
无法保证这j+1
是该数组的有效索引。
char str[250];
无法保证文件中的一行不会超过 248 个字符(包括换行符和空终止符)
Person person[300];
无法保证输入文件不超过 300 行。
str[k] = '\0';
k
可能现在指向字符数组的边界之外,尽管执行此操作所需的输入是一个非常特殊的边缘情况。
strcpy(person[index].id,str);
index
如果超出范围则缓冲区溢出(300)
for(i=1;i<=count;++i){
这可能试图访问数组边界之外的数据。你在循环早期增加并丢弃数组的索引 0 这一事实很奇怪,但从技术上讲并不是错误,但你愿意将其count + 1
作为有效地址进行访问这一事实是一个错误,如果你使用malloc
没有固定数组大小或处理具有 300 个输入的文件,这将导致分段错误/程序崩溃。
您应该用它编译您的代码gcc -Wall
,您可能会自动收到很多这样的警告。
如果您的课程材料允许,您应该使用带有标准模板库(STL)的 C++,在这种情况下,整个程序将只有几行代码,这些代码具有强有力的保证,即它不会出现这里介绍的许多内存错误,因为它会使用std::string
并std::istream
减少这个问题,同时std::unordered_map
加快查找速度。