2016-08-23 9 views
-1

In meinem Programm versuche ich jedes argv [i] nach Schlüsselwort [i] zu kopieren, aber mein Programm schlägt mit einem Segmentierungsfehler fehl. Was mache ich falsch?Segmentierungsfehler beim Versuch, ein Array von Strings zu deklarieren

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

int main(int argc, string argv[])  
{ 
    //prototype 
    string keyword = ""; 
    //int j; 

    for (int i = 0, n = strlen(argv[1]); i < n; i++) 
    { 
     keyword[i] = toupper(argv[1][i]); 
     printf("%i-- printing letters\n", keyword[i]); 
    } 
} 
+0

'string keyword =" ";' Sie haben Nullplatz für den zu kopierenden String zugewiesen, und wenn Sie genügend Platz haben, müssen Sie auch einen 'nul' String terminator schreiben, bevor Sie ihn als" string "bezeichnen können ". –

+1

Was ist eine Schnur? Ist das C oder C++? –

+2

@IshayPeled: "*' string' * "die meisten Likes kommen aus" * '# include ' * "und scheint zu einem' typedef char * string; '...: -/ – alk

Antwort

4

Wie andere beobachtet haben, initialisieren Sie Variable keyword entweder als leere Zeichenfolge oder als Zeiger auf einen leeren String wörtlichen, über die Definition des Typs abhängig string. In jedem Fall ist es dann zulässig, keyword[i] nur für i gleich Null auszuwerten; Jeder andere Wert - zum Lesen oder Schreiben - ist außerhalb der Grenzen. Darüber hinaus dürfen Sie im letzteren Fall (Zeiger auf Zeichenfolgenliteral) nicht versuchen, das Array keyword Punkte zu ändern.

Beachten Sie insbesondere, dass C Zeichenfolgen nicht automatisch erweitert, wenn Sie versuchen, auf ein Out-of-Bounds-Element zuzugreifen. Ein Versuch, dies zu tun, erzeugt stattdessen "undefiniertes Verhalten", und ein üblicher Weg, sich in solchen Fällen zu manifestieren, ist die Form eines Segmentierungsfehlers. Sie können einen Segmentierungsfehler anzeigen, wenn das System Ihr Programm abstürzt, um auf Speicher zuzugreifen, der nicht zu ihm gehört.

Da Sie nicht a priori wissen, wie lange das Argument Zeichenfolge sein, bevor Sie es kopieren, die praktikabelste Art für keyword ist char *. Ich werde diesen Typ anstelle von string im Folgenden zur Verdeutlichung verwenden.

Wenn Sie tatsächlich eine Kopie des Arguments machen wollen, dann die mit Abstand einfachste Weg, dies zu tun ist über die für Zweckfunktion strdup():

char *keyword = strdup(argv[1]); 

, die für eine Kopie genug Speicher reserviert von Sein Argument, einschließlich des Terminators, kopiert es und gibt einen Zeiger auf das Ergebnis zurück. Sie sind dann verpflichtet, den resultierenden Speicher über die Funktion free() freizugeben, wenn Sie damit fertig sind. eine Kopie auf diese Weise gemacht haben, können Sie dann jedes Element anstelle upcase:

for (int i = 0, n = strlen(keyword); i < n; i++) 
    { 
     keyword[i] = toupper(keyword[i]); 
     printf("%c-- printing letters\n", keyword[i]); 
    } 

Hinweis, nebenbei gesagt, dass das printf() Format Descriptor für ein einzelnes Zeichen ist %c, nicht %i. Sie müssen dies verwenden, um die Zeichen als Zeichen statt ihrer ganzzahligen Werte zu drucken.

Das ist eine der einfachsten Möglichkeiten, C-Code für das, was Sie versuchen, zu schreiben, obwohl es viele Variationen gibt.Die einzig andere, die ich für Ihre Aufmerksamkeit bieten würde, ist zu nicht Kopie überhaupt das Argument:

char *keyword = argv[1]; 

Wenn Sie keyword initialisieren, die Art und Weise dann keinen Speicher Sie zuweisen oder eine Kopie erstellen; Stattdessen setzen Sie keyword, um auf dieselbe Zeichenfolge zu zeigen, die argv[1] verweist. Sie können diese Zeichenfolge an Ort und Stelle ändern (Sie können sie jedoch nicht verlängern), vorausgesetzt, Sie müssen den ursprünglichen Inhalt nicht beibehalten.

Bevor ich dies beende, sollte ich auch beachten, dass Ihr Programm nicht überprüft, ob es tatsächlich ein Argument gibt. Falls nicht (, d. H.argc < 2), enthält argv[1] entweder einen Nullzeiger (argc == 1) oder ist nicht definiert (argc == 0; Sie werden wahrscheinlich nie darauf stoßen). Wie auch immer, Ihr Programm erzeugt in diesem Fall undefiniertes Verhalten, wenn es versucht, argv[1] so zu verwenden, als wäre es ein Zeiger auf eine gültige Zeichenkette. Sie sollten zuerst diesen Fall testen und mit einer Diagnosemeldung enden, wenn kein Programmargument verfügbar ist.

+0

vielen dank! – olafironfoot

-2

Ihr Hauptproblem: Sie sind nicht Speicher für die neue Zeichenfolge Zuteilung (string keyword = "").

In C muss jede zur Kompilierungszeit nicht bekannte Größe während der Laufzeit dynamisch zugewiesen werden.

Auch Sie nie nach fehlenden Parametern suchen, die Ihr Programm zum Absturz bringen können.

Siehe Code unten für beide Korrekturen

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

int main(int argc, string argv[]) 

{ 
    if (argc != 2) 
    { 
     printf("Usage: %s <word>\n", argv[0]); 
     return 1; 
    } 
    int length = strlen(argv[1]); 
    string keyword = malloc(length+1); 

    for(int i = 0, n = strlen(argv[1]); i < n; i++) 
    { 
     keyword[i] = toupper(argv[1][i]); 
     printf("%i-- printing letters\n", keyword[i]); 

    } 
    keyword[length]=0; 
    free(keyword); 
} 
+1

'Ihr Hauptproblem: Sie ordnen Speicher für Ihre neue Schnur nicht zu ...... ...... und Sie' 'nicht frei()' es. – Michi

+2

Dieser Code wird ein Problem verursachen, wenn versucht wird, auf "Schlüsselwort" als String danach zuzugreifen, da es nicht nullterminiert ist. –

+0

'für (int i = 0, n = strlen' sollte' size_t i' nicht sein 'int'. Dasselbe gilt hier' Schlüsselwort [i] = toupper' Umwandlung zwischen 'char' und' int' – Michi

Verwandte Themen