Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Помогите найти ошибку / 11 сообщений из 11, страница 1 из 1
11.01.2006, 10:32
    #33475739
BBrAT
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите найти ошибку
Задача - чтение квадратной матрицы из файла. Условие - все используемые массивы и переменные должны быль реализованы как динамические структуры (реализовано частично). Ошибка - в результате матрица отличается от исходной.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
#include <iostream.h>
#include <fstream.h> // ifstream input_file
#include <ctype.h>   // isdigit
#include <math.h>    //sqrt


int main(void) 
{
cout << "Enter name of file\n";
char filename[ 10 ];
cin >> filename;
ifstream input_file(filename, ios::nocreate);

if (input_file.fail())
{   
   cout << "\n!Error: cannot find " << filename ;
   cin >> filename;
   return  0 ;
}


int size= 0 ;
char element[ 64 ];        // для проверки size + digit
int i =  0 ;
  while (! input_file.eof())
   {
	  input_file >> element[i];
          size++;
	  i++;
   }
size--;                                                  // (1)
cout << size << endl;
               //если элемент не цифра
for (i= 0 ; i<size;i++){                                                        
	if (! isdigit(element[i])){                                                
       cout << "\n!Error: " << i+ 1  << "  " << element[i] << " is not digit!"; 
       cin >> i; return  0 ;                                                    
	}
}
             // если матрица не квадратная
if ((size/sqrt(size)) != sqrt(size)){                    // ( 2 )
  cout << "\n!Error: matrix is not quadro!";               
  cin >> i;                                                
  return  0 ;                                                
}


size = sqrt(size);                                       // ( 3 )

int **matrix = new int*[size];
for(i =  0 ; i < size; i++){matrix[i] = new int[size];}

cout << size << endl;
                 //вывод списка элементов
for (i= 0 ;i < (size*size);i++){           
cout << element[i] << " ";               
}

cout << endl;

      // присвоение

for (i= 0 ; i<size;i++){
	for (int j= 0 ;j<size;j++){
matrix[i][j] = element[(j+(size*i))];
	}
}


      // вывод  на экран

for (i= 0 ; i<size;i++){
	for (int j= 0 ;j<size;j++){
cout << matrix[i][j] << "\t";
	}
  cout << endl;
}

cin >> i;   
return  0 ;
}
Сноски:
1) почему-то показывает на 1 элемент больше. Ноль-символ вроде бы считать не должен...
2) Знаю, что неправильно, но работает!
3) переход от кол-ва элементов к кол-ву строк/столбцов
cin >> i в нек. участках для задержки перед выходом

Пример:
1 2 3 4
5 6 7 8
9 0 1 2
3 4 5 6

Результат:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
Enter name of file
 12 .txt
 16                                    // кол-во элементов - правильно
 4                                     // кол-во строк/столбцов - правильно
 1   2   3   4   5   6   7   8   9   0   1   2   3   4   5   6       // список элементов - правильно
 49        50        51        52            // результат - неправильно!!!
 53        54        55        56 
 57        48        49        50 
 51        52        53        54 
И еще: если в исходной матрице число, допустим, десятичное, то input_file распознает его как два числа!
...
Рейтинг: 0 / 0
11.01.2006, 11:46
    #33476040
BBrAT
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите найти ошибку
Все, понял. element[64] у меня char, отсюда все ошибки. Но как тогда реализовать проверку синтаксиса? Можно перехватить ошибку при попытке записи буквы в int? И условие - все переменные должны быть динамические. Как тогда узнать размер матрицы?
...
Рейтинг: 0 / 0
17.01.2006, 22:04
    #33488310
BBrAT
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите найти ошибку
Ладно, забил на проверку, другая проблема: как после input_file заставить программу читать файл сначала?
...
Рейтинг: 0 / 0
18.01.2006, 01:38
    #33488415
Гадёныш
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите найти ошибку
блин... потоки это конечно хорошо, но под чистым С это была бы функция

fseek

--------------------------------------------------------------------------------

Функция Устанавливает указатель файла в потоке.

Синтаксис #include <stdio.h>
int fseek(FILE * stream, long offset,
int fromwhere);

Файл, содержащий stdio.h
прототип

Описание Функция fseek устанавливает адресный указатель
файла, соответствующий потоку stream, в новую
позицию, которая расположена по смещению offset
относительно места в файле, определяемого
параметром fromwhere.

Параметр fromwhere может иметь одно из трех
значений 0, 1 или 2, которые представлены тремя
символическими константами (определенными в файле
stdio.h), следующим образом:

--------------------------------------------------
Параметр Размещение в файле
fromwhere
--------------------------------------------------
SEEK_SET (0) начало файла;
SEEK_CUR (1) позиция текущего указателя
файла;
SEEK_END (2) конец файла (EOF);
--------------------------------------------------

