Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 07.01.2012, 22:08   #1
neonakaneya
Пользователь
 
Регистрация: 02.01.2012
Сообщений: 19
По умолчанию Сдвиг элементов массива и вопрос о strcpy

Ситуация такая: вроде как полностью написал решение задачи, но на этапе поиска одинаковых строк в массиве строк и попытке сдвинуть элементы массива так, чтобы скрыть одну из повторяющихся строк, что-то идет не так, хотя с моей точки зрения все написано верно.
Вот пример входного и выходного файла.

И само условие задачи:
У меня же выхлоп получается такой:
Цитата:
a111aa78 3000
o000oo00 300
o000oo00 0
Вот весь код:
Код:
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;

int main ()
{
	ifstream fin("Input.txt");
	ofstream fout ("Output.txt");
	
    char m[6];//массив для первой строки
	fin.getline(m,4);//считываем первую строку для определения количества N строк с номерами 
    int N;//количество строк с номерами
    if(m[0]>=1) N=(m[0]-48);               
	if(m[1]>=1) N=(m[0]-48)*10 +(m[1]-48); //определяем кол-во номеров и присваиваем это значение переменной N
	if(m[2]>=1) N=(m[0]-48)*100 + (m[1]-48)*10 +(m[2]-48);
	
	char Arrays[100][13]; //массив со со всеми номерами и скоростью через пробел
    for(int a=0;a<N;a++) fin.getline(Arrays[a],13); // берем строку из входного файла, записываем ее в массив ArrayStr.

	int SpeedBanArray[100];//массив в котором храним штраф.
	for(int b=0;b<N;b++)
	{//пишем скорость в SpeedBanArray
		if(Arrays[b][10]=='\0') SpeedBanArray[b]=(Arrays[b][9]-48);
		if(Arrays[b][11]=='\0') SpeedBanArray[b]=(Arrays[b][9]-48)*10 + (Arrays[b][10]-48);
		if(Arrays[b][12]=='\0') SpeedBanArray[b]=(Arrays[b][9]-48)*100 + (Arrays[b][10]-48)*10 + (Arrays[b][11]-48);
		/*cout<<SpeedBanArray[b]<<endl;*/
	}

	for(int c=0;c<N;c++)
	{//сравниваем скорость с таблицей штрафов,  выносим штраф
		int tempary=SpeedBanArray[c] ;
		if(tempary <=70) SpeedBanArray[c]=0;
		if((tempary >=71) && (80>= tempary)) SpeedBanArray[c]=100;
		if((tempary >=81) && (100>= tempary)) SpeedBanArray[c]=300;
		if((tempary >=101) && (120>= tempary)) SpeedBanArray[c]=1000;
	    if(tempary >=121) SpeedBanArray[c]=2000;
          /*cout<<SpeedBanArray[c]<<endl;*/
	}
	//теперь нужно сравнить строки массива Arrays между собой и суммировать штраф, а ТАКЖЕ удалить(смещение) одинаковые строки.
	for(int first=0;first<N;first++) 
	{
		for(int second=first;second<N;second++)
		{
	      if(strcmp(Arrays[first],Arrays[second+1])==1)//сравниваем номера, если совпадают - суммируем штраф, и сдвигаем массивы(удаляем повторы)
		  {
			  SpeedBanArray[second+1]=SpeedBanArray[first]+SpeedBanArray[second+1]; //суммируем штраф 
			  for(int shift=first;shift<N;shift++) 
			      {
				  SpeedBanArray[shift]=SpeedBanArray[shift+1];   //сдвигаем элементы массива,чтобы "скрыть" повторяющиеся
                  strcpy(Arrays[shift],Arrays[shift+1]);   //судя по всему ошибка тут , 
но не могу понять в чем она заключается 
			      }
              N--;//уменьшаем переменную отвечающую за число строк 
		   } 
		}
	}
	

	 //сортируем пузырьком массив SpeedBanArray  по убыванию 
	int tmp=0;
	char buble[1][13];
	for (int one = 0; one<N; one++)
	{
		for(int two=0 ; two<N-one-1;two++)

		{
			if (SpeedBanArray[two]<SpeedBanArray[two+1]) 
			 {
				 tmp = SpeedBanArray[two];                        //переставляем элементы массива SpeedBanArray по убыванию
				 SpeedBanArray[two]=SpeedBanArray[two+1];
				 SpeedBanArray[two+1]= tmp;

				 for(int arshifttwo=0;arshifttwo<9;arshifttwo++)  // и так же переставляем соответсвующие им номера.
				 {
				 buble[0][arshifttwo]=Arrays[two][arshifttwo];
				 Arrays[two][arshifttwo]=Arrays[two+1][arshifttwo];
				 Arrays[two+1][arshifttwo]=buble[0][arshifttwo];
				 }
             }
		}
    }

	for(int conclusion=0;conclusion<N;conclusion++)//выводим пары номер-штраф в выходной файл через пробел
	{
	   for(int d=0;d<9;d++) fout<<Arrays[conclusion][d];
	   fout<<SpeedBanArray[conclusion]<<endl;
	}

	return 0;
}
Делал вывод на консоль после цикла, в котором сдвигаем элементы - получил те же номера, что и в моем выходном файле( но естественно в другом порядке) . Т.е. ошибка точно происходит еще до пузырька. Но в чем она заключается -понять не могу. Либо я где то в логике не туда ушел , либо глаз замылился и я не вижу банальной ошибки.
Подскажите в какую сторону думать?

