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

Διαγραφή τιμών σε πίνακα - C


johnykim

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

Δημοσ.

Καλησπέρα.

 

Θέλω να διαγράψω κάποιες τιμές από έναν μονοδιάστατο πίνακα,άλλα έχω κάποιο πρόβλημα.Ο κώδικας είναι ο παρακάτω:

 

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

main()
{
char pinakas[10];
int i=0;

printf("Dwse times pinaka\n");
gets(pinakas);
//scanf("%s",pinakas);



for (i=0;i<10;i++)
{
 

if  (pinakas[i]=='0' || pinakas[i]=='1' || pinakas[i]=='2' || pinakas[i]=='3' || pinakas[i]=='4' ||  pinakas[i]=='5' || pinakas[i]=='6' || pinakas[i]=='7' || pinakas[i]=='8' || pinakas[i]=='9')
{
   printf("\nMh dineis arithmo\n"); 
   pinakas[i]='0;
   //pinakas[i]=' ';
}


}


printf("\nXarakthres = %s\n",pinakas);
printf("Plithos = %lu\n",strlen(pinakas));



 
 system("PAUSE");	
 return 0;
}

 

Σε μια συμβολοσειρά που δίνει ο χρήστης, θέλω να εμφανίζω το πλήθος των χαρακτήρων που δίνει,αλλά όχι τους αριθμούς.Έτσι μηδενίζω τις συγκεκριμένες τιμές με μια if(η if μπορεί να γίνει καλύτερη με επανάληψη ,αλλά κάνω δοκιμές ακόμα).

 

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

 

