Hilfe beim Umschreiben von C>C++ Code

pap

Mitglied
Hallo zusammen,
ich wuerde gerne meinen C Code in C++ umscheiben, bin in der C++ Materie aber leider noch voellig blind unterwegs. Kann mir da vielleicht jemand unter die Arme greifen?
Ich poste hier mal meinen ersten Abschnitt:
Code:
#include "date.h"
#include "person.h"
#include "list.h"
#include <stdio.h>


/*a function to create some list content*/
void testlist1(plist *list)
{
	person *p;

	p = create_pexp("albert", "weiss", 3, 6, 2003);
	add(list, p);
	p = create_pexp("klaus", "kunze", 10, 5, 2003);
	add(list, p);
	p = create_pexp("albertus", "weiman", 2, 6, 2003);
	add(list, p);
	p = create_pexp("stefan", "adam", 10, 5, 2004);
	add(list, p);

}

/*the main program whoch creates an empty list, adds some entries
 * and searches and removes some elements, finally the list will be cleared*/
int main()
{
	plist *list = create_empty_list();
	testlist1(list);
	print_l(list);
	printf("----------------------------\n");
	bubblesort(list, &pcmp_lastname);
	printf("sorted by last name\n\n");
	print_l(list);
	bubblesort(list, &pcmp_firstname);
	printf("sorted by firs tname\n\n");
	print_l(list);
	bubblesort(list, &pcmp_birthday);
	printf("sorted by date of birth\n\n");
	print_l(list);
	print_l(list);

	person* p = search_name(list, "albertus", "weiman");
	remove_person(list, p);

	delete_p(p);

	/* only the pointer is removed from the list
	* we have to delete person by calling delete_p*/
	print_l(list);

	p = search_date(list, create_d(10, 5, 2003));

	remove_person(list, p);
	delete_p(p);

	print_l(list);
	/*this function clears the list and deallocates all the memory including the stored data*/
	clear_l(list);
	print_l(list);

	/*deallocating the memory for the list*/
	free(list);

	return 0;
}


Vielen Dank schonmal fuer jede Hilfe!
 
Hi und Willkommen bei tutorials.de :)

Prinzipiell geht jedes C-Programm auch als C++-Programm durch, da C++ quasi eine Erweiterung der Sprache ist (vor allem Richtung Objektorientierung).
Genau genommen hast du also schon ein C++-Programm.

Was möchtest du jetzt konkret ändern?
zB. die Listenfunktionen zu einer Klasse zusammenfassen?

In dem Fall bitte auch die eigenen .h-Dateien posten (vor allem list.h, die anderen sind aber auch nicht verkehrt)

Gruß
 
Dank dir schonmal für die Hilfsbereitschaft.
Das Programm soll mit einem g++ compiler fehlerfrei compilierbar sein, wobei ich gerne folgende Punkte gerne umsetzen würde:
1. Ein/Ausgabe mittels iostream (kein printf und co. mehr)
2. Verwendung von Klassen anstatt Strukturen (Sichtbarkeiten von Attributen, Konstruktoren,
Destruktoren, Set -und Getmethoden)
3. Implementierung einer Methode für jede Klassen, die den Inhalt als String zurückliefert.
Diese Funktion soll zur Ausgabe verwendet werden.
4. Verwendung von new und delete

Ich poste mein ganzes Programm, wobei bestimmt viele auch die monströse swap Funktion kompakter schreiben könnten. Im Grunde will ich einfach die gleiche Funktionalität gegeben haben, muss also nicht 1:1 uebersetzt werden.

Ok, hier der Code:
person.h
Code:
#ifndef __PERSON_H__
#define __PERSON_H__


#include <string.h>
#include "date.h"

/* a struct to represent a person
 * */

struct person_t{
	char *firstname;
	char *lastname;
	mdate birthday;
};

typedef struct person_t person;


/* functions to compare two persons either by their first name, their last name or their date of birth
 * the function returns
 * 0 if the two persons are equal
 * 1 if p1>p2
 * -1 otherwise
 *
 * */
int pcmp_lastname( person *p1,  person*p2);

int pcmp_firstname(person *p1,  person*p2);

