Мой код C отлично работает в Windows, но не работает точно в Ubuntu [закрыто]

Пример строк из входного файла:

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);
         }
}
0
задан 28 December 2018 в 03:07

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 и Вы, вероятно, получите много этих предупреждений автоматически.

Если бы Ваш материал курса позволяет его, необходимо использовать C++ со Стандартной библиотекой шаблонов (STL), в этом случае, эта вся программа была бы несколькими строками кода, которые имеют сильные гарантии, что это не будет иметь многих ошибок памяти представленными здесь, так как это использовало бы std::string и std::istream сделать это меньшим количеством проблемы наряду с std::unordered_map сделать поиски быстрее.

3
ответ дан 26 October 2019 в 17:53

Другие вопросы по тегам:

Похожие вопросы: