@Ilias (αλλά όχι μόνο): Δεν πρόκειται να το βρεις σχεδόν σε κανένα βιβλίο αυτό, μιας και όλα χρησιμοποιούν την
scanf() για την ανάγνωση της κύριας εισόδου, αλλά σου συνιστώ ανεπιφύλακτα να την καταργήσεις από τώρα που είναι νωρίς, πριν σου γίνει συνήθεια. Υπάρχουν ιδιαιτερότητες στην ανάγνωση της κύριας εισόδου με τις στάνταρ συναρτήσεις της γλώσσας, λόγω του
Line Buffering. Κανείς δεν τη χρησιμοποιεί σε πραγματικά προγράμματα.
Προς το παρόν (μέχρι να φτάσεις σε σημείο να μπορείς να κατανοήσεις τις λεπτομέρειες) αποστήθισε τον παρακάτω τρόπο ανάγνωσης από την κύρια είσοδο, ως αντικατάστατο της
scanf():
-
Μορφοποιημένος Κώδικας: Επιλογή όλων
-
#include <stdio.h>
#define MAXINPUT (1024+1)
int main( void )
{
char input[ MAXINPUT ] = {'\0'};
...
/* όταν έρθει η ώρα για ανάγνωση της εισόδου, τότε αντί για scanf() χρησιμοποίησε το παρακάτω... */
fgets( input, MAXINPUT, stdin );
sscanf( input, /* βάλε εδώ κανονικά ότι θα έβαζες και στην scanf() */ );
...
return 0;
}
Αυτό που κάνει ο παραπάνω κώδικας είναι να διαβάζει μονοκόμματα μέσω της
fgets() ότι έχει γράψει ο χρήστης στην κύρια είσοδο μέχρι να πατήσει ENTER. Τα διαβασμένα τα αποθηκεύει μέσα στο string
input, το οποίο έχει οριστεί με μέγιστη χωρητικότητα (1024+1) χαρακτήρες (λόγω της σταθεράς MAXINPUT στην αρχή του κώδικα).
Στην συντριπτική πλειοψηφία των πλατφορμών, το μέγιστο πλήθος χαρακτήρων που μπορούν να πληκτρολογηθούν στη γραμμή εντολών μέχρι να πατηθεί ENTER είναι πολύ μικρότερο από 1024 χαρακτήρες, οπότε είμαστε καλυμμένοι ότι δεν πρόκειται να μας ξεφύγει κανένας χαρακτήρας (π.χ. στα Windows το όριο είναι 256 χαρακτήρες).
Είναι σημαντικό η MAXINPUT να είναι ορισμένη με τιμή ίση ή μεγαλύτερη από το μέγιστο πλήθος χαρακτήρων που μπορεί να δεχτεί η γραμμή εντολών!Η
sscanf() λειτουργεί πανομοιότυπα με την
scanf() με μόνη εξαίρεση την προσθήκη ενός έξτρα ορίσματος στην αρχή της, το string μέσα από το οποίο καλείται να διαβάσει τις μεταβλητές που τις έχουμε πει (μέσα από το
input δηλαδή, στο παραπάνω παράδειγμα). Η
scanf() τις διαβάζει απευθείας από την κύρια είσοδο (btw, στη C η κύρια είσοδος είναι ένα buffered file stream, με την ονομασία:
stdin ... οπότε γίνεται ελπίζω πιο σαφής η σύνταξη της
fgets() 
).
Άρα λοιπόν ο παραπάνω κώδικας, διαβάζει πρώτα με την
fgets() ολόκληρη την γραμμή εισόδου μέσα σε ένα string ονόματι
input, το οποίο το περνάει κατόπιν ως 1o όρισμα στην
sscanf() προκειμένου να αντλήσει μέσα από αυτό τις τιμές που επιθυμεί