int pcmp_birthday( person *p1,  person*p2);

/* functions to create person, the strings fn and ln will be copied. the memory must be deallocated when the
 * is deleted
 */
person *create_pexp(char *fn, char *ln, unsigned day, unsigned month, unsigned year);

person *create_p(char *fn, char *ln, mdate d);

/* deletes the the person an deallocates the memory used to store the names*/
void delete_p(person *p);

/* prints the person's data to stdout*/
void print_p(person *p);

#endif

person.c
Code:
#include "person.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/*when we create a new person, we make a copy of the person's data*/
person *create_p(char *fn, char *ln, mdate d)
{
	person *p = (person*)calloc(1,sizeof(person));

	p->firstname = (char*)calloc((strlen(fn)+1),sizeof(char));
	strcpy(p->firstname,fn);
	p->lastname = (char*)calloc((strlen(ln)+1),sizeof(char));
	strcpy( p->lastname,ln);
	p->birthday = d;
	return p;
}

person *create_pexp(char *fn, char *ln, unsigned day, unsigned month, unsigned year)
{
	return create_p(fn,ln,create_d(day,month,year));
}

/*deletes a person completely*/
void delete_p(person *p)
{
	free(p->firstname);
	free(p->lastname);
	free(p);
}

void print_p(person *p)
{
	printf("name: %s %s\n",p->firstname,p->lastname);
	printf("birthday: ");
	print_d(p->birthday);
	printf("\n");
}

int pcmp_lastname( person *p1, person*p2)
{
	return strcmp(p1->lastname,p2->lastname);
}

int pcmp_firstname(person *p1, person*p2)
{
	return strcmp(p1->firstname,p2->firstname);
}

int pcmp_birthday( person *p1,  person*p2){
	return datecmp(&(p1->birthday),&(p2->birthday));
}

main.c
Code:
#include "date.h"
#include "person.h"
#include "list.h"
#include <stdio.h>


/*a function to create some list content*/
void testlist1(plist *list)
{
	person *p;

	p = create_pexp("albert", "weiss", 3, 6, 2003);
	add(list, p);
	p = create_pexp("klaus", "kunze", 10, 5, 2003);
	add(list, p);
	p = create_pexp("albertus", "weiman", 2, 6, 2003);
	add(list, p);
	p = create_pexp("stefan", "adam", 10, 5, 2004);
	add(list, p);

}

/*the main program whoch creates an empty list, adds some entries
 * and searches and removes some elements, finally the list will be cleared*/
int main()
{
	plist *list = create_empty_list();
	testlist1(list);
	print_l(list);
	printf("----------------------------\n");
	bubblesort(list, &pcmp_lastname);
	printf("sorted by last name\n\n");
	print_l(list);
	bubblesort(list, &pcmp_firstname);
	printf("sorted by firs tname\n\n");
	print_l(list);
	bubblesort(list, &pcmp_birthday);
	printf("sorted by date of birth\n\n");
	print_l(list);
	print_l(list);

	person* p = search_name(list, "albertus", "weiman");
	remove_person(list, p);

	delete_p(p);

	/* only the pointer is removed from the list
	* we have to delete person by calling delete_p*/
	print_l(list);

	p = search_date(list, create_d(10, 5, 2003));

	remove_person(list, p);
	delete_p(p);

	print_l(list);
	/*this function clears the list and deallocates all the memory including the stored data*/
	clear_l(list);
	print_l(list);

	/*deallocating the memory for the list*/
	free(list);

	return 0;
}

list.h
Code:
#ifndef __LIST_H__
#define __LIST_H__

#include "person.h"

/* defines a double linked list containing pointers to persons
 *
 * the next pointer of the last node and the prev pointer of the first node
 * are NULL
 *
 * */

/*struct to represent a list node*/
struct node_t{
	person *elem;
	struct node_t *next;
	struct node_t *prev;
};

typedef struct node_t pnode;

/*struct to represent a list*/
struct p_list_t{
	pnode *first;
	pnode *last;
};

typedef struct  p_list_t plist;

/*creates a new and empty list instance*/
plist *create_empty_list();

