Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Центр помощи > Помогите исправить ошибки


Автор: KyKy 5.2.2006, 02:07
Написал прогу, но препод сказал что неверно помогите исправить?
Код

//PR_HIPER_ALL.CPP
/*Программа вычисляющая S=a1-a2+a3-a4+a5-a6+... одномерном массиве A из N элементов (N<=9).
  Файлы проекта - HIPER2 : PR_HIPER_ALL.CPP - main()
                           PR_HIPER_FUNC.CPP - var()
                           PR_HIPER_OPEN.CPP - close()
                           PR_HIPER_CLOSE.CPP - open()
                           INDATA.TXT
                           OUTDATA.TXT
                           
Включаемые файлы :         PR_HIPER_HEADER.H
*/

#include "pr_hiper_header.h"  //Подключение необходимых заголовочных 

//Точка входа в программу.
int main(void)
{
//Исходные данные.

    
    int a[9];             //Массив а из 9 элементов.
    int s = 0;            //Сумма элементов массива а.
    int i = 0;//Индекс элементов массива а.
    


//Указатели на файлы ввода/вывода.    
    FILE *indata,   
         *outdata;

//Открытие файла ввода для считывания данных.
    indata = fopen("indata.txt","rt");   
    
//Считывание массива данных.
    while(EOF != fscanf(indata,"%d", &a[i++]));
    i--;
    
//Проверка количества элементов в массиве.
    if(i > 10) 
    {
        printf("ERROR #3: Wrong input data.\n");
        return 2;
    }else if(i==0)
    {
        printf("ERROR #4: Array is empty.\n");
        return 6;
    }

//Закрытие файла ввода.
    close("indata.txt",indata);

//Подсчёт данных.
    var(i, a, s);

//Открытие файла вывода для записи данных.   
    outdata  = fopen("outdata.txt","wt");

//Запись данных в файл вывода и их вывод в случаи удачи.
    fprintf(outdata,"Specifications performance:\nIn univariate array A from N elements (N<=9) calculate: S=a1-a2+a3-a4+a5-a6+...\nQuantity elements in massive is %d.\nResult calculations is %d.\n", i, s);
    
//Закрытие файла вывода.
    close("outdata.txt",outdata);
    
    return 0;
}



Код

//PR_HIPER_CLOSE.CPP
//Файл из проекта HIPER2
//Главная функция проекта находиться в файле PR_HIPER_ALL.CPP


#include "pr_hiper_header.h"

//Функция закрытия файла.

void close(         
     char *name,  //Получает имя файла
     FILE *file)  //Получает указатель на файл
{ 
     int ret;       //Вспомогательная переменная
    
     //Закрытие файла 
       ret=fclose(file);

     if(ret==EOF)
    {
        printf("ERROR #2: Can't close file %s\n", name);
        exit(2);
    }
    return ;
}



Код

// PR_HIPER_OPEN.CPP
// Файл из проекта HIPER2
//Главная функция проекта находится в файле PR_HIPER_ALL.CPP


#include "pr_hiper_header.h"

//Функция открытия файла
 
FILE *open(             // Передает указатель на файл
     char *name,      // Получает имя файла
     char *method)    // Получает метод открытия
{
    
      FILE *file;
    
    // Открытие файла
      file=fopen(name,method);
    
    
      if(file==NULL)
    {
        printf("ERROR #1: Can not open file %s\n", name);
        
        exit(1);
      }
    
    return file;
}



Код

//PR_HIPER_FUNC.CPP
//Файл из проекта HIPER2
//Главная функция находить в файле PR_HIPER_FUNC.CPP
#include "pr_hiper_header.h"

//Функция вычисляющая знак перед каждым аn-ым элементом.
void var(int N, 
         int *a, 
         int &s)
{ 
    for (int i = 0; i < N; i++)
    s+= i%2 ? -a[i] : a[i];
    
}


Код

//PR_HIPER_HEADER.H
//Включаемый файл для всех файлов проекта HIPER2
//Главная функция проекта находится в файле PR_HIPER_FUNC.CPP

#ifndef PR_HIPER_HEADER_H
#define PR_HIPER_HEADER_H

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


//Прототип функции var.
void var(int N, int *a, int &s);

//Прототип функции открытия.
FILE *open( char *name, char *method);

