Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ.

==========================================

========== Άνοιγμα και διαχείρηση αρχείων ==========

==========================================

File *p

αφού ανοίξω το αρχείο με fopen

πως μπορώ να δημιουργήσω μια συμβολοσειρα με μέγεθος μια γραμμή του αρχείου(χωρίς να ξέρω το πλήθος των στοιχείων).

 

 

==========================================

============== Δομές & Συναρτήσεις =============

==========================================

Ας πούμε ότι έχουμε την δομή

>    typedef struct Line {
          int total;
          char *newline;
          }Line;

Πώς την παιρνώ ως όρισμα σε μία συνάρτηση ώστε να μεταβάλω τα total,*newline σε αυτήν.

Επίσης πως μπορώ να βάλω την συναρτήση μου να επιστρέφει την ίδια την δομή

 

 

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

Αυτα για τώρα.Περισσότερες απορίες στο μέλλον!! :-D

Ευχαριστώ για τον χρόνο σας :P

Δημοσ.

Τι εννοεις "να δημιουργήσω μια συμβολοσειρα με μέγεθος μια γραμμή του αρχείου", θες να γραχεις στο αρχει ή να διαβασεις απο αυτο; Τι;

 

==========================================

============== Δομές & Συναρτήσεις =============

==========================================

Ας πούμε ότι έχουμε την δομή

>    
typedef struct Line {
   int total;
   char *newline;
}Line;

Πώς την παιρνώ ως όρισμα σε μία συνάρτηση ώστε να μεταβάλω τα total,*newline σε αυτήν.

Επίσης πως μπορώ να βάλω την συναρτήση μου να επιστρέφει την ίδια την δομή

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

 

Για να αλλαξουμε την τιμη μια μεταβλητης η οποια ειναι οροσματα μιας συναρτησης και η τιμη να "μινει" και μετα το περας της συναρτησης πρεπει να δινουμε ως ορισμα την διεθυνση της μεταβλητης.

Παραδειγμα:

 

>
#include<stdio.h>

void allazw_timi(int i)
{
i = 5;
printf("eimai stin allazw_timi(), i = %d\n", i);
}

void allazw_dieuthinsi(int *i)
{
*i = 5;
printf("eimai stin allazw_dieuthinsi(), i = %d\n", *i);
}

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

int dieuthinsi, timi;

timi = dieuthinsi = 0;

allazw_timi(timi);

allazw_dieuthinsi(&dieuthinsi);

printf("eimai sti main(), timi = %d | dieuthinsi = %d\n", timi, dieuthinsi);

return 0;
}

 

Αν το τρεξεις θα δεις:

 

eimai stin allazw_timi(), i = 5

eimai stin allazw_dieuthinsi(), i = 5

eimai sti main(), timi = 0 | dieuthinsi = 5

 

 

 

Προσοχη δωσε οτι οταν θελω να περασω διευθυνση μεταβλητης χρησιμοποιω το "&", ενω μεσα στην συναρτυση που πηρε ορισμα διευθυνση μεταβλητη, την τιμη την αλλαζω χρησιμοποιωνταςτο "*" πριν το ονομα της μετηαβλητης. Στη περιπτωση σου ομως επειδη η μεταβλητη ειναι struct, αντι για "*(Line.total) = X;" μπορεις να χρησιμοποιεις το "Line->total = X;"

Δημοσ. (επεξεργασμένο)

 

 

==========================================

========== Άνοιγμα και διαχείρηση αρχείων ==========

==========================================

 

 

File *p

αφού ανοίξω το αρχείο με fopen

πως μπορώ να δημιουργήσω μια συμβολοσειρα με μέγεθος μια γραμμή του αρχείου(χωρίς να ξέρω το πλήθος των στοιχείων).

Με malloc()/calloc() και κατόπιν realloc() όποτε χρειάζεται.

 

 

 

 

==========================================

============== Δομές & Συναρτήσεις =============

==========================================

Ας πούμε ότι έχουμε την δομή

>    typedef struct Line {
  		int total;
  		char *newline;
  		}Line;

 

 

Πώς την παιρνώ ως όρισμα σε μία συνάρτηση ώστε να μεταβάλω τα total,*newline σε αυτήν.

Κανονικά, όπως κάθε άλλη μεταβλητή...

 

 

 

>
#include <string.h>
#include <stdlib.h>

#define MAXLINESIZE  (80+1)
#define MIN(x,y)  ( (x) < (y) ? (x) : (y) )

typedef struct Line {
  int total;
  char *newline;
}Line;

