【问题标题】:Replacing substrings in C without using string library functions在不使用字符串库函数的情况下替换 C 中的子字符串
【发布时间】:2015-07-18 16:45:23
【问题描述】:

虽然这段代码很可怕,而且我显然错误地解决了这个问题,但这段代码仍然有效(目前)。我想搞砸它,但我真的不知道我在这里做错了什么。目标是不使用任何内置函数,将字符串“This is a test”替换为“gho”以拼出“This is a ghost”。

int main(int argc, const char * argv[]) {

    char *s = "This is a test";
    char *newstring = malloc(strlen(s));


    for (int i = 0 ; s[i] != '\0' ; i++){
        if (s[i] == 't' && s[i+1] == 'e') {
            newstring[i] = 'g';}
        else if (s[i] == 'e' && s[i+1] == 's') {
            newstring[i] = 'h';}
        else if (s[i] == 's' && s[i+1] == 't') {
            newstring[i] = 'o';
        }
        else if (s[i] == 't') {
            newstring[i] = 's';
        }
        else {
            newstring[i] = s[i];
        }
        }
    printf("%st",newstring);


    return 0;
}

我的问题是我不知道如何将字符附加到 C 中的新字符串中,以便在替换单个字符的同时保持原始字符串的完整性。

【问题讨论】:

  • 您的问题是什么?是“如何将字符附加到 C 中的新字符串”?
  • @user3121023 这是真的,我已经在我的代码中调整了它。在我的打印语句中,我必须在末尾手动添加一个“t”;我该怎么做才能避免这样做?我尝试在最后一个 else if 语句下添加代码来说明这一点,除了 newstring[i] = 's';新字符串[i+1] = 't'。那没用。
  • 我会将其拆分为三个函数:“在字符串中查找“te””、“在字符串中的某个位置写入“gho””和“将一个字符串的一部分复制到另一个字符串上。通过拆分它,我敢打赌复杂性会立即下降。
  • @MooingDuck 听起来是解决它的好方法。我的问题是我对 C 完全陌生,不知道如何实现它!关于将一个字符串的一部分“复制”到另一个字符串,我在上面通过将索引值设置为彼此来做到这一点。不确定如何在字符串中搜索多个字符并注意它们存在于哪些索引处。我基本上可以说“将导致'te'的字符串部分复制到新字符串”。然后,“忽略'te'并插入'gho'”。然后,“将 'te' 之后的所有内容复制到新字符串中”。它只是在实际执行它......
  • 您声明代码不能使用任何系统函数,但发布的代码使用 strlen()、malloc() 和 printf() 顺便说一句:C 没有任何内置功能来执行任何输入/输出。这就是为什么几乎总是需要像 stdio.h 和 stdlib.h 这样的库。 C 没有任何内置的能力来执行任何字符串操作。这就是为什么几乎总是需要像 string.h 这样的库。

标签: c string replace append


【解决方案1】:
char *s = "This is a test";
int len = 0;

while(s[len++]);//strlen(s) + 1
for (int i = 0 ; s[i] != '\0' ; i++){
    if (s[i] == 't' && s[i+1] == 'e') {//count "te"
        ++len;
        ++i;
    }
}

char *newstring = malloc(len);
int j = 0;
for (int i = 0 ; s[i] != '\0' ; i++){
    if (s[i] == 't' && s[i+1] == 'e') {
        newstring[j++] = 'g';
        newstring[j++] = 'h';
        newstring[j++] = 'o';
        ++i;
    } else {
        newstring[j++] = s[i];
    }
}
newstring[j] = '\0';
puts(newstring);
free(newstring);

【讨论】:

  • 根据 OP,不能使用“内置”函数(来自库的函数),因此不允许使用 malloc() 和 free()。 OP 如何向用户显示任何内容是一个问题,因为“puts()”是库中的“内置”函数之一。
  • @user3629249 OP 使用了malloc。也可以使用VLA。
  • 我认为 OP 可能没有完全理解给他们的限制。在任何情况下,都可以在计算需要多少字节后即时定义数组。
  • 我觉得用malloc没问题,我不是很懂“免费”的概念。我想我需要更多地阅读指针。
  • @karansatia 它本身不是pointers,而是您使用malloccalloc 创建的内存块,当您使用完内存后,您需要对free 负责.唯一起作用的位置指针是malloccalloc 都将起始地址返回到新创建的内存块。内存地址存储在指针中。 (例如int *array = malloc (20 * sizeof (int));创建一个内存块来保存20个整数,该块的起始地址存储在array中)。完成array后,您必须free (array);才能将内存返回给系统。
