Пример строк из входного файла:
abc@gmail.com Andee SMITH 1234
ADAM abc@gmail.com Andeee 21654
Anderea abc@gmail.com SAMMY 3524654
abc@gmail.com Andi BROWN 1245
Andie abc@gmail.com KNOWY 2485
Andra abc@gmail.com BRUCE 52445
Andrea abc@gmail.com 246574 DENNIS
2154 Andreana abc@gmail.com CHASE
Andree 21524 SIERRRA abc@gmail.com
Andrei 154 MONDY abc@gmail.com
4564765 Andria MALLE abc@gmail.com
78 Andriana abc@gmail.com WALLS
579874 abc@gmail.com Andriette MOUNT
52445 abc@gmail.com Andromache FRASSER
5478645 abc@gmail.com 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);
}
}
Ваша программа имеет много ошибок в ней, вот некоторые:
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
и Вы, вероятно, получите много этих предупреждений автоматически.
Если бы Ваш материал курса позволяет его, необходимо использовать C++ со Стандартной библиотекой шаблонов (STL), в этом случае, эта вся программа была бы несколькими строками кода, которые имеют сильные гарантии, что это не будет иметь многих ошибок памяти представленными здесь, так как это использовало бы std::string
и std::istream
сделать это меньшим количеством проблемы наряду с std::unordered_map
сделать поиски быстрее.