Последний раз редактировалось neonakaneya; 07.01.2012 в 22:26.
neonakaneya вне форума Ответить с цитированием
Старый 07.01.2012, 22:54   #2
onewho
Форумчанин
 
Регистрация: 29.09.2010
Сообщений: 636
По умолчанию

аааа... ппц
Цитата:
int N;//количество строк с номерами
if(m[0]>=1) N=(m[0]-48);
if(m[1]>=1) N=(m[0]-48)*10 +(m[1]-48); //определяем кол-во номеров и присваиваем это значение переменной N
if(m[2]>=1) N=(m[0]-48)*100 + (m[1]-48)*10 +(m[2]-48);
atoi не?

по остальному:
код плохо читаем, править другому человеку довольно сложно.
если совсем хочется так делать - то юзай дебаг...

про сдвиги какие-то ваще не понял.

я бы сделал так:
структура из 2 полей - номер и суммарный штраф. и массив структур соотв-но.

а если разрешено юзать СТЛ то вообще std::map и решение будет в 6 раз короче.
onewho вне форума Ответить с цитированием
Старый 08.01.2012, 00:13   #3
neonakaneya
Пользователь
 
Регистрация: 02.01.2012
Сообщений: 19
По умолчанию

onewho%) Вы меня морально уничтожили как новичка количеством новой информации.
По порядку:
про atoi только от вас узнал, я так понимаю она берет массив char и конвертит его в int?
А есть какие-то гайды как сделать код читабельным? Еще раз повторюсь - я с++ начал изучать чуть больше недели назад , так что еще новичок как в самом с++, так и в программировании вообще.
Про сдвиг :
Мне нужно найти повторяющиеся элементы массива , и удалить их все, оставив только один. Сообственно само "удаление" я делал с помощью сдвига(может это не так называется, но я так это обозвал) последующих элементов массива на одну позицию назад.
пример было {2,3,4,5,2,6,7,5} , а стало {3,4,2,6,7,5}

Цитата:
я бы сделал так:
структура из 2 полей - номер и суммарный штраф. и массив структур соотв-но.

а если разрешено юзать СТЛ то вообще std::map и решение будет в 6 раз короче.
из этого всего я знаю только, что STL это стандартная библиотека шаблонов(не знаю можно ли ее использовать на олимпиаде, по крайней мере в условии ни про какие ограничения не написано) , про остальное еще пока не слышал / не дошел до этого. ( читаю "Шилдт Г. С++ Базовый курс, 3-е издание,2010")

Последний раз редактировалось neonakaneya; 08.01.2012 в 00:22.
neonakaneya вне форума Ответить с цитированием
Старый 08.01.2012, 00:23   #4
Rififi
Старожил
 
Регистрация: 19.08.2009
Сообщений: 2,119
По умолчанию

neonakaneya

А есть какие-то гайды как сделать код читабельным?

Самый главный гайд - "Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете" (c) Стив Макконнелл

еще - гоогле по этому имени и "оформление кода"

Мне нужно найти повторяющиеся элементы массива , и удалить их все, оставив только один

для этого достаточно скопировать все элементы массива в стандартный контейнер std::set, который не допускает повторений.

например:

Код:
int arr[] = {...}; // массив с повторениями
const size_t N = sizeof(arr) / sizeof(arr[0]); // размер массива

std::set<int> distinct;
std::copy(arr, arr + N, std::inserter(distinct, distinct.begin()));
Rififi вне форума Ответить с цитированием
Старый 08.01.2012, 00:50   #5
onewho
Форумчанин
 