【解决方案2】:

我们应该识别出你想做的事情的模式。首先,记住可以像这样填写新数组是一个有用的技巧:

int num = 0;
int buf[256];

buf[num++] = 123;
buf[num++] = 456;
buf[num++] = 789;

这是一个简写。行:

buf[num++] = 123;

提供等效的行为:

buf[num] = 123;
++num;

那么我们想在这里做什么?我们想要创建一个与原始字符串相同的新字符串,只是它将“te”替换为“gho”。那么这个怎么样?

#include <stdio.h>

int main(int argc, const char * argv[]) 
{
    const char *s = "This is a test";
    int i = 0;
    int new_len = 0;

    // We don't know what the final size of the string will be, so
    // let's make one that's generally large enough. Can do more
    // elaborate things here if you want a really robust solution.
    char new_string[256] = {0};

    // For each character in the string:
    for (i=0; s[i] != '\0'; ++i)
    {
        if (s[i] == 't' && s[i+1] == 'e')
        {
            // If we find "te", add "gho".
            new_string[new_len++] = 'g';
            new_string[new_len++] = 'h';
            new_string[new_len++] = 'o';

            // ... and skip one character to ignore both the 't' and the 'e'.
            ++i;
        }
        else
        {
            // Otherwise just add the same character.
            new_string[new_len++] = s[i];
        }
    }

    // Add the null terminator at the end of our new string.
    new_string[new_len] = '\0';

    // Output the new string.
    printf("%s\n", new_string);
}

【讨论】:

  • 非常努力,但您应该重新审视问题中不使用任何内置函数的部分(强调原文)。我打赌你能做到。
  • 抱歉,根据 OP,不能使用“内置”功能 I.E.库提供的那些函数。所以不允许'string.h'
  • 多哈。我错过了那部分。我希望至少允许printf
  • 大家好!我可以使用 printf!
  • 很好的解决方案@Ike。快速提问:当你增加 [new_len++] 时,跳过下一个字符有什么作用?假设我们在(在原始字符串中)找到“te”的索引是 4 和 5。这意味着在 new_string 中的索引 4、5 和 6 处,我们分别填充了 g、h 和 o。跳过原始字符串中的索引“6”有什么作用?我们不是只需要转到接下来的两个索引并添加它们(s 和 t)吗?为什么我们需要跳过第 6 个索引(实际上不是第 6 个索引,只是在我的坏例子中)。
【解决方案3】:
int myStrLen( char * );


int myStrlen( char *testStr )
{
    int rtnCount;

    for( rtnCount = 0; testStr[rtnCount]; rtnCount++ ) {;}

    return( rtnCount );
} // end function: myStrlen

其他字符串函数可以用类似的方式实现。

然后可以像这样使用“自制”字符串函数:

// get length of original string
int oldStringLen = myStrLen( s );

// provide room on the stack for the new string
char newString[oldStringLen+2] = {'\0'};

// search for occurrence of string to be replaced
char * targetString = myStrStr( s, "test" );
if( NULL == targetString )
{ // then target string not found
    // handle error??
    return( -1 );
}

// implied else, target string found in 's'

// copy first part of original string
myStrNCpy( newString, s, (targetString - s) +1 );

// append the replacement string
myStrCat( newString, "ghost" );

// append remainder of original string
myStrCat( newString, &targetString[4] );

代码是否需要一直查找原始字符串 其他可能的替代品?

当然,如何向用户显示结果 可能很“有趣”,因为 C 没有执行任何 I/O 的能力 不使用 stdio.h 库之类的东西

【讨论】:

  • char newString[oldStringLen+2] = {'\0'}; 语法无效。 可变大小的对象可能没有被初始化
猜你喜欢
  • 2015-02-12
  • 2013-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-29
  • 2018-07-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多