#c #string
Вопрос:
Итак, вот в чем проблема:
- Введите строку, содержащую числа от 0 до 9 (максимальная длина-15).
- Если самый левый символ делится на 3, удалите его из строки
- Если самый правый символ делится на 3, удалите его из строки
- Если строка не соответствует двум вышеуказанным условиям и если сумма самого левого символа и самого правого символа делится на 3, удалите их из строки.
- Продолжайте делать это до тех пор, пока строка не станет НУЛЕВОЙ или не будет соответствовать вышеуказанным условиям. Пример: ввод: «312248» —> вывод: 2. Ввод: «366936363» —>> вывод: «» Итак, вот мой код:
#include <stdio.h>
#include <stdbool.h>
#include <conio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
char* truncateString(char* s)
{
char *p = amp;s[0];
int n = strlen(s);
p = calloc(n,sizeof(char));
int flag = 1;
do{
for (int i = 0; i < strlen(s); i )
{
if ((s[0]-'0') % 3 == 0)
{
for(int j = 0; j < strlen(s); j )
{
s[j] = s[j 1];
}
p = realloc(p, (strlen(s)-1)*sizeof(char));
}
else if ((s[strlen(s)-1]-'0') % 3 == 0)
{
p = realloc(p, (strlen(s)-1)*sizeof(char));
}
else if (((s[strlen(s)-1]-'0') (s[0]-'0')) % 3 == 0)
{
for(int j = 0; j < (strlen(s)-1); j )
{
s[j] = s[j 1];
p = realloc(p, (strlen(s)-2)*sizeof(char));
}
}
else
{
flag = 0;
}
}
} while (strlen(s) != 0 || flag != 0);
free(p);
return s;
}
int main()
{
char s[100];
gets(s);
printf("Result:%s", truncateString(s));
getch();
return 0;
}
Я, честно говоря, не знаю, как проверить, делится ли символ на 3 или нет, поэтому код не выполняется.
Комментарии:
1. Это не возвращает результат, я не знаю, почему
2. я получил его, поэтому я не могу использовать другое, если в этом случае, но я должен использовать, если
3. Вы указываете p на s, а затем сразу же указываете его в другое место, выделенное calloc, а затем изменяете кучу p, даже ничего в нее не помещая, а затем освобождаете ее и, наконец, возвращаете неизмененный s. Вам не нужны все эти перераспределения и все такое. Вопрос в том, хотели ли вы вернуть измененный s или вернуть выделенную строку, содержащую данные, без изменения s?
4. Все эти звонки на
strlen(s)
… что в данном случае ничего не меняет. Просто поместите его уже в vraiable !5. @QuanLeAnh Я не думаю, что проблема в другом — потому что вы находитесь в цикле, если вы не поймаете это на этой итерации, вы поймаете это на следующей — я думаю, что это будет работать с другим.
Ответ №1:
Я бы рассмотрел возможность переписывания, которое четко соответствует целям кодирования, для исправления функциональных ошибок.
(s[0]-'0') % 3 == 0
это прекрасный способ проверить делимость, поскольку s[0]-'0'
обеспечивает текстовое char
int
значение.
Часто бывает полезно помещать цели в виде комментариев прямо там, где они используются.
strlen()
нужно позвонить только один раз. Обновите длину по мере необходимости. Это позволяет избежать повторяющихся вызовов strlen()
, каждый из которых обходится в O(len).
char* truncateString(char *s) {
char *start = s;
size_t len = strlen(s);
// Keep doing so until the string is "NULL"
while (len > 0) {
char left = s[0] - '0';
bool left_remove = left % 3 == 0;
char right = s[len - 1] - '0';
bool right_remove = right % 3 == 0;
bool right_differ_from_left = len > 1;
// If the left most character divisible by 3, remove it from the string
if (left_remove) {
s ;
len--;
}
// Only consider the 'right' if the string was more than 1.
if (right_differ_from_left) {
// If the right most character divisible by 3, remove it from the string
if (right_remove) {
len--;
s[len] = '';
}
// If the string does not match the above two conditions,
// and if the summary of the left most character and
// the right most character is divisible by 3,
// remove them from the string.
if (!left_remove amp;amp; !right_remove amp;amp; (left right) % 3 == 0) {
s ;
len -= 2;
s[len] = '';
left_remove = right_remove = true;
}
}
// Keep doing so until the string is ... not meet the above conditions.
if (!left_remove amp;amp; !right_remove) {
break;
}
}
// Move string to its original beginning.
return memmove(start, s, len 1);
}
Если цели кодирования стабильны, существуют упрощения. Тем не менее, обратите внимание, что это может быть быстрее, сложнее увидеть, что это соответствует целям кодирования, чем вышеописанное.
char* truncateString2(char *s) {
char *start = s;
size_t len = strlen(s);
size_t len_at_loop_start;
do {
len_at_loop_start = len;
while (len > 0 amp;amp; (s[0] - '0') % 3 == 0) {
s ;
len--;
}
while (len > 0 amp;amp; (s[len-1] - '0') % 3 == 0) {
len--;
}
while (len > 1 amp;amp; (s[0] - '0' s[len-1] - '0') % 3 == 0) {
s ;
len -= 2;
}
} while (len < len_at_loop_start);
s[len] = '';
return memmove(start, s, len 1);
}
Ответ №2:
У вас тоже проблемы с перераспределением. Попробуйте это, это может упростить дело
char* truncateString(char* s)
{
int n = strlen(s);
int flag = 1;
while (strlen(s) != 0 amp;amp; flag != 0){
if ((s[0]-'0') % 3 == 0)
s ;
else if ((s[strlen(s)-1]-'0') % 3 == 0)
s[strlen(s)-1] = '';
else if (((s[strlen(s)-1]-'0') (s[0]-'0')) % 3 == 0)
{
s ;
s[strlen(s)-1] = '';
}
else
flag = 0;
}
return s;
}
Краткое объяснение: когда вы объявляете s
, что вы точно удаляете первый элемент массива, а с помощью s[strlen(s)-1] = ''
удаляете последний элемент.
Редактировать:
Здесь есть еще одно решение, которое будет работать быстрее. Вместо того, чтобы звонить s[strlen(s)-1]
каждый раз, вы можете просто отслеживать начальный n=strlen(s);
номер , также удалив -'0'
, потому ASCII
что коды для номеров начинаются 48
, поэтому они находятся в правильном положении для проверки делимости на 3. Благодаря @chux-ReinstateMonica
. Вот код:
char* truncateString(char* s)
{
int n = strlen(s);
int flag = 1;
while (n != 0 amp;amp; flag != 0){
if ((s[0]) % 3 == 0){
s ;
n--;
}
else if ((s[n-1]) % 3 == 0)
s[--n] = '';
else if (((s[n-1]) (s[0])) % 3 == 0)
{
s ;
n--;
s[--n] = '';
}
else
flag = 0;
}
return s;
}
Комментарии:
1. Код без объяснения проблем или того, как они были исправлены, не является хорошим ответом.
2. Я написал объяснение в конце
3. вау, спасибо тебе ! Я наконец-то лучше понимаю это!
4. @chux-переустановите приложение, вы правы. Я исправил ответ. Спасибо
5. robbinc91, Примечание:
s ; s[strlen(s)-1] = '';
имеет недостатки в производительности. Этот код проходит вниз по строке, чтобы найти ее длину., делая это решение O(n*n). Серьезное воздействие с большойn
. Отслеживаниеn
сэкономило бы много времени.