2016-04-27 5 views
0

Так что я делаю прошлый бумажный вопрос о функциях/символах/указателях. Я столкнулся с проблемой в своем коде и нуждаюсь в помощи в понимании этого.Удаление символа из строки в C

В частности, у меня возникают проблемы с вопросом B) ii), который требует от меня удаления двоеточия из строки.

Моя идея состояла в том, чтобы взять строку, сделать указатель и указать прямо на двоеточие, а затем заменить этот двоеточие на следующий символ, который его продолжит. Затем замените остальные символы после двоеточия символом перед ним, пока он не достигнет NULL.

Когда дело доходит до компиляции, оно компилируется просто отлично, но дает мне ошибку сегментации: 11. Что происходит? Как я могу это исправить? Я что-то не понимаю? Благодарю.

Question

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


int locate_colon(char* x) //Question B) i) 
{ 
    int i = 0; 
    while(*x != '\0') 
    { 
     if(*x == ':') 
     { 
      return i; 
     } 
     i++; 
     x++; 
    } 
    return -1; 
} 

char* remove_colon(char* x) //Question B) ii) 
{ 
    int y,i,j; 
    y = locate_colon(x); 
    i =0; 
    j =1; 
    while(*x != '\0') 
    { 
     x[y+i] = x[y+j]; 
     i++; 
     j++; 
    } 
    return x; 
} 

int main() //Testing if functions work by running through compiler 
{ 
    int x; 
    char colon[] = "Colon: 123"; 
    char* colonptr; 
    colonptr = colon; 
    x = locate_colon(colonptr); 
    printf("%d",x); 

    //B) ii) 
    char* y; 
    y = remove_colon(colonptr); 
    while(y != '\0') 
    { 
     printf("%s",y); 
     y++; 
    } 
    return 0; 
} 
+1

Вы уверены, что хотите сбросить 'i' и' j' на '0' и' 1' соответственно для каждой итерации в 'remove_colon'? – Downvoter

+0

, если ваша функция 'remove_colon()' когда-либо возвращается, обязательно будет иметь место, что возвращаемое значение ('x') указывает на пустую строку, потому что это единственный способ выхода цикла. –

+0

@Downvoter ok Я исправил код, но все же придумал ошибку сегментации. – emuterisa

ответ

0

Ваш цикл в remove_colon() должно быть:

while(x[y+i] != '\0') 
{ 
    x[y+i] = x[y+j]; 
    i++; 
    j++; 
} 
x[y+i]= '\0'; 

и

while(y != '\0') 
{ 
    printf("%s",y); 
    y++; 
} 

должно быть просто:

printf("%s",y); 

или другой вариант:

printf("%s",colonptr); 
+0

Тогда вам придется отказаться от завершения после завершения цикла, если я не ошибаюсь. – SGM1

+0

@SGM, yep (фиксированный). –

+0

yay это работает, спасибо большое! : D – emuterisa

0

В его теперь удален ответ, @Giorgi указал этот фрагмент кода, который является действительным С, но тем не менее, совершенно неправильно:

while(y != '\0') 
{ 
    printf("%s",y); 
    y++; 
} 

Variable y является указателем на char, поэтому while (y != '\0') эквивалентен while (y != NULL), который некоторые люди предпочли бы написать просто while (y). C не определяет, каким образом приращение ненулевого указателя даст нулевой указатель, поэтому, если поведение в противном случае было бы корректно определено, этот цикл никогда не выйдет.

Фактически, однако, тело разломов петли y (косвенно, через printf()) и увеличивает его. Перед слишком большим количеством итераций y будет указывать вне памяти, выделенной объекту, с которым он первоначально указывал (в), и после этого поведение разыменования не определено. Ошибка сегментации является общим наблюдаемым результатом этого конкретного типа UB.

Я подозреваю, что вы намеревались написать while(*y != '\0'), но это все еще кажется странным, потому что вы закончите печать последовательности хвостов строки, тогда как кажется, вы хотите напечатать только одну строку. В этом случае мне непонятно, почему вы вообще используете петлю. Что не так просто

printf("%s",y); 

?

Конечно, это не единственное, что не так с вашим кодом, как указано в комментариях, но это, вероятно, объясняет ошибку сегментации, которая является предметом вашего фактического вопроса.

+0

Интересное объяснение, да, я должен был написать: while (* y! = '\ 0'), и вы теперь abit странно, что я думаю об этом. Большое спасибо! – emuterisa

+0

@emuterisa 'printf' выводит строку вверх по нулевому символу. Нет необходимости в цикле. Если вы хотите создать цикл и напечатать один символ, вы можете сделать 'printf («% c », * y);» и сохранить цикл. Опять же, это бессмысленно по сравнению с этим он 'printf ("% s ", y);' без цикла. – SGM1

Смежные вопросы