2017-02-17 3 views
0

Ich habe die folgende Methode, die in zwei Zeichenfolgen liest, um den Vor- und Nachnamen von zwei Einträgen in einer Datenbank zu ändern. Der Name wird immer in Kleinbuchstaben konvertiert und sollte nur Namen mit Buchstaben oder Bindestrichen enthalten, es sei denn, der Bindestrich ist das erste oder letzte Zeichen in der Zeichenfolge. Bei einem Fehler wird der Benutzer nur erneut aufgefordert.Logischer Fehler in meinem C-Code

/* 
Prompts for a student name, and checks if input is correct. 
Returns 0 on success, -1 onEOF. 
If the user inputs an invalid entry, the error is ignored and the user is simply asked again. 
*/ 
int get_name(char *first, char *last) 
{ 
char input[LINESIZE]; 
char buffer[LINESIZE]; 
char buffer2[LINESIZE]; 
int i; 

while (1) 
{ 
    printf("\n%s", "Enter the Student Name "); 
    if (!fgets(input, LINESIZE, stdin)) 
    { 
     clearerr(stdin); 
     return -1; 
    } 
    if (sscanf(input, "%s %s", buffer, buffer2) == 2) 
    { 
     if (strlen(buffer) < 20 && strlen(buffer2) < 20 && strlen(buffer) >= 2 && strlen(buffer2) >= 2) /*checks to see if the length is at least 2, but less than 20*/ 
     { 
      for (i = 0; i < 20; i++) /*checks every character on the string, converts it to lower and then checks if it's a letter or a hyphen, restarts if not.*/ 
      { 
       if (isalpha(buffer[i])) 
       { 
        buffer[i] = tolower(buffer[i]); 
       } 
       if (isalpha(buffer2[i])) 
       { 
        buffer2[i] = tolower(buffer2[i]); 
       } 
       if (!isalpha(buffer[i]) && buffer[i] != '-') 
       { 
        break; 
       } 
       if (!isalpha(buffer2[i]) && buffer2[i] != '-') 
       { 
        break; 
       } 
      } 
      if (buffer[0] == '-' || buffer[(strlen(buffer) - 1)] == '-') 
      { 
       i = 0; 
      } 
      if (buffer2[0] == '-' || buffer2[(strlen(buffer2) - 1)] == '-') 
      { 
       i = 0; 
      } 
      if (i == 20) 
      { 
       sscanf(buffer, "%s", first); 
       sscanf(buffer2, "%s", last); 
       return 0; 
      } 
     } 
    } 
} 

}

Ich habe den Fehler auf die Linien mit (!isalpha(buffer[i]) && buffer[i] != '-') aufgespürt, aber ich kann nicht herausfinden, warum die Aussage falsch ist.

So kann beispielsweise eine erfolgreiche Eingabe "John Smith" oder "Hom-er Simpson" sein. In beiden Fällen sollte die Funktion 0 (erfolgreich) zurückgeben. Wenn die Eingabe etwas wie: "Denny's White", "-alexa Redfield", "Albert" oder "1234 5647" ist, sollte die Funktion einfach von vorn beginnen (den Benutzer erneut auffordern). Im Moment, unabhängig von der Eingabe, beginnt die Funktion neu.

+1

zeigen Sie einen Beispiel-Eingang, sollte Ausgang und tatsächliche Leistung. –

+0

Ohne Kommentare ist es wirklich schwer zu sagen, welche Teile dieses Codes gemacht werden sollen. Warum testen Sie zum Beispiel, ob "i" 20 erreicht hat? Was denkst du macht das? Und was denkst du, was diese zwei "scanf" Anrufe am Ende tun? Was ist der beabsichtigte Zweck der beiden Break-Statements? –

+0

meine schlechte, ich werde den Beitrag bearbeiten, um weitere Kommentare hinzuzufügen. Der Grund, warum ich überprüfe, ob i == 20 ist, weil ich die for-Schleife beabsichtigte zu überprüfen, ob jedes Zeichen in der Zeichenfolge kein Buchstabe oder Bindestrich ist. Wenn die for-Schleife erfolgreich ausgeführt wird, würde sie bei i = 20 stehen bleiben, was bedeutet, dass es keine Probleme mit der Eingabe gibt und 0 zurückgeben kann (was bedeutet, dass die Methode erfolgreich war). Der sscanf macht den ersten = Puffer und den letzten = Puffer2. – Snow

Antwort

1