//Прототип функции закрытия.
void close(char *name,FILE *file);

#endif

Добавлено @ 02:17
Ошибка в первом файле PR_HIPER_ALL.CPP сторока 35. Ошибка в том что я считываю по индексу и при вводе например 10 чисел ошибки не будет,а я должен считать количество элементов и проверить их, следствие логическая ошибка.Вторая ошибка в том,что если в файл outdata.txt забить например 100 чисел будет ошибка это естественно,но преподу не нравиться то что я занимаю у компа лишнюю память этими числами.
Пербив вот так получается вроде как нормально, но считает толька 9 чисел, а 3,4,5 и более не может.

Код

//PR_HIPER_ALL.CPP
/*Программа вычисляющая S=a1-a2+a3-a4+a5-a6+... одномерном массиве A из N элементов (N<=9).
  Файлы проекта - HIPER2 : PR_HIPER_ALL.CPP - main()
                           PR_HIPER_FUNC.CPP - var()
                           PR_HIPER_OPEN.CPP - close()
                           PR_HIPER_CLOSE.CPP - open()
                           INDATA.TXT
                           OUTDATA.TXT
                           
Включаемые файлы :         PR_HIPER_HEADER.H
*/

#include "pr_hiper_header.h"  //Подключение необходимых заголовочных 

//Точка входа в программу.
int main(void)
{
//Исходные данные.

    
    int a[9]={0,0,0,0,0,0,0,0,0};             //Массив а из 9 элементов.
    int s = 0;            //Сумма элементов массива а.
    int i = 0;//Индекс элементов массива а.
    


//Указатели на файлы ввода/вывода.    
    FILE *indata,   
         *outdata;

//Открытие файла ввода для считывания данных.
    indata = fopen("indata.txt","rt");   
    
//Считывание массива данных.
    while(EOF != fscanf(indata,"%d", &a[i++]));
    i--;
    
//Проверка количества элементов в массиве.
    if(i != 9) 
    {
        printf("ERROR #3: Wrong input data.\n");
        return 2;
    }

//Закрытие файла ввода.
    close("indata.txt",indata);

//Подсчёт данных.
    var(i, a, s);

//Открытие файла вывода для записи данных.   
    outdata  = fopen("outdata.txt","wt");

//Запись данных в файл вывода и их вывод в случаи удачи.
    fprintf(outdata,"Specifications performance:\nIn univariate array A from N elements (N<=9) calculate: S=a1-a2+a3-a4+a5-a6+...\nQuantity elements in massive is %d.\nResult calculations is %d.\n", i, s);
    
//Закрытие файла вывода.
    close("outdata.txt",outdata);
    
    return 0;
}


Как вы считаете ?

Автор: Dreamer_0x01 5.2.2006, 12:15
Так. Вижу, ошибку с индексами массива "a[9]" ты нашел. Надеюсь, исправил правильно.

Об остальном подумаю позже, а пока вот еще плохая вещь.

ты делаешь return, не закрывая открытый тобой файл.
Код

    if(i > 10)    
    {    
        printf("ERROR #3: Wrong input data.\n");    
        return 2;    
    }
//и так несколько раз далее по коду


Как говорится это как в ресторане, поел - заплати, а не вскакивай из-за стола и убегай.Поймают - накажут ;)




Кстати. Для наглядности советую привыкнуть избавляться от явных заданий всех числовых констант (как у тебя например "9"), а задавать их дефайнами, и работать только через их обозначения. Поверь, в дальнейшем предохранит от массы неприятностей.
То есть определить
#define N_ELEM 9

и далее вместо твоей девяти писать N_ELEM. Потому что вдруг тебя попросят переделать программу на 10 элементов? Ты ж с ума сойдешь.


Видишь, я прочитал только пловину твоего первого файла, а уже столько ошибок и недочетов накопал.

Чуть попозже гляну остальной код, как время будет,а пока исправляй это.

Автор: Dreamer_0x01 5.2.2006, 12:43
Цитата(KyKy @ 5.2.2006, 02:07 Найти цитируемый пост)

    for (int i = 0; i < N; i++)
    s+= i%2 ? -a[i] : a[i];