Δοκίμασα να χρησιμοποιήσω την scanf ,αντί για την gets,έτσι ώστε να μην μετράει τα κενά ,και αντί να μηδενίζω τις τιμές που δεν θέλω, να τις αντικαθιστώ με κενό όπου δεν θα έχει διαβάσει η scanf.Δυστυχώς όμως στο πλήθος είναι μέσα και οι αριθμοί(κενά).:-(

Δημοσ.

Αντικατεστησε το for που εχεις με αυτο

 

>
int plithos = 0;
for (i=0;i<10;i++)
{
if  (pinakas[i]=='0' || pinakas[i]=='1' || pinakas[i]=='2' || pinakas[i]=='3' || pinakas[i]=='4' ||  pinakas[i]=='5' || pinakas[i]=='6' || pinakas[i]=='7' || pinakas[i]=='8' || pinakas[i]=='9')
{    
    continue;
}
else
   plithos ++;
}

 

και μετα τυπωσε το plithos

Δημοσ.

Ούτε if ούτε counters:

 

>
scanf("%9[A-Za-z]s", pinakas);

 

Και με μία strlen στο τέλος είσαι αρχηγός.

 

 

edit: Άκυρο, δεν είναι σωστή η λύση που προτείνω. Sorry! :(

Δημοσ.
Αντικατεστησε το for που εχεις με αυτο

 

>
int plithos = 0;
for (i=0;i<10;i++)
{
if  (pinakas[i]=='0' || pinakas[i]=='1' || pinakas[i]=='2' || pinakas[i]=='3' || pinakas[i]=='4' ||  pinakas[i]=='5' || pinakas[i]=='6' || pinakas[i]=='7' || pinakas[i]=='8' || pinakas[i]=='9')
{    
    continue;
}
else
   plithos ++;
}

 

και μετα τυπωσε το plithos

 

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

main()
{
char pinakas[10];
int i;
int p=0;

printf("Dwse times pinaka\n");
gets(pinakas);
//scanf("%s",pinakas);



for (i=0;i<10;i++)
{
 

if  (pinakas[i]=='0' || pinakas[i]=='1' || pinakas[i]=='2' || pinakas[i]=='3' || pinakas[i]=='4' ||  pinakas[i]=='5' || pinakas[i]=='6' || pinakas[i]=='7' || pinakas[i]=='8' || pinakas[i]=='9')
{
   continue;
}
else
{
       p++;
}        
   
}


printf("\nXarakthres = %s\n",pinakas);
printf("Plithos = %d\n",p);

 
 system("PAUSE");	
 return 0;
}

 

 

 

Τι λάθος κάνω; Το πλήθος δεν βγαίνει σωστό..:-(

 

@parsifal,αν και είδα το edit,θα το δοκίμαζα αν μου έλεγες τι ακριβώς διαβάζεις με την scanf..:o

Δημοσ.
@parsifal,αν και είδα το edit,θα το δοκίμαζα αν μου έλεγες τι ακριβώς διαβάζεις με την scanf..:o

 

Η scanf με τη συγκεκριμένη σύνταξη διαβάζει το πολύ 9 χαρακτήρες, με scanset A-Za-z μέχρι να συναντήσει χαρακτήρα που δεν ανήκει σε αυτό το scanset.

 

Όπως είπα όμως, δεν κάνει αυτό που ζητάς γιατί ακριβώς σταματά όταν συναντήσει χαρακτήρα εκτός scanset, δεν τον απορρίπτει απλώς και πάει παρακάτω. Άρα, αν η συμβολοσειρά που εισάγει ο χρήστης:

 

1. Αρχίζει με χαρακτήρα εκτός scanset, π.χ. "1abc" ή

2. Περιέχει εμβόλιμα τέτοιους χαρακτήρες, π.χ. "a1bc"

 

ο κώδικας δε θα έχει επιθυμητή συμπεριφορά.

Δημοσ.
>
main()

Να δηλώνεις την main πάντα ως int main(void);

 

>
char pinakas[10];
gets(pinakas);

Η gets δεν πρέπει να χρησιμοποιείται ποτέ επειδή δεν ελέγχει το μέγεθος του

buffer (επίσης θεωρείται deprecated και θα πάψει να υπάρχει στις διάφορες

libc). Εσύ δηλώνεις τον πίνακα με μέγεθος 10. Αν ο χρήστης δώσει 20 χαρακτήρες

τότε αυτοί οι χαρακτήρες θα γραφτούν σε περιοχή μνήμης που δεν θα έπρεπε

(πιθανότατα θα σβήσουν τα i,p και ποιος ξέρει τι άλλο). Μπορείς να χρησιμοποιείς

την fgets ή άλλες με ίδια λειτουργία.

 

>
for (i=0;i<10;i++)

 

Εκτελείς το for 10 φορές ενώ ο χρήστης μπορεί να δώσει 6 χαρακτήρες. Έλεγξε

με την strlen το μέγεθος.

 

>
if  (pinakas[i]=='0' || pinakas[i]=='1' || pinakas[i]=='2' || pinakas[i]=='3' || pinakas[i]=='4' ||  pinakas[i]=='5' || pinakas[i]=='6' || pinakas[i]=='7' || pinakas[i]=='8' || pinakas[i]=='9')

Αν χρησιμοποιείς ASCII, τότε οι αριθμοί είναι συνεχόμενοι και έχουν τιμές 0x30-0x39

οπότε μπορείς να το χρησιμοποιήσεις αυτό για να μην έχεις όλο αυτό το if

 

>
 system("PAUSE");	

Μην χρησιμοποιείς την system("PAUSE"). Αφενός η system είναι πολύ βαριά

και αφετέρου το πρόγραμμά σου θα παίζει μόνο σε Windows. Χρησιμοποίησε

μια εντολή που να δέχεται ένα χαρακτήρα όπως scanf,getchar.

 

@parsifal,αν και είδα το edit,θα το δοκίμαζα αν μου έλεγες τι ακριβώς διαβάζεις με την scanf..:o

Η scanf που έδωσε ο parsifal διαβάζει 9 αλφαριθμητικούς χαρακτήρες (αν δεν

κάνω λάθος δεν χρειάζεται το s στο τέλος).

 

Το πρόγραμμά σου θα μπορούσε να γίνει ως εξής:

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

int main(void)
{
char pinakas[10];
int i;
int s, p=0;

printf("Dwse times pinaka\n");
fgets(pinakas, 10, stdin);
s=strlen(pinakas);
if (pinakas[s-1]==0xa) s--;

for (i=0;i<s;i++)
{
   if ((pinakas[i]<0x30) || (pinakas[i]>0x39))
        p++;
}

printf("\nXarakthres = %s\n",pinakas);
printf("Plithos = %d\n",p);


i=getchar();
 return 0;
}

Δημοσ.

Ορίστε, ο παρακάτω κώδικας πρέπει να κάνει ακριβώς αυτό που θέλεις:

 

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

int main(void)
{
char pinakas[10] = "", c;
int i, index;

printf("Eisagete symvoloseira: ");

for(i = 0; i < 9 && (c = getchar()) != '\n';) {

	if(c >= '0' && c <= '9')
		continue;

	index = strlen(pinakas);
	pinakas[index] = c;
	pinakas[index + 1] = '\0';
	i++;
}

printf("Xarakthres = %s\n", pinakas);
printf("Plithos = %d\n", strlen(pinakas));

return 0;
}

 

Τσέκαρέ τον και αν έχεις απορίες, εδώ είμαστε!

Δημοσ.

parsifal ftw

 

Αντί για το index+strlen, δεν θα μπορούσε να χρησιμοποιηθεί το i ?

 

Στην συγκεκριμένη περίπτωση δεν παίζει ρόλο, αλλά γενικά να μην χρησιμοποιείται

μεταβλητή τύπου char στις συναρτήσεις που επιστρέφουν χαρακτήρα.

Δημοσ.
Αντί για το index+strlen, δεν θα μπορούσε να χρησιμοποιηθεί το i ?

 

Στην συγκεκριμένη περίπτωση δεν παίζει ρόλο, αλλά γενικά να μην χρησιμοποιείται

μεταβλητή τύπου char στις συναρτήσεις που επιστρέφουν χαρακτήρα.

 

Για το 1ο, ναι, έχεις δίκιο. Είναι όντως άσκοπη η κλήση της strlen, το i μέσα στο βρόχο δίνει την ίδια τιμή.

 

Για το 2ο, δεν κατάλαβα που αναφέρεσαι ακριβώς. :shifty:

Δημοσ.

Για το 2ο, δεν κατάλαβα που αναφέρεσαι ακριβώς. :shifty:

 

Εγκυκλοπαιδικά το ανέφερα. Στην συγκεκριμένη περίπτωση δεν παίζει ρόλο.

Πχ όμως στις getc,fgetc αν η μεταβλητή είναι τύπου char μπορούν να δημιουργηθούν

προβλήματα.

Δημοσ.

Α, λες για το implicit conversion από int σε char που γίνεται εδώ:

>
c = getchar();

 

Ναι, η getchar επιστρέφει int, σωστός και σε αυτό.

Δημοσ.
Α, λες για το implicit conversion από int σε char που γίνεται εδώ:

>
c = getchar();

 

Ναι, η getchar επιστρέφει int, σωστός και σε αυτό.

 

Δεν πειράζει το conversion αυτό καθεαυτό αλλά υπό ορισμένες συνθήκες μπορεί

να προκύψει overflow. Συχνά σε προγράμματα υπάρχει έλεγχος αν ισούται ο

χαρακτήρας που επιστράφηκε με το EOF που σημαίνει ότι έγινε κάποιο σφάλμα.

Συνήθως το EOF ορίζεται ως -1.

 

Όταν ο τύπος της μεταβλητής είναι char, τότε αν διαβαστεί ο χαρακτήρας 255 (0xFF)

αυτό θα μεταφραστεί σε -1 οπότε το σώμα του ελέγχου θα εκτελεστεί ενώ δεν

υπήρχε λάθος. Με int δεν γίνεται αυτό γιατί το 255 και το -1 είναι διαφορετικές τιμές.

 

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

για κάποιον που θα διαβάσει στο μέλλον το thread.

Δημοσ.

Κι όμως imitheos, το σχόλιό σου είναι εύστοχο και στην περίπτωση του κώδικα που παρέθεσα. Γιατί; Γιατί δεν υπάρχει εγγύηση ότι ο χρήστης π.χ. δε θα καλέσει το πρόγραμμα με piping/redirection εισόδου από έξοδο τρίτου προγράμματος ή από αρχείο. Οπότε εκεί θα υπάρξει πρόβλημα όταν στο αρχείο, πριν τον EOF χαρακτήρα, δεν υπάρχει newline character για να τερματιστεί σωστά η for. Λαμβάνοντας λοιπόν υπ' όψιν αυτό, ορίστε μία βελτιωμένη έκδοση:

 

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

int main(void)
{
   char array[10] = "";
   int i, c;

   printf("Please enter a string: ");

   for(i = 0; i < 9 && (c = getchar()) != '\n' && c != EOF;) {
       if(c >= '0' && c <= '9') continue;
       array[i] = c;
       i++;
   }

   array[i] = '\0';
   printf("String = %s\n", array);
   printf("String length = %d\n", i);

   return 0;
}

 

Εκτός της μεταβλητής c που έγινε τύπου int, προστέθηκε έλεγχος και για EOF. Οπότε τώρα ο κώδικας θα λειτουργεί σωστά και με ανακατεύθυνση εισόδου από αρχείο. Π.χ.:

 

a1b2c3d4e5f6g7

 

>
C:\Users\parsifal>program.exe < input.txt
Please enter a string: String = abcdefg
String length = 7

Δημοσ.

Παιδιά ευχαριστώ πολύ για τον χρόνο σας!

 

Τα είδα,λειτουργούν! Κάποιες απορίες που έχω, θα σας πω αύριο.:-)

Δημοσ.

Καλημέρα :-)

 

Λοιπόν ,χθες το βράδυ μπερδευόμουν στον κώδικα του parsifal με τον μετρητή i και το πλήθος strlen(pinakas).:o Μετά κατάλαβα αυτό που είπε ο imitheos :-D

 

Μια απορία που έχω : Η "continue;" τι ακριβώς κάνει βρε παιδιά; Αφού έχουμε δώσει ήδη όλες τις τιμές της συμβολοσειράς(που μπορεί να είναι και αριθμοί) ,μετά η "continue;"(αν υπάρχει αριθμός)τον διαγράφει; Πως δεν υπολογίζεται στο πλήθος ο κάθε αριθμός με την "continue;" ;

 

Μια αλλαγή που έκανα είναι "pinakas[10]='\0';" εκτός επανάληψης.Δεν είναι πιο βαρύς ο κώδικας να αντικαθιστά το " '\0'; " στην for κάθε φορά;

 

@imithee, επικεντρώθηκα πιο πολύ στον κώδικα του parsifal , επειδη μου φάνηκε πιο εύκολος.:o

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...