/*returns 1 if the list is empty, 0 otherwise*/
int empty(plist *list);

/*prints the list to stdout*/
void print_l(plist *list);

/*a new list element will be created and appended to the list*/
void add(plist *list, person *p);

/*sorts the list depending on the policy defined by a comparison function*/
void bubblesort(plist *list, int(*cmp)(person*,person*));

/* clears the list
 * all nodes and their content will be deleted, all the memory will be deallocated
 *
 * this may be dangerous if there is someone who references one of the stored elements
 *
 * the list itself remains and can be used to store new elements*/
void clear_l(plist *list);

/*return a pointer to the first person for which  the complete name equals
 * the given parameters*/
person *search_name(plist *list, char* firstname, char*lastname);

/*return a pointer to the first person for which  the  birth date equals
 * the given parameter*/
person *search_date(plist *list, mdate birthday);


void remove_node(plist *list, pnode *node);

/*removes the person from the list. the function will only deallocate the memory
 * for the list node.*/
void remove_person(plist* list , person* p);



void swap( plist *list, pnode *n1, pnode *n2);



#endif

list.c
Code:
#include "list.h"
#include <stdio.h>
#include <stdlib.h>

plist *create_empty_list()
{
	plist *l = (plist*) calloc(1,sizeof(plist));
	l->first = NULL;
	l->last = NULL;
	return l;
}

int empty(plist *l)
{
	if (l->first == NULL)
		return 1;
	return 0;
}

void print_l(plist *l)
{
	if (empty(l)) {
		printf("empty list\n");
		return;
	}
	printf("--->\n");
	pnode* current = l->first;
	while (current) {
		print_p(current->elem);
		current = current->next;
	}
	printf("<---\n");

}

void add(plist *l, person *p)
{
	pnode *node = (pnode*) calloc(1, sizeof(pnode));
	node->prev = NULL;
	node->next = NULL;
	node->elem = p;
	if (empty(l)) {
		l->first = node;
		l->last = node;
	} else {
		l->last->next = node;
		node->prev = l->last;
		l->last = node;
	}

}

void swap(plist *list, pnode *n1, pnode *n2)
{
#ifdef __SWAP_CONTENT__
	/* we could just swap the content of the nodes
	 * this is very easy but is problematic if it is possible that someone has direct access to the nodes, which is the case after
	 * searching for a specific name
	 *
	 person *tmp = n1->elem;
	 n1->elem=n2->elem;
	 n2->elem=tmp;
	 */
#else
	//nothing to do
	if (n1 == n2)
		return;
	//if n2 is the first element, we treat n2 as n1
	if (list->first == n2) {
		pnode *tmp = n1;
		n1 = n2;
		n2 = tmp;
	}
	//if n1 is the last element, we treat n1 as n2
	if (list->last == n1) {
		pnode *tmp = n1;
		n1 = n2;
		n2 = tmp;
	}
	//we can now assume, that n2 is not the first and n1 is not the last element

	pnode *tmp_n1_next = n1->next;
	pnode *tmp_n1_prev = n1->prev;
	pnode *tmp_n2_prev = n2->prev;
	pnode *tmp_n2_next = n2->next;

	n1->next = n2->next;
	n2->prev = n1->prev;
	if (list->first == n1) {
		list->first = n2;

		if (list->last == n2) {
			n1->prev = n2;
			n2->next = n1;
			list->last = n1;
			return;
		}
	} else {
		tmp_n1_prev->next = n2;
	}

	if (list->last == n2) {
		list->last = n1;
	} else {
		tmp_n2_next->prev = n1;
	}

	//special case
	if (tmp_n1_next == n2) {
		n1->prev = n2;
		n2->next = n1;
	} else {
		n1->prev = tmp_n2_prev;
		n2->next = tmp_n1_next;
	}
#endif
}

void bubblesort(plist *list, int(*cmp)(person*, person*))
{
	if (empty(list))
		return;
	unsigned changed = 1;
	while (changed) {
		changed = 0;
		pnode *current = list->first;
		while (current->next) {
			if (cmp(current->elem, current->next->elem) > 0) {
				swap(list, current, current->next);

				changed = 1;
			}
			if (current->next)
				current = current->next;

		}

	}
	return;
}

