2010-02-26 48 views
10

Tôi biết điều này đã được hỏi hàng ngàn lần nhưng tôi không thể tìm thấy lỗi trong mã của tôi. Ai đó có thể vui lòng chỉ ra những gì tôi đang làm sai?Đảo ngược một chuỗi trong C

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

void reverseString(char *myString){ 
    char temp; 
    int len = strlen(myString); 

    char *left = myString; 
    // char *right = &myString[len-1];                       
    char *right = myString + strlen(myString) - 1; 

    while(left < right){ 
    temp = *left; 
    *left = *right; // this line seems to be causing a segfault                
    *right = temp; 
    left++; 
    right--; 
    } 
} 

int main(void){ 
    char *somestring = "hello"; 
    printf("%s\n", somestring); 
    reverseString(somestring); 

    printf("%s", somestring); 

} 
+1

Mặc dù mọi người trả lời câu hỏi của bạn figured it out, bạn không bao giờ biết những gì lỗi bạn đã nhận được, hoặc những gì đã không làm việc! Bạn nên luôn luôn mô tả những gì bạn mong đợi, và những gì bạn thực sự nhìn thấy. (Đầu ra không chính xác? Seg-lỗi/GPF lỗi? Loop vô hạn/hang?) – abelenky

+0

Đó là một segfault. Tôi nên đề cập đến nó, cảm ơn bạn đã nhắc nhở. – qwer

Trả lời

13

vấn đề là ở đây

char *somestring = "hello"; 

điểm someString đến chuỗi chữ "hello". tiêu chuẩn C++ không bảo đảm điều này, nhưng trên hầu hết các máy, đây sẽ là dữ liệu chỉ đọc, vì vậy bạn sẽ không được phép sửa đổi nó.

khai báo nó theo cách này thay vì

char somestring[] = "hello"; 
+0

Điều tôi không thích về phương pháp này là hàm sẽ sửa đổi tham số đầu vào của nó. YMMV. – dirkgently

+1

dirkgently: Có, nhưng nó cũng nhanh hơn gấp đôi so với thay thế và sử dụng ít bộ nhớ hơn. Một số lập trình viên làm việc trên các tác vụ có hiệu suất. –

+3

Nếu phần quan trọng về hiệu suất của ứng dụng của bạn là đảo ngược chuỗi trong vòng lặp chặt chẽ, tôi nghĩ bạn nên suy nghĩ lại về thiết kế của mình. –

6

Bạn đang gọi hành vi undefined bằng cách cố gắng để sửa đổi một khu vực bộ nhớ có khả năng read-only (xâu là ngầm const - đó là ok để đọc chúng nhưng không phải viết cho họ). Tạo một chuỗi mới và trả về nó, hoặc vượt qua một bộ đệm đủ lớn và viết chuỗi đảo ngược vào nó.

-1

luận của bạn có vẻ đúng. Thay vì sử dụng con trỏ, nó là sạch hơn để đối phó với char[].

13

Cuối cùng, nó sẽ sạch hơn để đảo ngược nó tại chỗ, như vậy:

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

void 
reverse(char *s) 
{ 
    int a, b, c; 
    for (b = 0, c = strlen(s) - 1; b < c; b++, c--) { 
     a = s[b]; 
     s[b] = s[c]; 
     s[c] = a; 
    } 

    return; 
} 

int main(void) 
{ 
    char string[] = "hello"; 
    printf("%s\n", string); 
    reverse(string); 
    printf("%s\n", string); 

    return 0; 
} 

giải pháp của bạn về bản chất là một phiên bản ngữ nghĩa lớn hơn thế này. Hiểu sự khác biệt giữa một con trỏ và một mảng. Các tiêu chuẩn một cách rõ ràng nói rằng behviour của một hoạt động (sửa đổi các nội dung của một chuỗi chữ) là không xác định. Bạn cũng sẽ thấy this đoạn trích từ eskimo:

Khi bạn khởi tạo một mảng ký tự với một chuỗi liên tục:

char string[] = "Hello, world!"; 

bạn kết thúc với một mảng chứa các chuỗi, và bạn có thể sửa đổi nội dung của mảng để bạn nội dung của trái tim:

string[0] = 'J'; 

Tuy nhiên, có thể sử dụng hằng số chuỗi (cụm từ chính thức là chuỗi ký tự) tại các vị trí khác trong mã của bạn. Vì chúng là các mảng, trình biên dịch tạo ra các con trỏ tới các phần tử đầu tiên của chúng khi chúng được sử dụng trong các biểu thức, như thường lệ. Nghĩa là, nếu bạn nói

char *p1 = "Hello"; 
int len = strlen("world"); 

nó gần như là nếu bạn muốn nói

char internal_string_1[] = "Hello"; 
char internal_string_2[] = "world"; 
char *p1 = &internal_string_1[0]; 
int len = strlen(&internal_string_2[0]); 

Ở đây, các mảng tên internal_string_1 và internal_string_2 có nghĩa vụ phải đề nghị thực tế là trình biên dịch thực sự tạo ra ít tạm thời mảng mỗi khi bạn sử dụng một hằng số chuỗi trong mã của bạn. Tuy nhiên, thực tế tinh tế là các mảng có `` đằng sau '' các hằng số chuỗi không nhất thiết phải có thể sửa đổi được. Đặc biệt, trình biên dịch có thể lưu trữ chúng trong bộ nhớ chỉ đọc. Do đó, nếu bạn viết

char *p3 = "Hello, world!"; 
p3[0] = 'J'; 

chương trình của bạn có thể gặp sự cố, vì nó có thể cố gắng lưu giá trị (trong trường hợp này là ký tự 'J') vào bộ nhớ không thể ghi.

Đạo đức là bất cứ khi nào bạn xây dựng hoặc sửa đổi chuỗi, bạn phải đảm bảo rằng bộ nhớ bạn đang xây dựng hoặc sửa đổi chúng có thể ghi được.Bộ nhớ đó hoặc là một mảng mà bạn đã cấp phát hoặc một số bộ nhớ mà bạn đã phân bổ động bằng các kỹ thuật mà chúng ta sẽ thấy trong chương tiếp theo. Hãy chắc chắn rằng không có phần nào của chương trình của bạn sẽ cố gắng sửa đổi một chuỗi mà thực sự là một trong những mảng không tên, không có khả năng mà trình biên dịch tạo ra cho bạn để đáp ứng với một trong các hằng số chuỗi của bạn. (Ngoại lệ duy nhất là khởi tạo mảng, vì nếu bạn ghi vào mảng như vậy, bạn đang ghi vào mảng đó, không phải bằng chuỗi ký tự mà bạn đã sử dụng để khởi tạo mảng.) "

+1

Cảm ơn bạn đã nhập mã và liên kết để giải thích! Tôi đã học được rất nhiều điều từ kinh nghiệm này hơn là tôi muốn quan tâm: P – qwer

+0

@ qwer: Rất vui được giúp đỡ. –

+1

Câu trả lời Kickass. –

0

Bạn có thể sử dụng mã sau đây

#include<stdio.h> 
#include<string.h> 
#include<malloc.h> 
char * reverse(char*); 

int main() 
{ 
     char* string = "hello"; 
     printf("The reverse string is : %s", reverse(string)); 
     return 0; 
} 

char * reverse(char* string) 
{ 

    int var=strlen(string)-1; 
    int i,k; 
    char *array; 
    array=malloc(100); 
    for(i=var,k=0;i>=0;i--) 
    { 
      array[k]=string[i]; 
      k++; 
    } 
    return array; 
} 
0

tôi mang nó gọi strrev() là ra câu hỏi?

+0

Vâng, vấn đề là cố gắng tự viết nó. – qwer