Регистрация: 29.09.2010
Сообщений: 636
По умолчанию

понял вас, да не всё нормально для новичка.

atoi - да, запомни на будущее. а вообще я чёт сглупил можно вообще просто написать.

Код:
fin >> N;
данный оператор автоматически преобразует строку в инт!

Цитата:
А есть какие-то гайды как сделать код читабельным?
да нет с оформлением всё норм, просто в этой каше (сори) сложно ухватить мысль...

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

ты всё я смотрю читаешь как строки и потом их переводишь... ну здесь это излишне.

структуры знаешь?

хотел набросать код кратко примерный, в итоге написал всё, т.к просто довольно вышло.
Код:
struct Payment {

	char sign[20]; // номер
	int fee; // штраф

};

int main(int argc, char *argv[]) {

	ifstream fin("Input.txt");
	ofstream fout ("Output.txt");

	char s[20]; // временные
	int f;

	Payment p[100] = { // обнулячим всё.
		{0,0}
	};

	int N;

	fin >> N;

	for (int i=0, flag; i<N; i++) {

		flag =0; // штрафник уже есть в списке 'p' ?

		fin >> s >> f; // читаем временные
		
		for (int j=0; j<i; j++) {
			if (strcmp(s,p[j].sign)==0) { // нашли штрафника.
				p[j].fee+=f;
				flag=1; // штрафник есть.
				break;
			}
		}

		if (flag==0) // не нашли штрафника - добавим.
			strcpy(p[i].sign,s), p[i].fee=f;

	}

	for (int i=0; i<N; i++) {
		fout << p[i].sign << ": " << p[i].fee << '\n';
	}



getchar();
return 0;
}
тут есть 2 (очевидных для твоей задачи) недостатка.
выводит всегда N штрафников в файл независимо от реального числа их (<=N)
и штраф я не рассчитывал из скорости а просто суммировал 2-ое поле.

предлагаю тебе исправить 1ый баг и написать функцию которая принимает скорость и возвращает штраф за нарушение.
onewho вне форума Ответить с цитированием
Старый 08.01.2012, 13:49   #6
neonakaneya
Пользователь
 
Регистрация: 02.01.2012
Сообщений: 19
По умолчанию

Переделал с использованием atoi , получилось покороче, и выхлоп теперь другой, но все равно не верный
Цитата:
a111aa78 2000 //т.е. почему-то не суммируются два штрафа для номера a111aa78
a111aa78 1000
o000oo00 300
a234bv56 0
Вот код:
Код:
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;

int main ()
{
	ifstream fin("Input.txt");
	ofstream fout ("Output.txt");
	int N;
	char m[4];
        fin.getline(m,4);
        N=atoi(m);//количество строк с номерами

	int ban[100];// массив для штрафов
	char Arrays[100][11]; //массив со со всеми номерами 
        for(int a=0; a<N; a++) {
		 char ch[6];//временный массив для считывания скорости
                 fin.getline(Arrays[a],10,' '); // берем номер машины из входного файла, записываем ее в массив Arrays.
		 fin.getline(ch,5); // берем скорость и пишем ее во временный массив ch
		 int tempary=atoi(ch); 
		 if(tempary <=70) ban[a]=0; // сравниваем скорость с таблицей штрафов 
		 if((tempary >=71) && (80>= tempary)) ban[a]=100;   // и записываем штраф в массив ban
		 if((tempary >=81) && (100>= tempary)) ban[a]=300;
		 if((tempary >=101) && (120>= tempary)) ban[a]=1000;
	         if(tempary >=121) ban[a]=2000;

	}

	//теперь нужно сравнить строки массива Arrays между собой , а ТАКЖЕ удалить(смещением) одинаковые строки(оставив только одну из них) и суммировать их штраф.
	for(int first=0; first<N; first++) {
		for(int second=first; second<N; second++) {
			if(strcmp(Arrays[first],Arrays[second+1])==1) { //сравниваем номера, если совпадают - суммируем штраф, и сдвигаем массивы(удаляем повторы)
			  ban[second+1]=ban[first]+ban[second+1];     //суммируем штраф 
			  for(int shift=first; shift<N; shift++) {
				  ban[shift]=ban[shift+1];               //сдвигаем элементы массива,чтобы "скрыть" повторяющиеся
                                  strcpy(Arrays[shift],Arrays[shift+1]);
				  }

			    N--;  //уменьшаем переменную отвечающую за число строк
		   } 
	    }
	}


	//сортируем пузырьком массив SpeedBanArray  по убыванию 
	int tmp=0;
	char buble[1][13];

	for (int one=0; one<N; one++) {
		for(int two=0; two<N-one-1; two++) {
			if (ban[two]<ban[two+1]) { 
				 
				 tmp=ban[two];                        //переставляем элементы массива Ban по убыванию
				 ban[two]=ban[two+1];
				 ban[two+1]=tmp;

				 for(int arshifttwo=0; arshifttwo<9; arshifttwo++) {  // и так же переставляем соответсвующие им номера.
					buble[0][arshifttwo]=Arrays[two][arshifttwo];
					Arrays[two][arshifttwo]=Arrays[two+1][arshifttwo];
					Arrays[two+1][arshifttwo]=buble[0][arshifttwo];
				 }
             }
	}
    }
	

	
       for(int conclusion=0;conclusion<N;conclusion++) {//выводим пары номер-штраф в выходной файл через пробел
	   for(int d=0;d<9;d++) fout<<Arrays[conclusion][d];
	   fout<<ban[conclusion]<<endl;
	}

	system("pause");
	return 0;
}