Вот здесь будет ошибка при повторнм использовании этой функции. Если ты действительно хочешь ее использовать для подсчета только этого выражения, то s=0 лучше сделть в самой функции. Потому что иначе тебе придется это делать каждый раз перед вызовом функции.

Вот. Еще я вижу ты сделал проверку открытия файла, определив функцию open().
Все хорошо, но в коде тем не менее ты вызываешь не ее, а fopen().


Цитата

но считает толька 9 чисел, а 3,4,5 и более не может.

А вот эту фразу не понял

Цитата(KyKy @ 5.2.2006, 02:07 Найти цитируемый пост)

если в файл outdata.txt забить например 100 чисел будет ошибка это естественно,но преподу не нравиться то что я занимаю у компа лишнюю память этими числами.


может быть, речь идет все-таки о входном файле, а не о выходном?
Правильно говорит препод. Правда, если забъешь 100 чисел, то ничего страшного. А вот если 100000, то тогда уже чуть похуже.
Видимо он хочет, чтобы ты считывал числа из файла либо поблочно, либо, что проще, но медленнее - поэлементно.
То есть не считывал их в массив, а вообще отказался от массива, а лишь при каждом считанном числе прибавлял сумму с нужным знаком.



Автор: KyKy 5.2.2006, 12:54
Цитата

может быть, речь идет все-таки о входном файле, а не о выходном?

Да с файлом я перепутал, а насчёт 3,4,5 чисел попробуй в мой самый нижний исправленный файл подставить 3 числа их сумму и разность он не подсчитает, потому как расчитан на подсчёт толька 9 чисел в массиве.
Меня больше интересует вопрос про индексы?

Автор: Dreamer_0x01 5.2.2006, 14:15
Цитата

Меня больше интересует вопрос про индексы?



[censored 2] ... думал, ты это исправил, не посмотрел. Ан нет.
Опять ты допусил ту же самую ошибку,очень грубую!

Код

    while(EOF != fscanf(indata,"%d", &a[i++]));    



знаешь, к чему приводят подобные конструкции?

У тебя а - это
Код

int a[9].

Что будет, если в файле больше девяти элементов?

Ты будешь уже читать не в ячейки памяти, отведенные под массив а[],а бог знает куда, в "чужую" память. В лучшем случае ты получишь рано или поздно вопрос об отсылании отчета дядюшке Билли, в худшем - глюк в совершенно непредсказуемом и неожиданном месте.

Читать нужно с проверкой, допустимо ли такое чтение.
То есть хотя бы так

Код

//ранее объяви    
 #define N_ELEM 9    
//а массив а переопредели как    
int a[N_ELEM];    
//достали уже твои девятки =)    
    while( (EOF != fscanf(indata,"%d", &a[i++]) ) && (i<N_ELEM) );    



В этом случае ты не будешь портить память за границами массива.

Цитата(KyKy @ 5.2.2006, 12:54 Найти цитируемый пост)

попробуй в мой самый нижний исправленный файл подставить 3 числа их сумму и разность он не подсчитает, потому как расчитан на подсчёт толька 9 чисел в массиве.


А в чем проблема-то?
Кто тебе мешает перед открытием файла попросить пользователя ввести количество элементов?

Кстати, раз уж так хочется читать в массив, а не поэлементно (несморя на уговоры препода), то объявить тебе его уже придется не как

int a[9], а пожалуй лучше как int *a.

Потом, когда пользователь ввел нужное количество элементов, анализируешь его на допустимость (чтоб не отрицательное, не слишком большое, не ноль и т.д.), если устраивает - выделяешь под массив память. Допустим, пользоватль вводит количество элементов, которое момещается в переменную N.

Код

//ранее объеялвно
unsigned int N;
//просишь пользователя ввести N 
//....
//проверяешь.
a = new int[N];

//далее пользуешься а как обычным массивом, не забывая о допустимых значениях индексов

//а когда попользовался - освобождаешь память
delete a;

Автор: KyKy 5.2.2006, 15:38
Вот глянь что получилось толька без new
Код

//PR_HIPER_ALL.CPP
/*Программа вычисляющая S=a1-a2+a3-a4+a5-a6+... одномерном массиве A из N элементов (N<=9).
  Файлы проекта - HIPER2 : PR_HIPER_ALL.CPP - main()
                           PR_HIPER_FUNC.CPP - var()
                           PR_HIPER_OPEN.CPP - close()
                           PR_HIPER_CLOSE.CPP - open()
                           INDATA.TXT
                           OUTDATA.TXT
                           
Включаемые файлы :         PR_HIPER_HEADER.H
*/

