PDA

Показать полную графическую версию : заполнение массива


Lisiy_egik
14-11-2009, 17:08
Столкнулся с проблемой:
неком исходном файле содержатся данные в виде:

пн 23.3 55.8 32.5
вт 54.3 23.4
сб 45.7.78.1

или просто:
65.3 74.4 85.2
23.4 54.3
и т.д.

нужно заполнить массив double [7][]
в итоге массив содержит измерения погоды (строки - дни недели. столбцы - измерения)

Вопрос: как заполнить такой массив? Как узнать длину каждой строки массива?

Lisiy_egik
14-11-2009, 19:09
появилась идея - можно запрашивать кол-во столбцов в самом начале.
примерно то, что родилось в голове:

#include<stdio.h>
#include <conio.h>

void main()
{
#define NR 7;
#define NC = a;
FILE *f;
int a;

printf("Какое кол-во измерений в день было произведено?(1 2 4 и т.д.)\n");
scanf("%i", &a);

float weather[NR][NC];
If ((f = fopen("weather.txt", "rt")) == NULL)
{
printf ("не удалось открыть файл \n"
getch();
return;
}

int r,c; // номер строки и столбца

for (r=0; r < NR; r++)
{
for(c = 0; c < NC; c++)
{
fscanf(f, "%f", wether[r][c]);
}
}

fclose (f);

}

1. Можно ли так использовать "#define NC = a"? или нужно " = *a" ?
2. Возможно ли обойтись без этой переменной "а"? Чтобы прежде чем заполнять массив, допустим посчитать кол-во элементов первой строки, содержащейся в файле?
3. Каким образом в данной ситуации использовать средства ввода/вывода с++ (cin/cout)
4. Будет ли правильно заполнен массив, если данные в файле выглядят примерно так:

65.4 -98.7 63.5 -46.5 12.3
38.7 38.7 30.8 65.7 74.8
44.5 75.0 -87.0 28.7 34.7
65.4 98.7 -63.5 -46.5 -12.3
38.7 387 30.8 65.7 74.8
-44.5 -75.0 -87.0 28.7 34.7
24.3 70.8 73.2 24.2 09.8

т.е. данные разделены пробелом, присутствуют как положительные. так и отрицательные значения

Admiral
14-11-2009, 19:30
Lisiy_egik, можно задать структуру файла Бинарные файлы (http://forum.oszone.net/thread-138194.html)
Единственное что по данной структуре должен быть и заполнен файл, так что если в блокноте где-то пробел был добавлен, программа может с ошибкой считать файл.
В идеале нужно что-б в самой проге и была произведена запись в файл.

Lisiy_egik
15-11-2009, 00:53
решил посмотреть как заполняется массив и вот что вышло:

#include "stdio.h"
#include "conio.h"
#include "rus8.h"

void main() {

rus();

#define NR 7
#define NC 3

FILE *f;

float weather[NR][NC];
int r = 0, c = 0;

//printf("Введите кол-во измерени в сутки:");
//scanf("%i", &a);

if ((f=fopen("weather.txt", "rt"))==NULL)
{
printf("Файл с исходными данными не найден");
getch();
return;
}
for (r=0; r < NR; r++)
{
for(c = 0; c < NC; c++)
{
fscanf(f, "%f", weather[r][c]);
}
}

fclose (f);

printf("Данные, загруженные из файла в массив:\n");

for(r = 0; r < NR; r++)
{
for(c = 0; c < NC; c++)
{
printf("%5.1f", weather[r][c]);
}
}

printf("\n \n я завершения нажминие Ввод");
getch();
}


или если поменять for на while

#include "stdio.h"
#include "conio.h"
#include "rus8.h"

void main() {

rus();

#define NR 7
#define NC 3

FILE *f;

float weather[NR][NC];
int r = 0, c = 0;

//printf("Введите кол-во измерени в сутки:");
//scanf("%i", &a);

if ((f=fopen("weather.txt", "rt"))==NULL)
{
printf("Файл с исходными данными не найден");
getch();
return;
}
while(r < NR)
{
while(c<NC)
{
fscanf(f, "%f", weather[r][c]);
}
c++;
}
r++;

fclose (f);

printf("Данные, загруженные из файла в массив:\n");

for(r = 0; r < NR; r++)
{
for(c = 0; c < NC; c++)
{
printf("%5.1f", weather[r][c]);
}
}

printf("\n \n я завершения нажминие Ввод");
getch();
}


в файле weather.txt содержится:
23.4 55.2 34.5
54.4 35.6 79.8
45.9 65.8 76.7
23.1 45.2 56.3
34.4 98.5 56.6
12.3 23.2 34.1
98.4 87.3 76.2

При компиляции ошибок нет, а вот при запуске выдает:

Необработанное исключение в "0x691c936c (msvcr90d.dll)" в "p2e1.exe": 0xC0000005: Нарушение прав доступа при записи "0x80000000".

В чем моя ошибка?

Ferum01
15-11-2009, 12:48
нужно заполнить массив double [7][]
в итоге массив содержит измерения погоды (строки - дни недели. столбцы - измерения)
Вопрос: как заполнить такой массив? Как узнать длину каждой строки массива? »
Я бы работал с переменной строки и при заполнии анализировал каждый символ (при анализе символов видно точки, пробелы и цыфры)... Потом есть операторы конца строки и конца фала, поэтому можно, не запрашивать количество измерений.
У меня есть прога похожего плана. Описание программы. Из файла заполненного разными символами выбрать все восеьмеричные комбинации цифр (например "hfdhfhdj45777789rerer jjjj 75 uhh78900987" выбираем 45777789 и 78900987).
Могу текст проги выложить, только там нет комментриев.

Ferum01
15-11-2009, 13:04
так наверное проще всего
for(r = 0; r < NR; r++)
fscanf(f,"%f %f %f\n", weather[r][0], weather[r][1], weather[r][2]);

если данные всегда вида:
23.4 55.2 34.5
54.4 35.6 79.8
45.9 65.8 76.7
23.1 45.2 56.3
34.4 98.5 56.6
12.3 23.2 34.1
98.4 87.3 76.2

Lisiy_egik
15-11-2009, 13:11
так наверное проще всего
for(r = 0; r < NR; r++)
fscanf(f,"%f %f %f\n", weather[r][0], weather[r][1], weather[r][2]);
если данные всегда вида:
23.4 55.2 34.5
54.4 35.6 79.8
45.9 65.8 76.7
23.1 45.2 56.3
34.4 98.5 56.6
12.3 23.2 34.1
98.4 87.3 76.2 »

в том то и дело, что кол-во элементов в различных строках одинаково, их может быть как 3 так и 5 так 100 в общем N(

Ferum01
15-11-2009, 13:53
Тогда примерно так:

while(!feof(f))
{
do
{
fscanf(fp1, "%c", &sim[eatt]);
if (sim[eatt]=='\n') break;

do
{
if ( sim[eatt]=='0' || sim[eatt]=='1' ||
sim[eatt]=='2' || sim[eatt]=='3' ||
sim[eatt]=='4' || sim[eatt]=='5' ||
sim[eatt]=='6' || sim[eatt]=='7' ||
sim[eatt]=='8' || sim[eatt]=='9' || sim[eatt]=='.')
{ eatt++; fscanf(f, "%c", &sim[eatt]); } else break;
} while (true);
weather[r][]=sim; r++;
// изначально так было strcpy(number1[num1],sim); можно ли символьную переменную целой присваивать не помню...
eatt=0;
} while (!feof(f));
fscanf(f, "\n");
}
fclose(f);

Lisiy_egik
15-11-2009, 14:00
weather[r][]=sim; r++; »

спасиб, ток вопрос - что обозначает эта строка? как я понимаю присваиваем значение sim массиву затем переходим на новую строку, а каким образом присваивается элемент строки? (weather[r][-вот этот-])? и как узнать, коке кол-во элементов в итоге получилось? (эта цифра прост для дальнейшей работы нужна)) )

Ferum01
15-11-2009, 14:10
спасиб, ток вопрос - что обозначает эта строка? как я понимаю присваиваем значение sim массиву затем переходим на новую строку, а каким образом присваивается элемент строки? (weather[r][-вот этот-])? и как узнать, коке кол-во элементов в итоге получилось? (эта цифра прост для дальнейшей работы нужна)) ) »

