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

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

Δημοσ.

Καλησπέρα...έχω μια απλή ερώτηση.

Πριν αρχίσουμε ένα πολύ απλό πρόγραμμα στη c χρησιμοποιούμε στην αρχή #include <stdio.h> και μετά τις εντολές που θέλουμε .

Θα ήθελα να μάθω λοιπόν...αν με αυτό μπορώ να χρησιμοποιήσω στο πρόγραμμα τύπο από τη c++ όπως το setw χωρίς να προσθέσω κάτι άλλο στην αρχή ...πχ #include <iostream.h> , #include <conio.h>, #include <iomanip.h> . Θα μπορούσα απλά στο παρακάτω κομμάτι(είναι και μισό :P ) αντί για όλα αυτά να βάλω stdio.h και να τελειώσω ;

 

#include <iostream.h>
#include <conio.h>
#include <iomanip.h>
void main()
{
char xxx;
cout<<setw(30)<<"To open a file press"<<" F"<<endl;
cout<<setw(30)<<"To start a new file press"<<" N"<<endl;
cout<<setw(30)<<"To save a file press"<<" S"<<endl;
cout<<setw(30)<<"To close a file press"<<" C"<<endl;
cout<<"Select an option";
cin>>xxx;

 

  • Moderators
Δημοσ.

Η C και η C++ είναι διαφορετικές γλώσσες. Αν θες κάτι που υπάρχει μόνο στη C++ πρέπει να χρησιμοποιήσεις C++.

  • Like 1
Δημοσ.

Και να τα κάνεις compile με C compiler; Αδύνατο.

 

Επίσης, δεν υπάρχουν τα iostream.h και τα λοιπά που δήλωσες.

 

Τέλος, ένα πολύ απλό πρόγραμμα C δεν περιέχει καμμία δήλωση για εισαγωγή βιβλιοθήκης:

int main(void)
{
    return 0;
}
Δημοσ.

Επειδή έχω μπερδευτεί...ουσιαστικά δεν στέκει το ένα με το άλλο με λίγα λόγια....

Και αν ας πούμε θέλω να εμφανίσω μια λέξη 10 θέσεις πιο μέσα...που στη c++ έχω την εντολή setw....στη C πως θα το κάνω αυτό ;

Δημοσ.

Θα μπορούσα απλά στο παρακάτω κομμάτι(είναι και μισό :P ) αντί για όλα αυτά να βάλω stdio.h και να τελειώσω ;

 

Θα μπορούσες να κάνεις ένα δικό σου .h που κάνει #include την Άρτα και τα Γιάννενα και μετά να κάνεις απλά #include το δικό σου.

 

Υπόψιν αυτό θεωρείται ψιλοκακή πρακτική και αν δε συνοδεύεται από τη χρήση precompiled headers (ένα feature που κάθε compiler υποστηρίζει διαφορετικά) θα είναι και πιο αργό απ' ότι θα ήταν αλλιώς στο compilation.

Δημοσ.

Και αν ας πούμε θέλω να εμφανίσω μια λέξη 10 θέσεις πιο μέσα...που στη c++ έχω την εντολή setw....στη C πως θα το κάνω αυτό ;

#include <stdio.h>

int main(void)
{
	printf("%15s", "hello");

	return 0;
}
  • Like 1
Δημοσ.

Ειπα να μην ανοιξω αλλο thread, οποτε συγχωρεστε με εκ των προτερων για το μικρο αυτο off topic:

ρε παιδια, στη C, ποια συναρτηση συνισταται, για εισαγωγη χαρακτηρων σε πινακα που βρισκεται μεσα σε μια δομη:

πχ εχουμε μια δομη τυπου στοιχειων, 15 μαθητων.
μεσα περιεχεται

  1. το ονομα σε πινακα char μεχρι 19 χαρακτηρες (μαζι με τον \0)
  2. ηλικια, απλα εναν ακεραιος τυπου int.

/*δηλωση δομης*/

struct stoixeia{

 

         char onoma[20];

         int     ilikia;

} mathites[15];

 

θελω τωρα να μου βγαζει καθε φορα να παταω το ονομα και την ηλικια του καθε μαθητη..ας πουμε οτι Ν=15..

 

/*εισαγωγη στοιχειων*/
for(i=0;i<=N;i++)

{

    printf("mathitis" );

  •     scanf("%c",mathites.onoma);  ????

     ή

  •     gets(mathites.onoma); ???

μετα για την ηλικια, ειμαι οκ με την scanf() ή θελει gets() ή κατι αλλο?

}

μετα θελω να τυπωνει τα ονοματα ολων των μαθητων, αλλα αυτο ειναι αλλου παπα ευαγγελιο.

υ.γ πολυ μπακαλικα γραμμενος, απλα ηθελα να προβαλω τη συγκεκριμενη ερωτηση χωρις πολλα πολλα.

edit: Ενα προβλημα που μολις ελυσα ηταν το λαθος που εκανα, αντι για %s εβαζα %c.

edit2 : Οκ, βρηκα τη λυση μου. ειναι καλυτερα να βαλω την scanf για να δινω συνεχομενα ονοματα.
η gets μου κανει κατι περιεργα.

Δημοσ.

edit2 : Οκ, βρηκα τη λυση μου. ειναι καλυτερα να βαλω την scanf για να δινω συνεχομενα ονοματα.

η gets μου κανει κατι περιεργα.

Η gets δεν κάνει τίποτα το περίεργο. Αν διαβάσεις το man page θα δεις πως συμπεριφέρεται απολύτως λογικά.

 

Επίσης θα διαβάσεις πως καλό είναι να αποφεύγεται η χρήση της.

 

 

BUGS

       Never use gets().  Because it is impossible to tell without knowing the
       data in advance how many  characters  gets()  will  read,  and  because
       gets() will continue to store characters past the end of the buffer, it
       is extremely dangerous to use.  It has  been  used  to  break  computer
       security.  Use fgets() instead.

 

 

 

..και για το λόγο που δεν πρέπει να χρησιμοποιούμε gets, δεν πρέπει να χρησιμοποιείς και τη scanf με τον τρόπο που το κάνεις.

 

Πρέπει να περιορίσεις το input του χρήστη στο μέγεθος του buffer, πλην 1, λόγω του nul. Αυτό το κάνεις, συγκεκριμένα στην περίπτωσή σου, έτσι:

scanf("%19s", mathites[i].onoma);
  • Like 5
Δημοσ.

Ένα λεπτο γιατι τα μπουρδούκλωσες. Καταρχην η μεταβλητή mathites[15] ειναι ένας πινακας που έχει στοιχεια 15 δομές που καθεμια απο αυτες τις δομές έχει 2 μέλη ένα ονομα και μια ηλικια. Στο ονομα αποθηκεύεις στοιχεια σε έναν πινακα απο χαρακτηρες αρα θες %s και οχι %c.Xρησιμοποιησε απευθειεας την fgets.

Δημοσ.

 

 
#include <stdio.h>
#define NUM_OF_STUD 3
struct stoixeia{
         char onoma[20];
         int ilikia;

} mathites[NUM_OF_STUD];

int main()
{
    int i;
    char temp[5]={'\0'};

    for(i=0; i<NUM_OF_STUD; i++) {
        printf("Give the name: ");
        fgets( mathites[i].onoma , 20 , stdin);
        printf("Give the age: ");
        fgets( temp , 5 , stdin);
        mathites[i].ilikia = atoi(temp);

    }

    for(i=0; i<NUM_OF_STUD; i++)
        printf("\nStudent %d\nName:%s Age:%d" , i , mathites[i].onoma , mathites[i].ilikia);

    return 0;
}

 

Αποθηκεύω την ηλικια σε έναν προχειρο πίνακα απο χαρακτηρες και μετα την μετατρέπω σε ακέραιο με την συνάρτηση atoi. Αν χρησιμοποιήσεις scanf μεσα στο βροχο θα έχεις το κλασσικο θέμα με τον χαρακτηρα ΕΝΤΕΡ που θα περνάει σε επομενη εισοδο αντι για ονομα.

  • Like 1
Δημοσ.

Υπόψιν πως μετά από μία fgets πρέπει να κάνεις strip το newline που μπορεί να μπήκε αν ο χρήστης έδωσε input μικρότερο του μεγέθους που περιμέναμε πλην 2.

 

Οπότε κάνεις κάτι τέτοιο:

size_t len = strlen(buf);
if (len > 0 && buf[len-1] == '\n') {
    buf[len-1] = '\0';
}

Υπάρχει και το one-liner

buf[strcspn(buf, "\n")] = '\0';

που είναι πιο αργό, αλλά πιο elegant.

 

 

 

Το one-liner με την strlen πρέπει να αποφεύγεται:

 

buf[strlen(buf) - 1] = '\0';

 

καθώς υπάρχει και η περίπτωση να δοθεί κενό string. Άρα θα γράψεις στη θέση buf[-1].

 

 

  • Like 4
Δημοσ.

Εντάξει εμενα προσωπικα δεν με ενοχλει αν ο χωρος ειναι 10 χαρακτήρες εγω δώσω 5 και πάρει μαζι και τον εντερ. Αν ο χρηστης δώσει 10 χαρακτηρες μαζι με το enter τοτε τον τελευταιο τον βγάζει η fgets και βαζει τον '\0' ωστε ολα να δουλευουν οπως πρέπει συμφωνα με τις συμβάσεις που έχουν συμφωνησει αλλοι προγραμματιστες που έφτιαχναν τα συστηματα που χρησιμοποιούμε. ;)

 

Οποιος άλλος δεν θελει ας τον βγάλει με τον τροπο που έδειξες. Ωραιος ειναι και εγω τον εχω χρησιμοποιήσει σε δικές μου συναρτησεις.

 

Την strlen μπορεις να την χρησιμοποιήσεις με τον τροπο που λές αν έχεις κανει πιο πριν έναν έλεγχο για κενη συμβολοσειρα... ουτως ή αλλως αμα ο χρηστης δωσει κενο θα πρέπει να του εμφανιζει ενα μηνυμα λάθους οποτε και ετσι να την αφησεις οταν θα έχει περάσει απο τον ελεγχο εγγυημένα δεν θα δώσει [-1] και αρα UB λογω buffer underflow.

 

Βάλε την εισοδο σε εναν do-while και μην τον κοψεις οσο ο χρηστης δεν δινει συμβολοσειρά που ειναι τουλαχιστον ενος χαρακτηρα.

  • Like 1

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

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

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

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

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

Σύνδεση

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

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