/* --------------------------------------- */
void line_set( Line *line, const char *text )
{
 if ( !line || !text || !line.newline )
return;

 strncpy( line->newline, text, MAXLINESIZE-1 );
 line->total = MIN( MAXLINESIZE, strlen( text ) );

 return;
}

/* --------------------------------------- */
int main( void )
{
 Line line = { 0, NULL };

 line.newline = calloc( MAXLINESIZE, sizeof(char) );
 if ( !line.newline )
exit( EXIT_FAILURE );

 line_set( &line, "sample text" );

 free( line.newline );
 exit( EXIT_SUCCESS );
}

 

 

 

Επίσης πως μπορώ να βάλω την συναρτήση μου να επιστρέφει την ίδια την δομή

Και πάλι κανονικά, όπως κάθε άλλη μεταβλητή...

 

 

 

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

typedef struct Point {
 int x,y;
} Point;

/* --------------------------------------- */
Point point_set( const int x, const int y )
{
Point p;

p.x = x;
p.y = y;

return p;
}
/* --------------------------------------- */
int main( void )
{
Point point = { 0, 0 };

point = point_set( 3, 9 );
printf( "point.x = %d, point.y = %d\n", point.x, point.y );

exit( EXIT_SUCCESS );
}

 

 

 

αλλά όταν η δομή περιέχει μέσα της δείκτες ή είναι πολύ μεγάλη, τότε είναι πολύ πιο εύκολο και κυρίως πολύ πιο efficient να βάλεις τη συνάρτηση να επιστρέφει δείκτη στη δομή...

 

 

 

>
#include <string.h>
#include <stdlib.h>

#define MAXLINESIZE  (80+1)
#define MIN(x,y)  ( (x) < (y) ? (x) : (y) )

typedef struct Line {
  int total;
  char *newline;
}Line;

/* --------------------------------------- */
Line *line_set( Line *line, const char *text )
{
 if ( !line || !text )
return NULL;

 strncpy( line->newline, text, MAXLINESIZE-1 );
 line->total = MIN( MAXLINESIZE, strlen( text ) );

 return line;
}

/* --------------------------------------- */
int main( void )
{
 Line line1 = { 0, NULL }, *line2 = NULL;

 line1.newline = calloc( MAXLINESIZE, sizeof(char) );
 if ( !line1.newline )
exit( EXIT_FAILURE );

 line2 = line_set( &line1, "sample text" );

 free( line1.newline );

 exit( EXIT_SUCCESS );
}

 

 

Επεξ/σία από migf1
Δημοσ.

Με malloc()/calloc() και κατόπιν realloc() όποτε χρειάζεται.

Σου έγραψα ως μικρό παράδειγμα ένα πρόγραμμα που τυπώνει τον πηγαίο κώδικα του εαυτού του, γραμμή προς γραμμή, με το πλήθος χαρακτήρων της καθεμιάς τους στην αρχή (εξαιρουμένου του '\n').

 

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

#define MAXFNAME	(256+1)
#define LNCHUNK		(80+1)

typedef struct Line {
char *data;
int  len;
} Line;

/* -------------------------------------------------------
* Line *line_fread( Line *line, FILE **fp );
*
* 	Create arbitrary size line->data by reading file fp, until either '\n' or EOF.
* 	Return a pointer to line, or NULL on error.
*
*	NOTES:	1) fp is passed by reference, so it keeps the current file position.
*		2) The caller is responsible for freeing the created line->data 
* -------------------------------------------------------
*/
Line *line_fread( Line *line, FILE **fp )
{
int i = 0, c = '\0', chunksize = LNCHUNK;
char *trial = NULL;

if ( !line || !fp || !*fp )				/* sanity checks 	*/
	return NULL;

line->data = calloc( chunksize, sizeof(char) );		/* initial allocation*/
line->len = 0;						/* init length   	*/

if ( !line->data )
	return NULL;

/* read line data from *fp into line->data, realloc the latter when necessary*/
for (i=0, c=fgetc(*fp); c != EOF && c != '\n'; c=fgetc(*fp), i++)
{
	if ( i != 0 && i % (LNCHUNK-1) == 0 )		/* need for realloc  */
	{
		chunksize += LNCHUNK;
		trial = realloc(line->data, chunksize); /* do it 			*/
		if ( !trial ) {				/* it failed 		*/
			free( line->data );
			return NULL;
		}
		line->data = trial;			/* it succeeded  	*/
	}
	/* updtate the line structure */
	line->data[i] = c;
	line->len++;
}

line->data[i] = '\0';

return line;
}