Функция fseek сбрасывает любой символ, записанный с
помощью функции ungetc.

Функция fseek используется с операциями
ввода/вывода в поток. При работе с дескриптором
файла пользуйтесь функцией lseek.

После этой операции можно производить как ввод, так
и вывод в поток.

Возвращаемое Функция fseek возвращает значение 0, если
значение указатель файла успешно перемещен, и ненулевое
значение в случае неудачного завершения.

Примечание. Функция fseek может вернуть нулевое
значение даже в случае, если этого не было. Это
происходит в результате того, что DOS, которая и
перемещает указатель, не проверяет его установку.
fseek возвращает индикатор ошибки только в случае,
если устройство или файл не открыты.

Переносимость Данная функция поддерживаются на системах UNIX
и стандартом ANSI C.

Смотрите также fgetpos, fopen, fsetpos, ftell, lseek, rewind,
setbuf, tell.

Пример:

#include <stdio.h>
int main(void)
{
FILE *stream;
stream = fopen("MYFILE.TXT", "r");
print("filesize of MYFILE.TXT is %ld bytes\n",
filesize(stream));
}
long filesize(FILE *stream);
{
long curpos,length;
/* сохранить текущее положение указателя */
curpos = ftell(stream);
/* перейти в конец файла */
fseek(stream, 0L, SEEK_END);
/* получить текущее положение указателя */
length = ftell(stream);
/* восстановить старое положение */
fseek(stream, curpos, SEEK_SET);
return(length);

ищи в потоках похожую
...
Рейтинг: 0 / 0
18.01.2006, 01:41
    #33488416
Гадёныш
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите найти ошибку
насчёт проверки....

isdigit

--------------------------------------------------------------------------------

Функция Макро классификации символов.

Синтаксис #include <ctype.h>
int isdigit(int ch);

Файл, содержащий ctype.h
прототип

Описание isdigit - это макрокованда, которая классифицирует
целые значения в коде ASCII, просмотром таблицы.
При true она возвращает ненулевое значение и 0 при
false. Она определена только в том случае, если
isascii(ch) равно true или ch = EOF.

Вы можете вместо макрокоманды, использовать
функцию, если воспользуетесь директивой #undef.

Возвращаемое isdigit возвращает ненулевое значение если ch -
значение это цифра ('0'-'9')

Переносимость isdigit доступна в системах UNIX и поддерживается
стандартом ANSI C.

Пример:

#include<ctype.h>
#include<stdio.h>

int main(void)
{
char c = 'C';
if(iscntrl(c))
printf("%c - цифра\n",c);
else
printf("%c - не является цифрой\n",c);
return 0;
}

для цифр...

для чисел юзай

Функция Преобразует строку в целое число.

Синтаксис #include<stdlib.h>
int atoi(const char *s);

Файл, содержащий stdlib.h
прототип

Описание Функция atoi преобразует символьную строку,
адресный указатель которой находится в аргументе s,
в число типа int; данная функция распознает в
следующем порядке:

- необязательную строку табуляции и пробелов;
- необязательный знак;
- строку цифр.

Символы должны соответствовать следующему формату:

[пробелы] [знак] [ddd]

Эта функция прекращает преобразование на первом
нераспознаваемом символе.

atoi не отслеживает переполнение.

Возвращаемое atoi возвращает преобразованное значение
значение входной символьной строки. Если строка не может
быть преобразована в число соответствующего типа
(int), то возвращаемое значение равно 0.

Переносимость Поддерживается в системах UNIX и определена в ANSI
C.

Смотрите также atof, atol, ecvt, fcvt, gcvt, scanf, strtod.

Пример:

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

int main(void)
{
int n;
char *str = "12345";
n = atoi(str);
printf("строка = %s целое = %d\n",str,n);
return 0;
}
...
Рейтинг: 0 / 0
18.01.2006, 02:30
    #33488430
Гадёныш
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите найти ошибку
воть на чистом С
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
#include <stdio.h>
#include <conio.h>
#include <math.h>
int main()
{
 clrscr();
 printf("Enter name of file: ");
 FILE *infile;
 char filename[] = "d:\\tc\\far\\1.txt";//под дос если юзать стандартные функции длина файла 8+3
// scanf("%s",filename);

 if((infile = fopen(filename,"r"))==NULL)
   {
     fprintf(stderr, "\ncan't open file \n");
     return - 1 ;
   }

 //только форматированная строка!
 int i,kolsymb= 0 ;

while(!feof(infile))
 {
  if(fscanf(infile,"%d",&i))kolsymb++;
  else
    {
     printf("\nThere are symbols in the source\n");
     return - 1 ;
    }
 }

int tmp = sqrt(kolsymb) ;

if(tmp*tmp != kolsymb)
  {
   printf("\nmatrix is not quadro\n");
   return - 1 ;
  }

int **matrix;
matrix = new int *[tmp];
for(i= 0 ;i<tmp;i++)
 matrix[i] = new int[tmp];

i= 0 ;
int j= 0 ;
fseek(infile,0L,SEEK_SET);
while(!feof(infile))
 {
  if(i%(tmp) ==  0  && i !=  0 ){i= 0 ;j++;}
  fscanf(infile,"%d",&matrix[i++][j]);
 }
printf("\n");
for(i= 0 ;i<tmp;i++)
 {
  for(j= 0 ;j<tmp;j++)
    printf("%-6d",matrix[i][j]);
  printf("\n");
 }

for(i= 0 ;i < tmp;i++)
  delete [ ] matrix[ i ];
delete [ ] matrix;
return  0 ;
}
...
Рейтинг: 0 / 0
18.01.2006, 13:41
    #33489370
BBrAT
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите найти ошибку
Круто:) Но необходимо на чистом С++
Такаой вопрос: а почему printf? Просто интересно.
Решил не использовать проверку, все равно невозможно (насчет isdigit : используют только с char, а его употреблять нельзя, ибо условие - динамические структуры)
Перевод указателя на начало -
Код: plaintext
input_file.seekg( 0 )
но не могу заставить работать:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
//*** получение размера ******
int element;
  while (! input_file.eof())
   {
      input_file >> element;
      *psize+= 1 ;
   }