Все правильно, только не могу сказать точно будет ли так работать присваивание, но всеравно как должно работать.

Количество элементов в строке определяет "eatt" ее наверное надо записать в дополнительный массив массива weather.

Lisiy_egik
15-11-2009, 23:24
я додумался, как определить кол-во элементов в строке. Столкнулся с такой проблемой:
при объявлении массива weather[NR][NC] компилятор сообщает об ошибке, т.к. не может разместить в памяти массив с нулевой размерностью.

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

#include <iostream>
#include <fstream>
#include "rus8.h"
#include "conio.h"
using namespace std;

int main() {

rus();
#define NR 7
#define NC *c

char str[100], ch;
int i=0,n=0, r, c;
float weather[NR][NC];

ifstream in("weather");
if(!in)
{
cout << "Не удалось открыть файл";
getch();
return 1;
}

in.get(str, 99);
cout << str <<'\n';
in.close();

for(n=0;str[n];n++)
{
if(str[n] == ' ')
{
i++;
cout << "Найден пробельный символ\n";
}
cout << "Символ не является пробелом \n";
}

c=i+1;

cout << "\n Всего символов " << n << " Из них пробельных " << i;

cout << "\n для завершения нажминие Ввод";
getch();

return 0;
}

вот такие ошибки MVS выдает на float weather[NR][NC];
main.cpp(15) : error C2100: недопустимое косвенное обращение
main.cpp(15) : error C2057: требуется константное выражение
main.cpp(15) : error C2466: невозможно выделить память для массива постоянного нулевого размера
main.cpp(15) : error C2087: weather: отсутствует индекс