Die Haupt Logikfehler in Ihrem Programm ist die Tatsache, dass Sie eine for Schleife mit einer festen Anzahl (20) von Wiederholungen auf zwei Arrays zugleich ausgeführt werden. Sie sollten zwei separate Schleifen für die Vor- und Nachnamen-Arrays ausführen. Außerdem sollten Sie diese beiden Schleifen nur für strlen jedes Arrays ausführen. Siehe das folgende Beispiel:

for (i = 0; i < strlen(buffer); i++) 
{ 
    /* your existing stuff for the "buffer" */ 
} 

for (i = 0; i < strlen(buffer1); i++) 
{ 
    /* your existing stuff for the "buffer1" */ 
} 
+0

@WeatherVane, danke für Ihre Eingaben. "@ snow", bitte lies dies auch. – VHS

+0

Vielen Dank! Mein Programm funktioniert jetzt wie beabsichtigt. Ich habe das i in der zweiten for-Schleife in ein j geändert, da am Ende überprüft werden muss, ob beide Schleifen erfolgreich waren. Auch auf die Antwort von Weather Vane bin ich nicht sicher, was das bedeutet? – Snow

+0

@ WeatherVane Ich sehe. Wäre das so einfach wie 'buffer [strlen (buffer)] = '/ 0'' zu sagen, oder ist es etwas viel komplexer? – Snow

0

Caveat: VHS das Hauptproblem bekam. Dies weist jedoch auch auf ein strukturelles Problem in Ihrem Code hin, das verbessert werden kann. Fast der gesamte Code ist für jedes Array doppelt vorhanden.

Das Erstellen einer Funktion zum Arbeiten mit dem Array hätte [wahrscheinlich] das Erkennen des Problems erleichtert.

ich Ihren Code überarbeitet habe diesen hinzufügen [bitte unentgeltlichen Stil Bereinigungs verzeihen]:

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

#define LINESIZE 80 

int 
bufdo(char *buf) 
{ 
    int len; 
    int idx; 
    int chr; 
    int ret; 

    len = strlen(buf); 

    do { 
     // assume non-conforming 
     ret = -1; 

     // length too great 
     if (len >= 20) 
      break; 

     // length too small 
     if (len < 2) 
      break; 

     // begins with hyphen 
     if (buf[0] == '-') 
      break; 

     // ends with hyphen 
     if (buf[len - 1] == '-') 
      break; 

     // assume it will be okay 
     ret = len; 

     // convert to lowercase and check for bad chars 
     for (idx = 0; idx < len; ++idx) { 
      chr = buf[idx]; 

      if (isalpha(chr)) { 
       chr = tolower(chr); 
       buf[idx] = chr; 
       continue; 
      } 

      // non-hyphen char in name 
      if (chr != '-') { 
       ret = -1; 
       break; 
      } 
     } 
    } while (0); 

    return ret; 
} 

int 
get_name(char *first, char *last) 
{ 

    char input[LINESIZE]; 
    char buffer[LINESIZE]; 
    char buffer2[LINESIZE]; 
    int len1; 
    int len2; 
    int ret; 

    ret = -1; 

    while (1) { 
     printf("\n%s", "Enter the Student Name "); 
     fflush(stdout); 

     if (!fgets(input, LINESIZE, stdin)) { 
      clearerr(stdin); 
      break; 
     } 

     if (sscanf(input, "%s %s", buffer, buffer2) != 2) 
      continue; 

     len1 = bufdo(buffer); 
     len2 = bufdo(buffer2); 

     if ((len1 > 0) && (len2 > 0)) { 
      strcpy(first,buffer); 
      strcpy(last,buffer2); 
      ret = 0; 
      break; 
     } 
    } 

    return ret; 
} 
+0

Vielen Dank! Das ist definitiv viel schöner. – Snow

+0

Gern geschehen! Beachten Sie, dass ich die Funktion stückweise aufgebaut habe. Ursprünglich habe ich es 'getlen' genannt und es hat nur' strlen' und die Längenbereichsprüfung gemacht. Ich wollte andere Funktionen für die anderen Schritte erstellen, fügte aber die anderen Schritte einzeln hinzu, als mir klar wurde, dass sie sich gut in die Funktion einfügen würden. Am Ende war die einzige Funktion ausreichend. Eine gute Faustregel ist die "Skalierung" (d. H. Tut mein Code _scale_ gut [genug]?). Mit etwas mehr Erfahrung werden diese Design-Entscheidungen leichter zu sehen und (fast) axiomatisch. Fröhliche Programmierung! –