Προσπάθησε να το κάνεις συνήθεια από τώρα που είναι νωρίς, όποτε κι όπου βλέπεις τη scanf()!
Οπότε η άσκηση με τα 16 νούμερα γίνεται πλέον έτσι...
-
Μορφοποιημένος Κώδικας: Επιλογή όλων
-
#include <stdio.h>
#define MAXINPUT (1024+1)
/* ------------------------ */
int main( void )
{
char input[ MAXINPUT ] = {'\0'};
int n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16;
printf( "Enter the integers from 1 to 16 in any order:\n" );
fgets( input, MAXINPUT, stdin );
sscanf( "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
&n1, &n2, &n3, &n4, &n5, &n6, &n7, &n8,
&n9, &n10, &n11, &n12, &n13, &n14, &n15, &n16
);
/* display them in tabular format */
printf( "\n%2d %2d %2d %2d\n", n1, n2, n3, n4 );
printf( "%2d %2d %2d %2d\n", n5, n6, n7, n8 );
printf( "%2d %2d %2d %2d\n", n9, n10, n11, n12 );
printf( "%2d %2d %2d %2d\n\n", n13, n14, n15, n16 );
printf( "Row sums: %d %d %d %d\n",
n1 + n2 + n3 + n4,
n5 + n6 + n7 + n8,
n9 + n10 + n11 + n12,
n13 + n14 + n15 + n16
);
printf( "Column sums: %d %d %d %d\n",
n1 + n5 + n9 + n13,
n2 + n6 + n10 + n14,
n3 + n7 + n11 + n15,
n4 + n8 + n12 + n16
);
printf( "Diagonal sums: %d %d\n", (n1 + n6 + n11 + n16), (n4 + n7 + n10 + n13) );
return 0;
}
Τώρα, επειδή είναι λίγο... tedious να γράφεις συνεχώς τα έξτρα κάθε φορά που θες να διαβάσεις με scanf() την είσοδο, και με την προϋπόθεση πως θα κάνεις compile με ενεργοποιημένη την αναθεώρηση C99 στον compiler, μπορείς να αποθηκεύσεις στον editor/IDE σου το παρακάτω macro ως snippet (για να μη το γράφεις χειροκίνητα κάθε φορά), και να το βάζεις στην αρχή όλων των προγραμμάτων σου...
-
Μορφοποιημένος Κώδικας: Επιλογή όλων
-
/* C99 specific macro, substituting scanf() */
#define mySCANF( ... ) \
do { \
char iNPutbUfFeR[1024+1] = {'\0'}; \
fgets( iNPutbUfFeR, 1024+1, stdin ); \
sscanf( iNPutbUfFeR, __VA_ARGS__ ); \
} while(0)
Οπότε για παράδειγμα, η άσκηση πλέον μπορεί να γραφτεί ως εξής:
-
Μορφοποιημένος Κώδικας: Επιλογή όλων
-
#include <stdio.h>
/* C99 specific macro, substituting scanf() */
#define mySCANF( ... ) \
do { \
char iNPutbUfFeR[1024+1] = {'\0'}; \
fgets( iNPutbUfFeR, 1024+1, stdin ); \
sscanf( iNPutbUfFeR, __VA_ARGS__ ); \
} while(0)
/* ------------------------ */
int main( void )
{
int n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16;
printf( "Enter the integers from 1 to 16 in any order:\n" );
mySCANF( "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
&n1, &n2, &n3, &n4, &n5, &n6, &n7, &n8,
&n9, &n10, &n11, &n12, &n13, &n14, &n15, &n16
);
/* display them in tabular format */
printf( "\n%2d %2d %2d %2d\n", n1, n2, n3, n4 );
printf( "%2d %2d %2d %2d\n", n5, n6, n7, n8 );
printf( "%2d %2d %2d %2d\n", n9, n10, n11, n12 );
printf( "%2d %2d %2d %2d\n\n", n13, n14, n15, n16 );
printf( "Row sums: %d %d %d %d\n",
n1 + n2 + n3 + n4,
n5 + n6 + n7 + n8,
n9 + n10 + n11 + n12,
n13 + n14 + n15 + n16
);
printf( "Column sums: %d %d %d %d\n",
n1 + n5 + n9 + n13,
n2 + n6 + n10 + n14,
n3 + n7 + n11 + n15,
n4 + n8 + n12 + n16
);
printf( "Diagonal sums: %d %d\n", (n1 + n6 + n11 + n16), (n4 + n7 + n10 + n13) );
return 0;
}
Είτε με τον έναν είτε με τον άλλον τρόπο, προσπάθησε να απεμπλακείς από την χρήση της
scanf() όσο είναι ακόμα νωρίς και δεν την έχει συνηθίσει το μυαλό σου, έστω κι αν δεν καταλαβαίνεις ακόμα πως ακριβώς λειτουργούν τα παραπάνω... είναι απόλυτα φυσιολογικό γιατί είσαι στην αρχή ακόμα