#include "pr_hiper_header.h"  //Подключение необходимых заголовочных 
#define N_ELEM 9
//Точка входа в программу.

int main(void)
{
//Исходные данные.

    
    int a[N_ELEM];             //Массив а из 9 элементов.
    int i = 0;                 //Индекс элементов массива а.
    int s;


//Указатели на файлы ввода/вывода.    
    FILE *indata,   
         *outdata;

//Открытие файла ввода для считывания данных.
    indata = open("indata.txt","rt");   
    
//Считывание массива данных.
    while ( (EOF != fscanf(indata,"%d", &a[i++]) ) && (i < N_ELEM) );
    i--;

    
//Проверка количества элементов в массиве.
 
    if(i != 9) 
    {
        printf("ERROR #3: Дурик!.\n");
        exit(3);
    }

    close("indata.txt",indata);    //Закрытие файла ввода.

//Подсчёт данных.
    var(i, a, s);

//Открытие файла вывода для записи данных.   
    outdata  = open("outdata.txt","wt");

//Запись данных в файл вывода и их вывод в случаи удачи.
    fprintf(outdata,"Specifications performance:\nIn univariate array A from N elements (N<=9) calculate: S=a1-a2+a3-a4+a5-a6+...\nQuantity elements in massive is %d.\nResult calculations is %d.\n", i, s);
    
//Закрытие файла вывода.
    close("outdata.txt",outdata);
    
    return 0;
}

Автор: Dreamer_0x01 5.2.2006, 16:13
Цитата(KyKy @ 5.2.2006, 15:38 Найти цитируемый пост)

    if(i != 9) 
    {
//......
  }


Убирай, убирай эти числа. Замучаешься потом по всей программе их искать.
раз определил N_ELEM - везде и используй его, где можно.
Добавлено @ 16:20
Цитата(KyKy @ 5.2.2006, 15:38 Найти цитируемый пост)

    if(i != 9) 
    {
        printf("ERROR #3: Дурик!.\n");
        exit(3);
    }


файл-то кто закрывать будет? smile
Вообще, на будущее - чтобы избегать подобных ошибок, полезно открытие/закрытие файлов, общение с объектами синхронизации (вход/выход из критических секций), выделение/освобождение памяти и другие вещи, требующие обязательного применения пары каких-либо действий, выносить за пределы функций вход из которых в случае ошибок определяется по return.
Но в данном случае это не обязательно, достаточно перед возвратом вписать закрытие файла, если такие вещи слишком часто у тебя не будут встречаться. Если же твой код сильно разрастется - полезно сделать вышеперечисленное.


Автор: Dreamer_0x01 5.2.2006, 16:38
Цитата(KyKy @ 5.2.2006, 15:38 Найти цитируемый пост)

while ( (EOF != fscanf(indata,"%d", &a[i++]) ) && (i < N_ELEM) );


Если честно, я забыл, есть ли определенный порядок выполнения действий вида
()&&()&&()&&(), и не помню также,будет ли выполняться каждое выражение в скобках, или условие не сработает на первом же неподходящем условии.
Подозреваю, что и эта запись тоже некорректна. Хотя, повторяю, не уверен. Причина в том, что я такие конструкции уже давно не использую.

Чтобы в этом не путаться, и лишний раз при чтении кода не напрягать мозг, я бы все-таки сделал нечто подобное, пусть более громоздкое по коду, но зато более явно читаемое:
Код

do{
int eof_flag=fscanf(indata,"%d", &a[i]);
i++;
}while ( (EOF != eof_flag ) && (i < N_ELEM) );



Автор: KyKy 5.2.2006, 16:53
Цитата


Если честно, я забыл, есть ли определенный порядок выполнения действий вида
()&&()&&()&&(), и не помню также,будет ли выполняться каждое выражение в скобках, или условие не сработает на первом же неподходящем условии.
Подозреваю, что и эта запись тоже некорректна. Хотя, повторяю, не уверен. Причина в том, что я такие конструкции уже давно не использую

Да какраз это и происходит.Щас проверю исправленное.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)