/* -------------------------------------------------------
* char *c_from_exe( char *cname, const char *exename );
*
* 	Given an executable filename (e.g: "test.exe" or "a.out" or even "test")
*	cname becomes "test.c".
*	Return cname, or NULL on error.
*
*	NOTES:	Both cname and exename must be already defined c-strings.
* -------------------------------------------------------
*/
char *c_from_exe( char *cname, const char *exename )
{
char *cp = NULL;

if ( !cname || !exename )
	return NULL;

strncpy( cname, exename, MAXFNAME-1 );

cp = (char *)(cname + strlen(cname) - 1 );
while ( *cp != '.' && cp != cname )
	cp--;

if ( cp == cname )
	strncat( cname, ".c", MAXFNAME-3-1 );
else
	strncpy( cp, ".c", MAXFNAME-3-1 );

return cname;
}

/* -------------------------------------------------------
*
* -------------------------------------------------------
*/
int main( int argc, char *argv[] )
{
char fname[ MAXFNAME ] 	= {'\0'};
Line line 		= { NULL, 0 };
FILE *fp 		= NULL;

/* */
if ( !c_from_exe(fname, argv[0]) || (fp=fopen(fname, "r")) == NULL )
{
	fputs("*** fatal error: cannot open file\n", stderr );
	exit( EXIT_FAILURE );
}

/* read file and print one line at a time */
while ( !feof(fp) )
{
	if ( !line_fread(&line, &fp) )
	{
		fputs("*** fatal error: out of memory\n", stderr);
		exit( EXIT_FAILURE );
	}
	printf( "%-4d: %s\n", line.len, line.data );
	free( line.data );
	line.data = NULL;
}

fclose( fp );

exit( EXIT_SUCCESS );
}

 

Η συνάρτηση που κάνει αυτό που ρώτησες είναι η...

 

>
Line *line_fread( Line *line, FILE **fp );

Αρχικά δεσμεύει χώρο για LNCHUNK χαρακτήρες για την κάθε γραμμή, κι αν βρεθεί γραμμή με περισσότερους, δεσμεύει άλλους τόσους, και πάει λέγοντας. Την τιμή του LNCHUNK μπορείς να το καορίσεις αλλάζοντας το σχετικό #define στην αρχή του κώδικα.

 

Άλλη μια συνηθισμένη τακτική στο reallocating είναι να προσθέτεις κάθε φορά το 1/2 ή το 1/3 του τρέχοντος δεσμευμένου χώρου όταν χρειάζεται

 

Σε κάθε περίπτωση, το realloc() δεν το κάνεις απευθείας στον κανονικό σου δείκτη, αλλά σε έναν προσωρινό. Αυτό για να μη χάσεις την επαφή με τον κανονικό σου δείκτη αν αποτύχει το realloc(). Αν σου επιστρέψει NULL και το εκχωρήσεις στον κανονικό σου δείκτη, τότε δεν μπορείς πλέον να κάνεις free() τη μνήμη στην οποία έδειχνε ο κανονικός σου δείκτης πριν την αποτυχία του realloc()... memory leak!

 

Διάβασε και την τεκμηρίωση της realloc() ... πιθανότατα θα το αναφέρει κι αυτό, ενδεχομένως και με παράδειγμα.

 

EDIT:

 

Έξοδος του παραπάνω κώδικα...

 

 

 

