2009-11-13 17 views
24

Mam ciąg znaków C, który wygląda jak "Nmy stringP", gdzie N i P mogą być dowolną postacią. Jak mogę edytować go w "my string" w C?Usuń pierwszą i ostatnią literę z ciągu C

+2

Praca domowa? Dodaj tag "praca domowa", jeśli jest. – pmg

+0

Nie, nie zadanie domowe - po prostu próbuję nauczyć się C dla zabawy. – igul222

+1

W czystym C nie ma czegoś takiego jak "ciąg". Czy masz wskaźnik do bufora ('char *') lub tablicy znaków ('char []')? –

Odpowiedz

46

celu "usunięcie" 1st punkt znaku do drugiego znaku:

char mystr[] = "Nmy stringP"; 
char *p = mystr; 
p++; /* 'N' is not in `p` */ 

Aby usunąć ostatni znak zastąpić go '\ 0'

p[strlen(p)-1] = 0; /* 'P' is not in `p` (and it isn't in `mystr` either) */ 
+3

To może nie działać, ponieważ inicjując "Nmy stringP" jako literał, kompilator/linker może umieścić go w pamięci tylko do odczytu, powodując niepowodzenie edycji. – Suppressingfire

+8

@Suppressingfire: "Nmy stringP" jest rzeczywiście dosłownym ciągiem, ale jest kopiowane (char by char) do tablicy 'mystr'. Tablica 'mystr' jest modyfikowalna. – pmg

+0

@pmg: Gdzie kopiujesz? 'char * p = mystr' wskazuje' p' na 'mystr', nie kopiuje' mystr'. – quark

1

Najskuteczniejszym sposobem:

//Note destroys the original string by removing it's last char 
// Do not pass in a string literal. 
char * getAllButFirstAndLast(char *input) 
{ 
    int len = strlen(input); 
    if(len > 0) 
    input++;//Go past the first char 
    if(len > 1) 
    input[len - 2] = '\0';//Replace the last char with a null termination 
    return input; 
} 


//... 
//Call it like so 
char str[512]; 
strcpy(str, "hello world"); 
char *pMod = getAllButFirstAndLast(str); 

najbezpieczniej:

void getAllButFirstAndLast(const char *input, char *output) 
{ 
    int len = strlen(input); 
    if(len > 0) 
    strcpy(output, ++input); 
    if(len > 1) 
    output[len - 2] = '\0'; 
} 


//... 
//Call it like so 
char mod[512]; 
getAllButFirstAndLast("hello world", mod); 

Drugi sposób jest mniej wydajny, ale bezpieczniejszy, ponieważ można wprowadzić literały łańcuchowe do danych wejściowych. Możesz też użyć strdup na drugą stronę, jeśli nie chcesz go zaimplementować samodzielnie.

+0

Problem z drugą implementacją polega na upewnieniu się, że twój wynik jest wystarczająco duży do obsługi kopii przed wywołaniem metody getAllBufFirstAndLast(). W tym przypadku, poleciłbym dodanie zmiennej outputLength do wywołania i pozwoliłaby wywoływanej funkcji manipulować wyjściem z funkcjami strn *. – shank

+0

tak, to jest warunek wstępny, możesz dodać parametr długości. –

9

Inną opcją, ponownie przy założeniu, że „edytuj” oznacza, że ​​chcesz zmodyfikować w miejscu:

void topntail(char *str) { 
    size_t len = strlen(str); 
    assert(len >= 2); // or whatever you want to do with short strings 
    memmove(str, str+1, len-2); 
    str[len-2] = 0; 
} 

ten modyfikuje ciąg w miejscu, bez generowania nowego adresu jako rozwiązanie PMG za nie. Nie chodzi o to, że w odpowiedzi na pmg jest coś złego, ale w niektórych przypadkach nie jest to, czego chcesz.

2

nawiązaniu do użytkownika @ PMG odpowiedź, trzeba pamiętać, że można to zrobić zarówno operacje w jednym stwierdzeniem:

char mystr[] = "Nmy stringP"; 
char *p = mystr; 
p++[strlen(p)-1] = 0; 

to prawdopodobnie będzie działać zgodnie z oczekiwaniami, ale zachowanie jest niezdefiniowane w standardzie C.

+0

Najlepiej jednak nie polegać na niezdefiniowanym zachowaniu. – T0xicCode

+1

@ xav0989 Uzgodnione, zamierzałem dodać to jako komentarz (aby podkreślić powód, aby tego nie robić), a nie jako alternatywną odpowiedź. Jestem trochę nowy w tym. –

Powiązane problemy