Последний раз редактировалось neonakaneya; 08.01.2012 в 13:53.
neonakaneya вне форума Ответить с цитированием
Старый 08.01.2012, 13:55   #7
neonakaneya
Пользователь
 
Регистрация: 02.01.2012
Сообщений: 19
По умолчанию

Цитата:
Сообщение от Rififi Посмотреть сообщение
neonakaneya

А есть какие-то гайды как сделать код читабельным?

Самый главный гайд - "Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете" (c) Стив Макконнелл

еще - гоогле по этому имени и "оформление кода"

Мне нужно найти повторяющиеся элементы массива , и удалить их все, оставив только один

для этого достаточно скопировать все элементы массива в стандартный контейнер std::set, который не допускает повторений.

например:

Код:
int arr[] = {...}; // массив с повторениями
const size_t N = sizeof(arr) / sizeof(arr[0]); // размер массива

std::set<int> distinct;
std::copy(arr, arr + N, std::inserter(distinct, distinct.begin()));
что-то я совсем не понял как поступить с set Х_Х
neonakaneya вне форума Ответить с цитированием
Старый 08.01.2012, 14:21   #8
neonakaneya
Пользователь
 
Регистрация: 02.01.2012
Сообщений: 19
По умолчанию

Номер a111aa78 во входном файле первый(и повторяется на четвертом месте), т.е. в массиве arrays он под индексом [0] (и повторяющийся под индексом [3]). В двух вложенных циклах for условие if(strcmp(Arrays[first],Arrays[second+1])==1)
то бишь при first=0 и second=2 if(strcmp(Arrays[0],Arrays[2+1])==1) должно быть истинно(т.к. эти две строки одинаковы) , но судя по выводу это не так. Непонятно почему
neonakaneya вне форума Ответить с цитированием
Старый 08.01.2012, 15:11   #9
Rififi
Старожил
 
Регистрация: 19.08.2009
Сообщений: 2,119
По умолчанию

neonakaneya

что-то я совсем не понял как поступить с set Х_Х

Ничего страшного. Для вашего уровня это нормально. Читайте книге и да придет к вам просветление.
Rififi вне форума Ответить с цитированием
Старый 09.01.2012, 00:27   #10
neonakaneya
Пользователь
 
Регистрация: 02.01.2012
Сообщений: 19
По умолчанию

кажется я допетрил почему у меня были проблемы
http://www.cplusplus.com/reference/c...string/strcmp/
"A zero value indicates that both strings are equal."
а я почему-то считал что когда строки равны , то она возвращает единицу(поэтому в if'e сравнивал ее с единицей), а оказалось что она возвращает 0 , когда строки равны.
neonakaneya вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
циклический сдвиг элементов массива Carter Паскаль, Turbo Pascal, PascalABC.NET 0 19.12.2011 19:54
Сдвиг элементов массива на 1 влево. Вывести матрицу в Memo Abrokadawr Помощь студентам 3 04.11.2011 23:13
Удаление элементов массива и сдвиг Alex11223 Паскаль, Turbo Pascal, PascalABC.NET 1 12.01.2011 20:01
Описать процедуру,осуществляющую циклический сдвиг элементов массива на k позиций Bloodpoisoning Общие вопросы C/C++ 0 29.11.2010 15:50
Вопрос про циклический сдвиг массива С++ Юлия12 Общие вопросы C/C++ 4 08.02.2010 08:52