>
18  : #include <stdio.h>
19  : #include <stdlib.h>
19  : #include <string.h>
0   : 
24  : #define MAXFNAME	(256+1)
30  : #define LNCHUNK 		(80+1)
0   : 
21  : typedef struct Line {
12  : 	char *data;
10  : 	int  len;
7   : } Line;
0   : 
58  : /* -------------------------------------------------------
45  :  * Line *line_fread( Line *line, FILE **fp );
2   :  *
82  :  * 	Create arbitrary size line->data by reading file fp, until either '\n' or EOF.
47  :  * 	Return a pointer to line, or NULL on error.
2   :  *
78  :  *	NOTES:	1) fp is passed by reference, so it keeps the current file position.
68  :  *		2) The caller is responsible for freeing the created line->data 
58  :  * -------------------------------------------------------
3   :  */
41  : Line *line_fread( Line *line, FILE **fp )
1   : {
42  : 	int i = 0, c = '\0', chunksize = LNCHUNK;
20  : 	char *trial = NULL;
0   : 
55  : 	if ( !line || !fp || !*fp )				/* sanity checks 	*/
14  : 		return NULL;
0   : 
73  : 	line->data = calloc( chunksize, sizeof(char) );		/* initial allocation*/
44  : 	line->len = 0;						/* init length   	*/
0   : 
19  : 	if ( !line->data )
14  : 		return NULL;
0   : 
80  : 	/* read line data from *fp into line->data, realloc the latter when necessary*/
66  : 	for (i=0, c=fgetc(*fp); c != EOF && c != '\n'; c=fgetc(*fp), i++)
2   : 	{
64  : 		if ( i != 0 && i % (LNCHUNK-1) == 0 )		/* need for realloc  */
3   : 		{
24  : 			chunksize += LNCHUNK;
66  : 			trial = realloc(line->data, chunksize);	/* do it     		*/
45  : 			if ( !trial ) {				/* it failed 		*/
23  : 				free( line->data );
16  : 				return NULL;
4   : 			}
48  : 			line->data = trial;			/* it succeeded  	*/
3   : 		}
34  : 		/* updtate the line structure */
20  : 		line->data[i] = c;
14  : 		line->len++;
2   : 	}
0   : 
22  : 	line->data[i] = '\0';
0   : 
13  : 	return line;
1   : }
0   : 
0   : 
58  : /* -------------------------------------------------------
2   :  *
58  :  * -------------------------------------------------------
3   :  */
25  : char skipline( FILE *fp )
1   : {
15  : 	char c = '\0';
0   : 
46  : 	while ( (c = fgetc(fp)) != '\n' && c != EOF )
20  : 		;	/* empty body */
0   : 
15  : /*	return c; */
33  : 	return c == EOF ? c : fgetc(fp);
1   : }
0   : 
58  : /* -------------------------------------------------------
56  :  * char *c_from_exe( char *cname, const char *exename );
2   :  *
76  :  * 	Given an executable filename (e.g: "test.exe" or "a.out" or even "test")
26  :  *	cname becomes "test.c".
34  :  *	Return cname, or NULL on error.
2   :  *
67  :  *	NOTES:	Both cname and exename must be already defined c-strings.
58  :  * -------------------------------------------------------
3   :  */
52  : char *c_from_exe( char *cname, const char *exename )
1   : {
17  : 	char *cp = NULL;
0   : 
26  : 	if ( !cname || !exename )
14  : 		return NULL;
0   : 
39  : 	strncpy( cname, exename, MAXFNAME-1 );
0   : 
43  : 	cp = (char *)(cname + strlen(cname) - 1 );
36  : 	while ( *cp != '.' && cp != cname )
7   : 		cp--;
0   : 
19  : 	if ( cp == cname )
39  : 		strncat( cname, ".c", MAXFNAME-3-1 );
5   : 	else
36  : 		strncpy( cp, ".c", MAXFNAME-3-1 );
0   : 
14  : 	return cname;
1   : }
0   : 
58  : /* -------------------------------------------------------
2   :  *
58  :  * -------------------------------------------------------
3   :  */
34  : int main( int argc, char *argv[] )
1   : {
34  : 	char fname[ MAXFNAME ] 	= {'\0'};
27  : 	Line line 		= { NULL, 0 };
19  : 	FILE *fp 		= NULL;
0   : 
6   : 	/* */
69  : 	if ( !c_from_exe(fname, argv[0]) || (fp=fopen(fname, "r")) == NULL )
2   : 	{
56  : 		fputs("*** fatal error: cannot open file\n", stderr );
23  : 		exit( EXIT_FAILURE );
2   : 	}
0   : 
45  : 	/* read file and print one line at a time */
20  : 	while ( !feof(fp) )
2   : 	{
32  : 		if ( !line_fread(&line, &fp) )
3   : 		{
53  : 			fputs("*** fatal error: out of memory\n", stderr);
24  : 			exit( EXIT_FAILURE );
3   : 		}
46  : 		printf( "%-4d: %s\n", line.len, line.data );
20  : 		free( line.data );
19  : 		line.data = NULL;
2   : 	}
0   : 
14  : 	fclose( fp );
0   : 
0   : 
17  : 	system("pause");
22  : 	exit( EXIT_SUCCESS );
1   : }
0   : 

 

 

 

EDIT2:

Είχα ξεχάσει να μηδενίζω τον τελικό χαρακτήρα της γραμμής (το διόρθωσα).

  • 3 εβδομάδες αργότερα...
Δημοσ.

Παιδεια καλησπερα εχω κατεβασει το codeblocks έχω τον κλασσικο κωδικα Hello world αλλα δεν ξερω πως να θέσω το προγραμμα σε λειτουργια χρειαζομαι καποιο linker πρωτου βάλω τον κώδικα στον μεταγλωτιστη?

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...