person *search_name(plist *list, char* firstname, char*lastname)
{
	pnode *current = list->first;
	while (current) {

		if (strcmp(current->elem->firstname, firstname) == 0 && strcmp(
				current->elem->lastname, lastname) == 0) {
			return current->elem;
		}
		current = current->next;
	}
	return NULL;

}

person *search_date(plist *list, mdate birthday)
{
	pnode *current = list->first;
	while (current) {

		if (datecmp(&(current->elem->birthday), &birthday) == 0) {
			return current->elem;
		}
		current = current->next;
	}
	return NULL;
}

pnode *search_person(plist *list, person *p)
{
	pnode *current = list->first;
	while (current) {

		if (current->elem == p) {
			return current;
		}
		current = current->next;
	}
	return NULL;
}

void remove_node(plist *list, pnode *node)
{
	if (node == NULL || list == NULL)
		return;

	if (list->first == node && list->last == node) {
		//just one element
		list->first = NULL;
		list->last = NULL;
		free(node);
		return;
	}

	if (list->first == node) {
		list->first = node->next;
		list->first->prev = NULL;
		node->next = NULL;
		free(node);
		return;
	}

	if (list->last == node) {
		list->last = node->prev;
		list->last->next = NULL;
		node->prev = NULL;
		free(node);
		return;
	}
	//ordinary case
	node->prev->next = node->next;
	node->next->prev = node->prev;
	node->next = NULL;
	node->prev = NULL;

	//reallocating the memory of node, elem remains
	free(node);
}

void remove_person(plist* l, person* p)
{
	remove_node(l, search_person(l, p));
}

void clear_l(plist *list)
{
	pnode *current = list->first;
	while(current){
		pnode *tmp=current;
		current=current->next;
		//we delete also the content
		delete_p(tmp->elem);
		free(tmp);
	}
	list->first=NULL;
	list->last=NULL;
}

date.h
Code:
#ifndef __DATE_H__
#define __DATE_H__

/* a struct to represent a date! of course there is an existing implementation in the C standard :)
 * */
struct date_{
	unsigned year;
	unsigned month;
	unsigned day;
} ;

typedef struct date_ mdate;

/* creates a date, currently their is no check, whether the given date is valid; 31.02.2000 would make no sense :)
 * */
mdate create_d(unsigned day, unsigned month, unsigned year);

mdate copy_d(mdate d);

/*allows to compare two dates, the function returns
 * 0 if the dates are equal
 * 1 if d1 > d2
 * -1 otherwise
 * */
int datecmp(const mdate *d1, const mdate *d2);

/*prints the date to stdout day.month.year*/
void print_d(mdate d);

#endif

date.c
Code:
#include <stdio.h>
#include <stdlib.h>


#include "date.h"

mdate create_d(unsigned day, unsigned month, unsigned year)
{
	//mdate* date =   (mdate*)malloc(sizeof(mdate));
	mdate date;
	date.day=day;
	date.month=month;
	date.year=year;
	return date;
}

mdate copy_d(mdate d)
{
	return create_d(d.day,d.month,d.year);
}

int datecmp( const mdate *d1, const mdate *d2)
{
	if (d1->year < d2->year)
			return -1;
		if (d1->year > d2->year)
			return 1;
		//year is equal
		if (d1->month < d2->month)
			return -1;
		if (d1->month > d2->month)
			return 1;
		//year and month are equal
		if (d1->day < d2->day)
			return -1;

		if (d1->day > d2->day)
					return 1;
		//the dates are equal
		return 0;
}



void print_d(mdate d)
{
	printf("%u.%u.%u",d.day,d.month,d.year);
}
 
Gut, also
-cout/cin statt printf/scanf...
-und Klassen, mit allem was dazugehört.

Die printf... durch cout... zu ersetzen schaffst du bestimmt selber.
Beispiel:
C++:
    printf("111");
    cout << "111";

    printf("\n");
    cout << endl;

    printf("111\n");
    cout << "111" << endl;

    int i = 4;
    printf("%d", i);
    cout << i;