Ferum01
16-11-2009, 09:59
я думаю на #define NC *c ругается, константа не должна меняться, это же не перменная.

Lisiy_egik
16-11-2009, 16:37
все то. что я делал не верно, нужно было через структуру делать, потом читать не символы, а то. что мне точно известно - это значения типа дабл, в общем пойду читать книжки умные и форумы рыть ((

Ferum01
17-11-2009, 11:45
Если будет время сделаю заполнение массива по вашему случаю... Структура нужна для удобства, но в ней то всеравно надо алгоритм реализовывать...

Ferum01
19-11-2009, 17:52
Сделал, пользуйте...

//---------------------------------------------------------------------------

#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <vcl.h>
#pragma hdrstop
#pragma argsused

int main(int argc, char* argv[])
{
char sim[63]; // максимально возможная длина числа
int a, b, eatt=0, numa=0,numb=0,
numstr[1000]; // количество чисел в каждой строке
double number[1000][100]; // массив всех чисел, построчно

FILE*fp1;

if ((fp1=fopen("1397000.txt", "r"))==NULL) // считывание чисел из файла 1397000.txt
{
printf ("not file");
return 0;
}

do { //*******
fscanf(fp1, "%c", &sim[eatt]);

do //*
if ( sim[eatt]=='0' || sim[eatt]=='1' || sim[eatt]=='2' || sim[eatt]=='3' ||
sim[eatt]=='4' || sim[eatt]=='5' || sim[eatt]=='6' || sim[eatt]=='7' ||
sim[eatt]=='8' || sim[eatt]=='9' || sim[eatt]=='.' || sim[eatt]=='-')
{eatt++; fscanf(fp1, "%c", &sim[eatt]); } else break;
while (true); //*

if (sim[eatt]==' ') {number[numa][numb]=atof(sim); numstr[numa]=numb; numb++; eatt=0;}
if (sim[eatt]=='\n') {number[numa][numb]=atof(sim); numstr[numa]=numb; numb++; eatt=0; numa++; numb=0;}

} //*******
while (!feof(fp1)); //*******


fclose(fp1);

// ввод всех преобразованных чисел (в double) в файл 1397001.txt
FILE*fp;
fp=fopen("1397001.txt", "w");

for (a=0; a<=numa-1; a++)
{
for (b=0; b<=numstr[a]; b++)
fprintf (fp,"%f ",number[a][b]);
fprintf (fp,"\n");
}

fclose(fp);

return 0;
}
//---------------------------------------------------------------------------

pva
19-11-2009, 21:40
Не совсем по теме конечно, вот как ещё можно сделать. здесь не хранится в виде *double[7]

#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <iterator>
#include <sstream>
#include <iomanip>
using namespace std;

int main(int argc, char* argv[])
{
string str1;
map<string,vector<double> > weather_by_wday;

while(getline(cin, str1)) // перебираем строчки
{
istringstream line_stm(str1);

if ((line_stm >> str1)) // день недели
{
typedef istream_iterator<double,char> istream_iter;
// копируем в него данные из потока
copy(istream_iter(line_stm), istream_iter(), back_inserter(weather_by_wday[str1]));
}
}

// теперь всё упорядочено по дням недели
// weather_by_wday["день недели"] - это вектор данных
// можно пользоваться им так: weather_by_wday["ВТ"][3] - это будет 3-й вторник
// допустим надо вывести на экран

typedef map<string,vector<double> >::iterator map_iter_t;
unsigned max_data_size = 0;

// т.к. длины векторов могут быть разные, найдём самый длинный

string order[7] = {"mon", "tue", "wed", "thr", "fri", "sat", "sun"};

for(unsigned wday=0; wday<7; ++wday)
{
cout << setw(10) << order[wday];
unsigned size1 = weather_by_wday[order[wday]].size();
if (max_data_size<size1) max_data_size=size1;
}

for(unsigned n=0; n<max_data_size; ++n)
{
cout << "\n";

for(unsigned wday=0; wday<7; ++wday)
{
cout << setw(10);
vector<double> &weather(weather_by_wday[order[wday]]);
if (n<weather.size()) cout << weather[n];
else cout << "?";
}
}

return 0;
}

Lisiy_egik
20-11-2009, 12:52
Ferum01, pva, спасибо большое, это действительно очень помогло

Lisiy_egik
20-11-2009, 13:46
#include <vcl.h> »
за что отвечает этот модуль? где его можно взять и как его добавить в библиотеку MVS2008?

Ferum01
20-11-2009, 14:58
за что отвечает этот модуль? где его можно взять и как его добавить в библиотеку MVS2008? »
vcl.h - библиотека визуальных компонентов, она изначально стоит при создании программ в компиляторе Borland 5.
Вероятно эту библиотеку можно не использовать.




© OSzone.net 2001-2012