//****************************
//...............................
//*********** присвоение ********************
input_file.seekg( 0 );

for (i= 0 ; i<*psize;i++){
	for (int j= 0 ;j<*psize;j++){
		input_file >> *(*(matrix+i)+j);
	}
}
//*******************************************
...
Рейтинг: 0 / 0
18.01.2006, 14:07
    #33489453
Станислав C.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите найти ошибку
BBrATКруто:) Но необходимо на чистом С++
Такаой вопрос: а почему printf? Просто интересно.
Решил не использовать проверку, все равно невозможно (насчет isdigit : используют только с char, а его употреблять нельзя, ибо условие - динамические структуры)

Странно... Обычно требуют на чистом С. Скорее всего требование чистого С++ связано с необходимостью исключить разные "вкусности" типа MFC, Qt и т.д. и использовать только "стандартные" библиотеки...

Динамические структуры и char никак не связаны: преобразуй int к строке (char *), затем выполни проверку (isdigit) и т.д.
А динамические структуры называются так потому, что на этапе компиляции их размер неизвестен...

У меня такое предложение:
сделать так же, как при вводе "бесконечной" строки: выделять/реаллокировать память по мере надобности (при прочтении очередного значения), а затем, после ввода всех данных, обращаться к данным в блоке памяти как к двумерному массиву (матрице) - по индексам... Правда, в этом случае данные в файле должны храниться "по строкам"...
...
Рейтинг: 0 / 0
18.01.2006, 14:31
    #33489528
redskin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите найти ошибку
BBrATКруто:) Но необходимо на чистом С++

Есть файловый поток ввода ifstream. У него есть метод seekg. Точно такой же как fseek в сишной библиотеке. Всё.

Вот пример как оно работает:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
    if(argc >  1 )
    {
        ifstream ifs(argv[ 1 ]);
        if(ifs)
        {
            string s;
            ifs >> s;
            cout << s << endl;

            ifs.seekg( 0 );
            ifs >> s;
            cout << s << endl;
        }
    }
    return  0 ;
}

...
Рейтинг: 0 / 0
19.01.2006, 00:11
    #33490546
BBrAT
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите найти ошибку
Код из моего предыдущего соощения не работал, т.к. необходимо было добавить
Код: plaintext
input_file.clear();
2 Станислав С.: я имел ввиду не это, да ладно, все равно шел не в том направлении...
В общем, Все исправил, все работает, спасибо за советы!
И все-таки остался один вопрос: в чем отличие потокового i/o от низкоуровнего и почему стоит выбрать один из них?
...
Рейтинг: 0 / 0
19.01.2006, 02:22
    #33490588
Гадёныш
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите найти ошибку
И все-таки остался один вопрос: в чем отличие потокового i/o от низкоуровнего и почему стоит выбрать один из них?

потоковые stream основаны на низкоуровневых... потому работают немного медленее...

если есть смысл экономии времени надо юзать printf..
я просто к ним привык, долго мну мучали с логическим програмированием те олимпиады и другое, а там скорость програмы это один с показателей...х)

и ещё если ты юзаеш fstream подключать iostream уже не нуна...
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Помогите найти ошибку / 11 сообщений из 11, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]