usw...
Beispiele gibts genug im Internet.

Zu den Klassen:
Weils relativ einfach ist, beginne ich einmal mit dem Datum

Es soll also eine Klasse date gemacht werden, die folgendes braucht:
-Drei Variablen für Tag, Monat und Jahr, auf die von außen kein Zugriff möglich sien soll
-Für Tag/Monat/Jahr jeweils eine Get- und eine Set-Methode zum Abfragen und Ändern des Wertes
-Eine Ausgabemethode (vom Sinn her das jetzige print_d)
-Einen Konstruktor, mit dem man eine Instanz erzeugt und gleich auch Tag/Monat/Jahr festlegen kann (jetzt create_d)
-Zum Konstruktor gehört auch immer ein Destruktor (der am Schluss zum Aufräumen da ist, hier aber nichts zu tun hat und leer sein kann)
-Anstellen von copy_d kann man den Operator = überladen, damit man x=y; mit date-Variablen verwenden kann.
-Dazu eventuell noch einen Konstruktor, der Statt Tag/Monat/Jahr ein fertiges Date nimmt und kopiert (sog. Copyconstructor)
Der Unterschied von Copyc. und = ist, dass der Konstruktor die Variable erst erstellt und bei = schon eine vorhanden ist, die nur neue Werte bekommt.
-Und anstelle von datecmp kann man == und != für date möglich machen, damit man es wie zB. int vergleichen kann.

Die date.h bekommt dann das "Gerüst" der Klasse, das mit den obigen Punkten ca. so ausschauen kann:
C++:
#ifndef __DATE_H__
#define __DATE_H__
class date
{
protected:
    int day, mon, year;
public:
    date(int, int, int); //day, moth, year
    date(date &); //Werte von anderem Date übernehmen
    ~date();//Destruktor

    date &operator=(date &);
    int operator==(date &);
    int operator!=(date &);

    int get_day();
    int get_moth();
    int get_year();

    void set_day(int);
    void set_month(int);
    void set_year(int);

    void print();
};
#endif

In der date.cpp (nicht mehr date.c) kommt dann wie gewohnt der tatsächliche Funktionsinhalt rein.
Allerdings ist die Schreibweise des Namens etwas anders, er bekommt noch vorne den Klassennamen und "::" dazugehängt.
Beispiel für get_day (das ja nur day returnen muss) und set_day:
C++:
int date::get_day()
{
    return day;
}

void date::set_day(int newday)
{
    day = newday;
}
Mit get/set-month und -year geht es gleich, damit wären die Getter/Setter schon einmal erledigt.

In print gibts du einfach die drei Variablen aus (wie bei print_d mit . getrennt).
C++:
void date::print()
{
    //Ausgabe...
}

Jetzt zu == und !=
Die Funktionen/Methoden/Operatoren operator== und operator!= sorgen dafür, dass zB so ein Code funktioniert:
C++:
date a;
date b;
...
if(a == b)
...
Wenn die vorhanden sind, kann man date also wie int/float/... vergleichen.
Das ersetzt damit datecmp.

operator== muss dabei 0 zurückgeben, wenn die dates nicht gleich sind, sonst was anderes als 0.
Bei != ist es umgekehrt
Verglichen werden dabei die eigenen Variablen (day/mon/year) und die des übergebenen dates.
C++:
int date::operator==(date &d)
{
    if(day == d.day && mon == d.mon && year == d.year) return 1;
    else return 0;
}

Fragen bis hier her?

Gruß
 
Zuletzt bearbeitet:
Hi.
Fragen bis hier her?
Nein. ;) Einige Anmerkungen:

Methoden die den Zustand der Instanz nicht ändern (wie z.B. alle getter) sollten grundsätzlich const sein.

Methodenparameter die innerhalb der Methode nicht geändert werden, sollten grundsätzlich als konstante Referenz übergeben werden.

Warum sollte ein Vergleichsoperator int zurückgeben? Er sollte bool zurückgeben:
C++:
bool date::operator==(const date& d) const {
  return (day == d.day && mon == d.mon && year == d.year);
}
Gruß
 
Zurück